-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Constrainted datetime based on timezone offset / UTCDateTime #8088
Comments
I think we could make use of annotated-types' |
I'm happy to add this via full support for the annotated-types type. @bram-tv by the way, you can use custom errors to make the errors nicer. |
Any interest in opening a PR to add support for this? |
I would appreciate it if @sydney-runkle , @bram-tv , @samuelcolvin could provide me with some context regarding the implementation of this Feature. Specifically, I am interested in understanding the various Cases that need to be covered and the desired outcomes we aim to achieve by implementing these constraint types. |
@Zidane786 @samuelcolvin @bram-tv It would be great if this constraint will support not only specifying one specific timezone, but also specifying a UTC offset range or a list of supported timezones. Example of use: postgres supports timezones with UTC offset from -12:00 to +13:00. If we pass a datetime with a utc offset that goes beyond this limit, we get an error. For myself, so far I've done something like this from datetime import datetime, timedelta
from typing import Annotated
from pydantic import AfterValidator
def check_timezone_utcoffset_range(v: datetime) -> datetime:
utc_offset = v.utcoffset()
if utc_offset is not None and (
utc_offset < timedelta(days=-1, seconds=43200)
or utc_offset > timedelta(seconds=46800)
):
raise ValueError("timezone utc offset should be in range from -12:00 to +13:00")
return v
DatetimeRestrictedUtcOffset = Annotated[
datetime, AfterValidator(check_timezone_utcoffset_range)
] Another approach would be to add constraint support to pydantic with a specific timezone, and add to pydantic extra types a datetime type for postgres that verifies that the timezone is correct |
At PyCon2024, taking a look at this. |
We're looking at adding support for the Also happy to chat in person if you'd like, we're in room 321. |
Here's the approach we talked about :). This is a super cool way to combine from pydantic import TypeAdapter, GetCoreSchemaHandler
from typing_extensions import Annotated
from datetime import datetime
from pydantic._internal._core_utils import pretty_print_core_schema
from dataclasses import dataclass
from typing import Any
from pydantic_core import CoreSchema, core_schema
from functools import partial
def my_validator_function(tz_constraint: str, value: datetime, handler):
# pre logic
validated_dt = handler(value)
# post logic
return validated_dt
@dataclass(frozen=True)
class MyDatetimeValidator:
tz_constraint: str
def __get_pydantic_core_schema__(self, source_type: Any, handler: GetCoreSchemaHandler) -> CoreSchema:
return core_schema.no_info_wrap_validator_function(
partial(my_validator_function, self.tz_constraint), handler(source_type)
)
ta = TypeAdapter(Annotated[datetime, MyDatetimeValidator('UTC')])
print(pretty_print_core_schema(ta.core_schema))
"""
{
'type': 'function-wrap',
'function': {
'type': 'no-info',
'function': functools.partial(<function my_validator_function at 0x104a73d90>, 'UTC')
},
'schema': {'type': 'datetime', 'microseconds_precision': 'truncate'}
}
"""
my_dt = ta.validate_python(datetime.now())
print(my_dt)
# > 2024-05-20 14:42:15.066963 |
Offsets are not timezones, so I'd oppose such a change.
...and offsets are very very very rarely the right solution to a problem, making an Offset type into an attractive nuisance of an interface. I'd oppose adding one to
IMO this is a nasty bug in Postgres; there are timezones with a +14 UTC offset, and other historical examples still might need to be represented in a database. I recommend reporting a bug to your database vendor. More generally, supporting only some timezones is somewhere between an attractive nuisance and a code smell. If you really really need to, you can use a union of types: |
Initial Checks
Description
This is basically the same request as #4385 but that was closed as duplicate of #4330 (which is closed now too) but several things have changed since then so creating a new issue.
Summary of the request: being able to add a constraint on the timezone offset of an AwareDatetime.
Support for constraining the timezone offset was added in pydantic-core in May 2023 with
pydantic/pydantic-core#653
So far I can see two ways to achieve this:
tz_constraint
option from pydantic-core by extending from AwareDatetime and overriding__get_pydantic_core_schema__
,Example code
AfterValidator
to do the extra validationExample code
In both cases there is validation error (as expected), and the error from pydantic-core is superior.
Now back to the future request: Make it easier to use the
tz_constraint
option of pydantic-core to restrict the tz offset of a datetime.Could be via:
Field
to supporttz_constraint
?Affected Components
.model_dump()
and.model_dump_json()
model_construct()
, pickling, private attributes, ORM modeThe text was updated successfully, but these errors were encountered: