You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Noda Time has "date adjusters" and "time adjusters". Some adjustments are discussed at the bottom of the recipes page.
These are essentially functions which take an argument of either LocalTime or LocalDate, adjust it in some way, and then return the adjusted instance.
They can be user-defined, or selected from predefined adjusters for dates or times.
They are intended to be used by passing the adjuster to a .With() method on instances of the following types:
Date adjusters
LocalDate
LocalDateTime
OffsetDate
OffsetDateTime
Time adjusters
LocalTime
LocalDateTime
OffsetTime
OffsetDateTime
In Python, the natural inclination would be to treat "date adjusters" as Callable[[LocalDate], LocalDate] and "time adjusters" as Callable[[LocalTime], LocalTime].
But an issue arises when we come to types which provides overloads for both types of adjuster, namely LocalDateTime and OffsetDateTime.
The problem in Python is that we cannot distinguish between Callable[[LocalDate], LocalDate] and Callable[[LocalTime], LocalTime] at runtime. You cannot do something like this:
classLocalDateTime:
defwith_(self, adjuster: Callable[[LocalDate], LocalDate] |Callable[[LocalTime], LocalTime]) ->LocalDateTime:
ifisinstance(adjuster, Callable[[LocalDate], LocalDate]): # TypeError: Subscripted generics cannot be used with class and instance checks
...
else:
...
There are probably some third party libraries which can do single dispatch based on type annotations, but I'm not interested in adding a dependency just for that.
So what options do we have here? I think there are two:
Rather than Callable[[LocalDate], LocalDate] and Callable[[LocalTime], LocalTime], port "adjusters" as discrete types which implement __call__ (or some other abstract method). This would allow for isinstance checks at runtime, and would allow us to keep a consistent .with_(adjuster) interface for all types which may be "adjusted".
Rather than adding .with_() methods and overloads, just have separate methods for different types of adjustment. For example, .with_date_adjuster() and .with_time_adjuster. Not the catchiest or most "fluent", but they are explicit. And this way you can keep the type annotations as Callable, which avoids the penalty of class instantiation from the first option, and potentially allows for plain old functions or even lambdas to be passed. It also avoids the eyesore of a .with_() method.
I find option 2 more appealing. The most important thing is to be consistent with naming across the various types, and to some day get around to documenting this and other differences between Noda Time and Pyoda Time!
The text was updated successfully, but these errors were encountered:
Noda Time has "date adjusters" and "time adjusters". Some adjustments are discussed at the bottom of the recipes page.
These are essentially functions which take an argument of either
LocalTime
orLocalDate
, adjust it in some way, and then return the adjusted instance.They can be user-defined, or selected from predefined adjusters for dates or times.
They are intended to be used by passing the adjuster to a
.With()
method on instances of the following types:LocalDate
LocalDateTime
OffsetDate
OffsetDateTime
LocalTime
LocalDateTime
OffsetTime
OffsetDateTime
In Python, the natural inclination would be to treat "date adjusters" as
Callable[[LocalDate], LocalDate]
and "time adjusters" asCallable[[LocalTime], LocalTime]
.But an issue arises when we come to types which provides overloads for both types of adjuster, namely
LocalDateTime
andOffsetDateTime
.In C# this looks roughly like:
The problem in Python is that we cannot distinguish between
Callable[[LocalDate], LocalDate]
andCallable[[LocalTime], LocalTime]
at runtime. You cannot do something like this:There are probably some third party libraries which can do single dispatch based on type annotations, but I'm not interested in adding a dependency just for that.
So what options do we have here? I think there are two:
Callable[[LocalDate], LocalDate]
andCallable[[LocalTime], LocalTime]
, port "adjusters" as discrete types which implement__call__
(or some other abstract method). This would allow forisinstance
checks at runtime, and would allow us to keep a consistent.with_(adjuster)
interface for all types which may be "adjusted"..with_()
methods and overloads, just have separate methods for different types of adjustment. For example,.with_date_adjuster()
and.with_time_adjuster
. Not the catchiest or most "fluent", but they are explicit. And this way you can keep the type annotations asCallable
, which avoids the penalty of class instantiation from the first option, and potentially allows for plain old functions or even lambdas to be passed. It also avoids the eyesore of a.with_()
method.I find option 2 more appealing. The most important thing is to be consistent with naming across the various types, and to some day get around to documenting this and other differences between Noda Time and Pyoda Time!
The text was updated successfully, but these errors were encountered: