Python datetime.utcnow() returning incorrect datet

2019-01-07 20:49发布

问题:

datetime.utcnow()

This call is returning an incorrect datetime, delayed from UTC/GMT by 1 hour (check in: http://www.worldtimeserver.com/current_time_in_UTC.asp).

Is it working like it should be?

For example, it's returning, right now:

2015-02-17 23:58:44.761000.

Current UTC time is: 00:58, not 23:58

回答1:

datetime.utcnow() uses OS provided values.

datetime.utcnow() uses gettimeofday(2) or time.time() on Python 2 (and gmtime(3) to convert the result into broken-down time).

time.time() uses gettimeofday(2), ftime(3), time(2). Newer CPython versions may use clock_gettime(2), GetSystemTimeAsFileTime().

You could check the self-consistency as follows:

#!/usr/bin/env python
import time
from datetime import datetime, timedelta

print(datetime.utcnow())
print(datetime(1970, 1, 1) + timedelta(seconds=time.time()))
print(datetime(*time.gmtime()[:6]))

Here's (non-tested) code that calls GetSystemTimeAsFileTime() on Windows based on CPython source:

#!/usr/bin/env python
import ctypes.wintypes
from datetime import datetime, timedelta

def utcnow_microseconds():
    system_time = ctypes.wintypes.FILETIME()
    ctypes.windll.kernel32.GetSystemTimeAsFileTime(ctypes.byref(system_time))
    large = (system_time.dwHighDateTime << 32) + system_time.dwLowDateTime
    return large // 10 - 11644473600000000

print(datetime(1970, 1, 1) + timedelta(microseconds=utcnow_microseconds()))

Here's code that calls clock_gettime() on Python 2.



回答2:

I know I am tremendously late in replying to this.

I have tried doing this recently and therefore I suggest using datetime.now() instead of datetime.utcnow(). For my simple application that works fine.



回答3:

Problem only occurs with utc time (Python3).

e.g. System time:

$ date

Wed Jul 15 10:44:26 BST 2015

Python time correct when using datetime.now():

>>> datetime.now()

datetime.datetime(2015, 7, 15, 10, 44, 30, 775840)

...But incorrect by one hour when using datetime.utcnow():

>>> datetime.utcnow()

datetime.datetime(2015, 7, 15, 9, 44, 32, 599823)

UTC's problem is it doesn't know my timezone.

You have to tell it, with the help of a timezone module called pytz:

>>> import pytz
>>> mytz = pytz.timezone('Europe/London')
>>> pytz.utc.localize(datetime.utcnow(), is_dst=None).astimezone(mytz)

datetime.datetime(2015, 7, 15, 11, 3, 43, 688681, tzinfo=<DstTzInfo 'Europe/London' BST+1:00:00 DST>)

References:

pytz - Converting UTC and timezone to local time

https://opensourcehacker.com/2008/06/30/relativity-of-time-shortcomings-in-python-datetime-and-workaround/

http://sweemengs-tech-world.blogspot.co.uk/2010/05/get-correct-datetime-value-for-python.html

http://bugs.python.org/issue5094)