from whenever import ( # For the "UTC everywhere" case UTCDateTime, # Simple localization sans DST OffsetDateTime, # Full-featured IANA timezones ZonedDateTime, # The local system timezone LocalDateTime, # Detached from any timezones NaiveDateTime, ) Why so many different types? Doesn't ZonedDateTime cover all of the other use cases?
First, there's a fundamental difference between naïve datetimes and timezone-aware datetimes. Try to combine them in one representation, and you are guaranteed to end up with a broken datetime library that spawns endless blog posts attacking it.
Second, there's a more subtle distinction between a datetime which has a known timezone and one which merely has a known instantaneous offset. A timezone is essentially a naïve date time -> tzoffset, albeit one whose values for future dates tends to be surprisingly unrobust. Among the offset-only date times, UTC is a very common case that deserves its own alias.
Finally, separating the local-tz datetime from other tz-aware datetimes can be very useful, for if the user changes their local timezone, then a local-tz datetime usually wants to switch the timezone it is using as well.