为什么datetime.now()和datetime.today()在我的电脑上显示UTC时间而不是当地时间?

时间:2017-11-29 22:44:33

标签: python python-3.x datetime

datetime.now()datetime.today()在我的计算机上以UTC格式返回时间,即使the documentation表示他们应该返回当地时间。

这是我运行的脚本:

#!/usr/bin/python

import time
import datetime

if __name__ == "__main__":
   print(datetime.datetime.now())
   print(datetime.datetime.today())
   print(datetime.datetime.fromtimestamp(time.time()))

以及输出:

2017-11-29 22:47:35.339914
2017-11-29 22:47:35.340399
2017-11-29 22:47:35.340399

运行date之后的输出是:

Wed, Nov 29, 2017  3:47:43 PM

为什么我的安装返回UTC时间?
我能做些什么让这些功能返回当地时间?

PS 我们在MST,这是UTC-7。

PS 2 我意识到有一些方法可以将UTC时间转换为本地时间,例如Convert a python UTC datetime to a local datetime using only python standard library?中所述的方法。但是,我试图了解基本问题的原因,而不是在我自己的代码中寻找修补问题的方法。

回应@jwodder的评论:

执行

的输出
print(time.altzone)
print(time.timezone)
print(time.tzname)

是:

-3600
0
('Ame', 'ric')

3 个答案:

答案 0 :(得分:6)

正如您在your answer中所述,TZ环境变量是此处的关键。在unix类型的系统上,这支持更多友好的"价值如"美国/太平洋"或者,确实," America / Denver",但在Windows上,它并没有。虽然它在Windows上不可用,但documentation for the time.tzset function描述了您需要设置TZ以获得所需内容的格式。它不......很漂亮。但它的确有效:

C:\Users\zorb>set TZ=MST+07MDT,M3.2.0,M11.1.0
C:\Users\zorb>python.exe
>>> import time
>>> time.tzname
('MST', 'MDT')
>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2018, 2, 9, 16, 27, 7, 164062)

(这是太平洋时间的15:27。)这种格式的结构是:

  • 标准时间缩写(MST)
  • 标准时间的UTC偏移量,以小时(+07)
  • 表示
  • 夏令时缩写
  • 白天时间开始时(见下文)
  • 白天时间结束时(见下文)

日光时间开始和结束的格式为:

  • M(适用于"基于月份")
  • 月份编号 - 3月/ 3月或11月/ 11月,在这种情况下。
  • 每月的一周 - 1到5,表示下面命名的第1天到第5天。
  • 星期日 - 星期日0星期六星期六

还有一些选项可以指定日光时间开始和结束的时间(但默认为02:00:00,在这种情况下是不必要的)和日光时间的偏移量(但默认为1小时,所以也没有必要)。

(编辑)事实证明这实际上是一个glibc功能,而不是直接的python功能。 glibc docs中的更详细信息。

答案 1 :(得分:2)

最初,它似乎是使用cygwin引起的问题。

Cygwin shows UTC time instead of local time的问题有助于进一步将问题与cygwin中环境变量TZ的价值隔离开来。

更新的脚本:

import time
import datetime

if __name__ == "__main__":
   print(datetime.datetime.now())
   print(datetime.datetime.today())
   print(datetime.datetime.fromtimestamp(time.time()))
   print(time.altzone)
   print(time.timezone)
   print(time.tzname)

在Windows CMD shell下运行时输出,其中未设置TZ

"D:\Program Files\Python35\python.exe" test.py
2017-11-30 09:39:47.236798
2017-11-30 09:39:47.236799
2017-11-30 09:39:47.236799
21600
25200
('Mountain Standard Time', 'Mountain Daylight Time')

在cygwin bash shell下运行时的输出,其中TZ设置为"America/Denver"

 /cygdrive/D/Program\ Files/Python35/python.exe test.py
2017-11-30 16:39:45.419884
2017-11-30 16:39:45.419884
2017-11-30 16:39:45.419884
-3600
0
('Ame', 'ric')

它设置为"America/Denver"。我执行时

env TZ="" /cygdrive/D/Program\ Files/Python35/python.exe test.py

我得到了更明智的结果:

2017-11-30 09:56:08.643368
2017-11-30 09:56:08.643368
2017-11-30 09:56:08.643368
21600
25200
('Mountain Standard Time', 'Mountain Daylight Time')

当我在windows CMD shell中将环境变量TZ设置为"America/Denver"时,我获得与在cygwin shell中运行时相同的输出。

我不清楚Python如何使用环境变量TZ以及正确的值是什么。

答案 2 :(得分:1)

我认为在Windows上使用glibc时间和时区库时会出现一些奇怪的行为。我最近开始在python和emacs中注意到这种行为。

最好的办法是将TZ设置为最佳答案中描述的“丑陋”版本,因为这似乎解决了python和emacs中的问题,并且在cygwin中也能正常工作。

我尝试的另一种解决方法是确保TZ环境变量 NOT 设置。以下说明了纽约时间10:18左右的问题。我在Windows上使用cygwin或CMD获得了类似的结果。 Emacs使用current-time-string函数说明了同样的问题,这表明它是一个glibc问题,或者至少是一些python和emacs都在使用的库。有趣的是,cygwin中的date命令给出了正确的结果,TZ设置为“America / New York”,但如果TZ未设置则不正确。

总结:Windows上的某些内容(例如,python,emacs)似乎不接受TZ的“America / New_York”,而某些内容(例如,cygwin)确实接受它。在东部时间使用EST+05EDT,M4.1.0,M10.5.0之类的东西(或适当的丑陋等同物)可以使用。

$ echo $TZ
America/New_York

$ python -i
Python 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2018, 5, 14, 15, 38, 6, 174073)
>>> datetime.datetime.now()
datetime.datetime(2018, 5, 14, 15, 38, 57, 141708)
>>> quit()

$ export TZ=

$ python -i
Python 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2018, 5, 14, 10, 38, 41, 102117)