12

当 Python 在 Windows 下运行时,如果在 Python 实例的生命周期内更改了时区,则 time.localtime 不会报告正确的时间。在 Linux 下,总是可以运行 time.tzset 来缓解此类问题,但在 Windows 中似乎没有等效项。

有没有办法解决这个问题而不做一些荒谬的事情,哦,我不知道......

#!/bin/env python
real_localtime = eval(subprocess.Popen(
    ["python","-c", "import time;repr(time.localtime())"],
    stdout=subprocess.PIPE).communicate()[0])
4

3 回答 3

8

更合理的解决方案是将 Kernel32 的GetLocalTime与 pywin32 或 ctypes 一起使用。任何时区更改都会立即反映出来。

import ctypes
class SYSTEMTIME(ctypes.Structure):
    _fields_ = [
        ('wYear', ctypes.c_int16),
        ('wMonth', ctypes.c_int16),
        ('wDayOfWeek', ctypes.c_int16),
        ('wDay', ctypes.c_int16),
        ('wHour', ctypes.c_int16),
        ('wMinute', ctypes.c_int16),
        ('wSecond', ctypes.c_int16),
        ('wMilliseconds', ctypes.c_int16)]

SystemTime = SYSTEMTIME()
lpSystemTime = ctypes.pointer(SystemTime)
ctypes.windll.kernel32.GetLocalTime(lpSystemTime)
print SystemTime.wHour, SystemTime.wMinute 
于 2010-12-05T23:44:02.530 回答
4

不,如果不做你所做的,这是无法解决的。这有点荒谬,但如果您需要 Windows 中的正确时区,并且在程序执行过程中发生了变化,则必须这样做。

这可能不是错误(文档非常清楚该tzset()功能仅在 Unix 上可用)。它更可能是 Windows 中的一个弱点,它阻止了 Python 程序员tzset()在它下实现。您可以请求增强功能,但自 Python 2.3(7 年)以来一直如此,因此不太可能真正实现。

于 2010-12-05T21:21:07.730 回答
4

最重要的是,对于 VC 版本 6,tzset() 不能正常工作。但是,对于 VC 版本 8,tzset() 现在可以正常工作(我认为它可能也在版本 7 中工作,但我没有那个版本可以检查)。

所以现在要做的就是在源代码中启用 HAVE_WORKING_TZSET并重新编译(和测试)。

根据我的经验,TZ 不同设置的所有功能需求都需要有一个有效的 tzset()。每次更改 C Lang TZ var -或- Windows TIME_ZONE_INFORMATION 时都必须调用 tzset()。这在 VC 版本 6 中是不可能的,这就是未启用 HAVE_WORKING_TZSET 的原因(但现在应该至少适用于 VC 版本 8 及更高版本)。

顺便提一句。对于我所做的所有日期/时间的事情,我总是有一个 SetUtcTime() 和 UnsetUtcTime() ,它将 TZ 设置为 GMT 并相应地调用 tzset() 。我也有临时设置到另一个时区的功能。这是正确执行此操作的唯一方法!在多年的经验中,我可以说其他任何事情都是麻烦的。而且 calendar.timegm() 不正确。使用 tzset()。

这是它现在正在工作的证明(所以去 bug 作者修复 windows 代码):

(我是从另一台计算机上输入的,所以希望没有拼写错误,但这是我的重点,而不是代码)。


注意:下面都是 PYTHON(我从 python 的 ctype 接口调用 C 语言) 注意:因为我在这里通过 DLL 边界设置 TZ 和线程本地和所有这些废话,它不能用作解决方法。必须重新启用 HAVE_WORKING_TZSET。

import time
from ctypes import *

dTime = time.time ()
nTime = int (dTime)
intTime = c_int (nTime)

print time.ctime (dTime)
print c_char_p (cdll.msvcrt.ctime (addressof (intTime))).value

-> ... 21:02:40 ...(python)
-> ... 21:02:40 ...(C 语言)

cdll.msvcrt._putenv ('TZ=GMT')
cdll.msvcrt._tzset ()

(通常会调用 time.tzset() 并调用 inittimezone () 来更新 python 的时区变量)

print time.ctime (dTime)
print c_char_p (cdll.msvcrt.ctime (addressof (intTime))).value

-> ... 21:02:40 ... (python)
-> ... 11:02:40 ... (C lang) <- 底层 VC 版本 8 正在运行!

(因此,如果为(版本 8 及更高版本)定义了 HAVE_WORKING_TZSET,您将得到:)

-> ... 11:02:40 ...(python)
-> ... 11:02:40 ...(C 语言)


只需检查源代码即可了解我的意思。

我用最新的python'2.0'系列检查了这一点:刚刚2.7.2。

于 2011-08-07T11:48:08.340 回答