Add aware local time support to datetime module
[I've got no response from python-ideas, so I am forwarding to python-dev.] With addition of fixed offset timezone class and the timezone.utc instance [0], it is easy to get UTC time as an aware datetime instance:
datetime.now(timezone.utc) datetime.datetime(2010, 8, 3, 14, 16, 10, 670308, tzinfo=datetime.timezone.utc)
However, if you want to keep time in your local timezone, getting an aware datetime is almost a catch 22. If you know your timezone UTC offset, you can do
EDT = timezone(timedelta(hours=-4)) datetime.now(EDT) datetime.datetime(2010, 8, 3, 10, 20, 23, 769537, tzinfo=datetime.timezone(datetime.timedelta(-1, 72000)))
but the problem is that there is no obvious or even correct way to find local timezone UTC offset. [1] In a comment on issue #5094 ("datetime lacks concrete tzinfo implementation for UTC"), I proposed to address this problem in a localtime([t]) function that would return current time (or time corresponding to the optional datetime argument) as an aware datetime object carrying local timezone information in a tzinfo set to an appropriate timezone instance. This solution is attractive by its simplicity, but there are several problems: 1. An aware datetime cannot carry all information that system localtime() supplies in a time tuple. Specifically, the is_dst flag is lost. This is not a problem for most applications as long as timezone UTC offset and timezone name are available, but may be an issue when interoperability with the time module is required. 2. Datetime's tzinfo interface was designed with the idea that <2010-11-06 12:00 EDT> + <1 day> = <2010-11-07 12:00 EST>, not <2010-11-07 12:00 EDT>. It other words, if I have lunch with someone at noon (12:00 EDT) on Saturday the day before first Sunday in November, and want to meet again "at the same time tomorrow", I mean 12:00 EST, not 24 hours later. With localtime() returning datetime with tzinfo set to fixed offset timezone, however, localtime() + timedelta(1) will mean exactly 24 hours later and the result will be expressed in an unusual for the given location timezone. An alternative approach is the one recommended in the python manual. [3] One could implement a LocalTimezone class with utcoffset(), tzname() and dst() extracting information from system mktime and localtime calls. This approach has its own shortcomings: 1. While adding integral number of days to datetimes in business setting, it is natural to expect automatic timezone adjustments, it is not as clearcut when adding hours or minutes. 2. The tzinfo.utcoffset() interface that expects *standard* local time as an argument is confusing to many users. Even the "official" example in the python manual gets it wrong. [4] 3. datetime(..., tzinfo=LocalTimezone()) is ambiguous during the "repeated hour" when local clock is set back in DST to standard time transition. As far as I can tell, the only way to resolve the last problem is to add is_dst flag to the datetime object, which would also be the only way to achieve full interoperability between datetime objects and time tuples. [5] The traditional answer to call for improvement of timezone support in datetime module has been: "this is upto 3rd parties to implement." Unfortunately, stdlib is asking 3rd parties to implement an impossible interface without giving access to the necessary data. The impossibility comes from the requirement that dst() method should find out whether local time represents DST or standard time while there is an hour each year when the same local time can be either. The missing data is the system UTC offset when it changes historically. The time module only gives access to the current UTC offset. My preference is to implement the first alternative - localtime([t]) returning aware datetime with fixed offset timezone. This will solve the problem of python's lack of access to the universally available system facilities that are necessary to implement any kind of aware local time support. [0] http://docs.python.org/dev/library/datetime.html#timezone-objects [1] http://bugs.python.org/issue1647654 [2] http://bugs.python.org/issue5094#msg106997 [3] http://docs.python.org/library/datetime.html#tzinfo-objects [4] http://bugs.python.org/issue9063 [5] http://bugs.python.org/issue9004
On Wed, Aug 4, 2010 at 19:46, Alexander Belopolsky <alexander.belopolsky@gmail.com> wrote:
[I've got no response from python-ideas, so I am forwarding to python-dev.]
With addition of fixed offset timezone class and the timezone.utc instance [0], it is easy to get UTC time as an aware datetime instance:
datetime.now(timezone.utc) datetime.datetime(2010, 8, 3, 14, 16, 10, 670308, tzinfo=datetime.timezone.utc)
However, if you want to keep time in your local timezone, getting an aware datetime is almost a catch 22. If you know your timezone UTC offset, you can do
EDT = timezone(timedelta(hours=-4)) datetime.now(EDT) datetime.datetime(2010, 8, 3, 10, 20, 23, 769537, tzinfo=datetime.timezone(datetime.timedelta(-1, 72000)))
but the problem is that there is no obvious or even correct way to find local timezone UTC offset. [1]
In a comment on issue #5094 ("datetime lacks concrete tzinfo implementation for UTC"), I proposed to address this problem in a localtime([t]) function that would return current time (or time corresponding to the optional datetime argument) as an aware datetime object carrying local timezone information in a tzinfo set to an appropriate timezone instance. This solution is attractive by its simplicity, but there are several problems:
1. An aware datetime cannot carry all information that system localtime() supplies in a time tuple. Specifically, the is_dst flag is lost. This is not a problem for most applications as long as timezone UTC offset and timezone name are available, but may be an issue when interoperability with the time module is required.
2. Datetime's tzinfo interface was designed with the idea that <2010-11-06 12:00 EDT> + <1 day> = <2010-11-07 12:00 EST>, not <2010-11-07 12:00 EDT>. It other words, if I have lunch with someone at noon (12:00 EDT) on Saturday the day before first Sunday in November, and want to meet again "at the same time tomorrow", I mean 12:00 EST, not 24 hours later. With localtime() returning datetime with tzinfo set to fixed offset timezone, however, localtime() + timedelta(1) will mean exactly 24 hours later and the result will be expressed in an unusual for the given location timezone.
An alternative approach is the one recommended in the python manual. [3] One could implement a LocalTimezone class with utcoffset(), tzname() and dst() extracting information from system mktime and localtime calls. This approach has its own shortcomings:
1. While adding integral number of days to datetimes in business setting, it is natural to expect automatic timezone adjustments, it is not as clearcut when adding hours or minutes.
2. The tzinfo.utcoffset() interface that expects *standard* local time as an argument is confusing to many users. Even the "official" example in the python manual gets it wrong. [4]
3. datetime(..., tzinfo=LocalTimezone()) is ambiguous during the "repeated hour" when local clock is set back in DST to standard time transition.
As far as I can tell, the only way to resolve the last problem is to add is_dst flag to the datetime object, which would also be the only way to achieve full interoperability between datetime objects and time tuples. [5]
The traditional answer to call for improvement of timezone support in datetime module has been: "this is upto 3rd parties to implement." Unfortunately, stdlib is asking 3rd parties to implement an impossible interface without giving access to the necessary data. The impossibility comes from the requirement that dst() method should find out whether local time represents DST or standard time while there is an hour each year when the same local time can be either. The missing data is the system UTC offset when it changes historically. The time module only gives access to the current UTC offset.
My preference is to implement the first alternative - localtime([t]) returning aware datetime with fixed offset timezone. This will solve the problem of python's lack of access to the universally available system facilities that are necessary to implement any kind of aware local time support.
For all of the reasons you give above, I think it's a bad idea. :-) You need a proper time zone database to solve these issues, like pytz. Which incidentally solves the ambiguity problem as well. so the solution is pytz. :-) What pytz doesn't have (but dateutil.tz does) is a timezone object that uses the operating systems local timezone data, like /etc/localzone on unix. That could be interesting to include, possibly. Having a fixed time zone offset object for the localtime seems a bad idea. The problem it solves is easy to get around, but the problems created are not. -- Lennart Regebro, Colliberty: http://www.colliberty.com/ Python, Zope, Plone blog: http://regebro.wordpress.com/ Telephone: +33 661 58 14 64
It looks like this response has slipped under my radar. Sorry. On Sun, Aug 8, 2010 at 4:37 AM, Lennart Regebro <regebro@gmail.com> wrote: [skipped description of two alternative solutions] ..
For all of the reasons you give above, I think it's a bad idea. :-)
I did not give any reason for not having access to the information that is readily available through reasonably cross-platform C API. Can you elaborate on what you think is a bad idea?
You need a proper time zone database to solve these issues, like pytz.
Pytz is more ambitious than what I propose. I don't propose adding a timezone database to python or even a functionality to access system timezone database. All I want to add is a method to get aware local time in the system timezone.
Which incidentally solves the ambiguity problem as well. so the solution is pytz. :-)
No, it does not. In order to resolve the ambiguity, pytz adds a non-standard argument to tzinfo methods, but datetime objects don't know how to pass this argument and don't have data to determine its value to begin with.
What pytz doesn't have (but dateutil.tz does) is a timezone object that uses the operating systems local timezone data, like /etc/localzone on unix. That could be interesting to include, possibly. Having a fixed time zone offset object for the localtime seems a bad idea. The problem it solves is easy to get around, but the problems created are not.
This sounds like an argument against my "second alternative." As I explained, my preference is the same. Do you have an opinion on the localtime([t]) alternative?
participants (2)
-
Alexander Belopolsky
-
Lennart Regebro