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
Add aware local time support to datetime module #53736
Comments
See python-dev post for motivation. http://mail.python.org/pipermail/python-dev/2010-August/102842.html I am attaching a patch implementing the proposed method in datetime.py. I will also paste the code below. Note that this is only prototype. Real implementation will use tm_zone and tm_gmtoff components of tm structure on platforms that supply them. @classmethod
def localtime(cls, t=None, isdst=-1):
"""Return local time as an aware datetime object.
If called without arguments, return current time. Otherwise
*t* is converted to local time zone according to the system
time zone database. If *t* is naive (i.e. t.tzinfo is None),
it is assumed to be in local time. In this case, a positive or
zero value for *isdst* causes localtime to presume initially
that summer time (for example, Daylight Saving Time) is or is
not (respectively) in effect for the specified time. A
negative value for *isdst* causes the localtime() function to
attempt to divine whether summer time is in effect for the
specified time.
"""
if t is None:
t = _time.time()
else:
if t.tzinfo is None:
tm = t.timetuple()[:-1] + (isdst,)
t = _time.mktime(tm)
else:
delta = t - datetime(1970, 1, 1, tzinfo=timezone.utc)
t = delta.total_seconds()
tm = _time.localtime(t)
if _time.daylight:
if tm.tm_isdst:
offset = _time.altzone
tzname = _time.tzname[1]
else:
offset = _time.timezone
tzname = _time.tzname[0]
tz = timezone(timedelta(seconds=-offset), tzname)
return cls.fromtimestamp(t, tz) |
Merging nosy lists from issues bpo-1647654 and bpo-2736. If datetime.localtime() is implemented, I argue that the features requested in these two issues will become unnecessary. |
Would anyone like to review this? The Rietveld link works (thanks Martin!) and I would like to get some feedback on the python version before I invest effort into coding this in C. |
Following Anatoly's review, I renamed datetime argument and a local variable, added comments and expanded docstring. I am uploading a new patch: datetime-localtime-proto-1.diff. Martin, I could not figure out how to add the new patch to rietveld and I don't think auto-review feature works. |
Forwarding Rietveld conversation to the tracker. It looks like Forwarded conversation From: <techtonik@gmail.com> I'm not proficient in C and not an expert in datetime issues either, but http://bugs.python.org/review/9527/diff/1568/2704 http://bugs.python.org/review/9527/diff/1568/2704#newcode1420 http://bugs.python.org/review/9527/diff/1568/2704#newcode1421 http://bugs.python.org/review/9527/diff/1568/2704#newcode1435 http://bugs.python.org/review/9527/diff/1568/2704#newcode1437 http://bugs.python.org/review/9527/diff/1568/2704#newcode1438 http://bugs.python.org/review/9527/show ---------- On 2011/01/14 04:30:11, sasha wrote:
I prefer to threat UTC time and timezone separately. My API wannabe: global.time() - returns value that can be printed and it will be in UTC Maybe its even better if global.time() returns tuple (UTC time, offset) As you may see I am not interested in DST details etc. All I need is the http://www.atomenabled.org/developers/syndication/atom-format-spec.php#date.constructs In my low-level and non-OOP API it is: global.toiso(global.time(), global.offset()) epoch as an
At first I thought about datetime.toaware(dt), but this description of
dt is a consistent name for datetime parameters in Python manual.
It must be recorded for history if we want to get rid of date/time curse
But these seconds are in UTC. There is no TZ correction. |
I think Tim and Guido had deliberately avoided local timezone awareness when they designed the module. Also, I question whether the proposed API is correct. ISTM that any code that sets the *dst* parameter is guaranteed to be wrong (hardwiring-in a value that will change every few months). Have you studied the solutions used in other libraries and other languages? This path has been well-traveled, so original work may be less helpful than just researching existing solutions. |
On Sat, Jan 29, 2011 at 11:56 PM, Raymond Hettinger
Can you elaborate on this? ISTM that your argument would equally |
LocalTimezone support would be *really* helpful for the email module. It would allow us to have unambiguous semantics for datetime objects representing timestamps exacted from or inserted into email messages (see bpo-665194 for recent discussion). The email module is already trying to handle timestamp translation, and I'd be willing to bet it is buggier than the proposal here. At one point I even started to copy the LocalTimezone class from the docs into the email module. I implemented a naive extension of the current formatdate function instead, but after Alexander's feedback on bpo-665194 I think the naive implementation is not a good idea. |
One important thing to remember is that once a time is in the past, whether or not DST was in effect for that time *is never going to change*. That means converting a DST aware timezone to a fixed offset timezone will work just fine for historical times. It's mainly applications that need to handle times in the *future* (where the DST dates are still subject to change) that have to be aware of the problems when trying to handle DST with fixed offset timezone objects. I think it's sufficient if the documentation pushes developers of such applications towards modules like pytz and dateutil to get access to variable offset tzinfo implementations. |
New changeset df12ce0c96eb by R David Murray in branch 'default': |
This was originally posted on python-dev, but I hope reposting it here will make this issue easier to navigate. """ >>> 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 >>> 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 In a comment on issue bpo-5094 ("datetime lacks concrete tzinfo
An alternative approach is the one recommended in the python manual.
As far as I can tell, the only way to resolve the last problem is to The traditional answer to a call for improvement of timezone support in My preference is to implement the first alternative - localtime([t]) [0] http://docs.python.org/dev/library/datetime.html#timezone-objects -- http://mail.python.org/pipermail/python-dev/2010-August/102842.html |
Two objections have been raised to the proposed datetime.localtime() function:
I attach a prototype patch for a different approach: make datetime.astimezone() method supply local timezone information if no argument is given. This patch also demonstrates that extracting all TZ information that platform may have knowledge of is not trivial. |
One problem I can see with using a fixed offset tzinfo for localtime is that it might confuse people when doing date arithmetic. For example:
While it will give a correct answer as a point in time it will have the wrong time zone offset if run just before a daylight saving transition, which could be just as confusing. I'm not sure how you'd solve this without e.g. importing pytz into the standard library though. |
On Mon, Jun 11, 2012 at 11:18 PM, James Henstridge <report@bugs.python.org> wrote:
Yes, this is the issue that I discussed in my first python-ideas/python-dev post. (See msg162631 above.)
I think my latest proposal will fare slightly better in this scenario. I am now propose implementing local timezone info discovery in datetime.astimezone() method. Obtaining local time will now be a little more verbose: local_time = datetime.now(timezone.utc).astimezone() but (local_time + timedelta(7)).astimezone() will give you correctly adjusted aware datetime seven days later. If we also implement astimezone() for naive instances, we can even support naive local time arithmetics: (datetime.now() + timedelta(7)).astimezone() will produce the same time of day as "now" unless it falls into a non-existing hour.
Importing pytz will not help. Pytz fudges the issue by extending tzinfo methods to accept isdst flag, but there is no place in datetime to store this flag. Doing time calculations in local time is inherently ambiguous in presence of DST. On the other hand, producing tz aware local time from any unambiguous absolute time specification (UTC, time_t, local time + tz offset, etc.) is a well-defined problem which does not have an adequate solution. |
I meant to say "does not have an adequate solution *in the current datetime module*". I think the enhanced datetime.astimezone() method will solve this problem. |
Attached patch implements astimezone() default in both Python and C. |
New changeset 88a5f2730579 by Alexander Belopolsky in branch 'default': New changeset 336c53c1f547 by Alexander Belopolsky in branch 'default': |
New changeset a7237f157625 by Alexander Belopolsky in branch 'default': |
This patch breaks OpenIndiana buildbots. For instance """ Traceback (most recent call last):
File "/export/home/buildbot/64bits/3.x.cea-indiana-amd64/build/Lib/test/support.py", line 1139, in inner
return func(*args, **kwds)
File "/export/home/buildbot/64bits/3.x.cea-indiana-amd64/build/Lib/test/datetimetester.py", line 3286, in test_astimezone_default_eastern
self.assertEqual(local.strftime("%z %Z"), "+0500 EST")
AssertionError: '-0500 EST' != '+0500 EST'
- -0500 EST
? ^
+ +0500 EST
? ^
""" |
Working on this. It turns out tm_gmtoff uses the opposite sign to $ TZ=EST+5 date +%z
-0500 I am rechecking all UTC offset signs. On Fri, Jun 22, 2012 at 3:36 PM, Jesús Cea Avión <report@bugs.python.org> wrote:
> Traceback (most recent call last):
> File "/export/home/buildbot/64bits/3.x.cea-indiana-amd64/build/Lib/test/support.py", line 1139, in inner
> return func(*args, **kwds)
> File "/export/home/buildbot/64bits/3.x.cea-indiana-amd64/build/Lib/test/datetimetester.py", line 3286, in test_astimezone_default_eastern
> self.assertEqual(local.strftime("%z %Z"), "+0500 EST")
> AssertionError: '-0500 EST' != '+0500 EST'
> - -0500 EST
> ? ^
> + +0500 EST
> ? ^
> """
>
>
|
New changeset 0f0e3ec22fce by Alexander Belopolsky in branch 'default': |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: