Заставьте Python реагировать на изменения часового пояса Windows

Когда Python работает под Windows, time.localtime не сообщает правильное время, если часовой пояс был изменен в течение времени жизни экземпляра Python. В Linux всегда можно запустить time.tzset, чтобы решить подобные проблемы, но похоже, что в Windows нет эквивалента.

Есть ли способ исправить это, не делая что-то абсурдное, например, о, я не знаю...

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

person Eric Pruitt    schedule 05.12.2010    source источник
comment
Я могу это подтвердить, для меня это выглядит как ошибка.   -  person AndiDog    schedule 05.12.2010
comment
@Rafe Почему не нужна оценка? Мне нужен кортеж, с которым я могу работать, а не строка.   -  person Eric Pruitt    schedule 06.12.2010


Ответы (3)



Нет, это нельзя исправить, не сделав того, что вы сделали. Это немного абсурдно, но если вам нужен правильный часовой пояс в Windows и он изменился в процессе выполнения программы, то это необходимо сделать.

Вероятно, это не ошибка (в документации ясно сказано, что функция tzset() доступна только в Unix). Скорее всего, это слабость Windows, которая не позволяет программистам Python реализовать tzset() под ней. Вы можете сделать запрос на улучшение функции, но так было с Python 2.3 (7 лет), поэтому маловероятно, что это действительно будет реализовано.

person Rafe Kettler    schedule 05.12.2010
comment
Запрос функции не принесет мне особой пользы, так как я все еще использую 2.X, но я полагаю, что мог бы пощадить кого-нибудь позже. Есть ли способ заставить функцию перезагрузки работать со встроенными модулями? Я пробовал дел время; del sys.modules['time'] без такой удачи, когда старая добрая функция перезагрузки не работала. - person Eric Pruitt; 06.12.2010
comment
@EricPruitt, вероятно, нет, если вы попытаетесь перезагрузиться обычным способом. Ваше решение немного тупое, но оно должно работать - person Rafe Kettler; 06.12.2010
comment
Я думаю, что буду использовать ctypes или pywin32 и попытаюсь использовать GetLocalTime от Kernel32.lib. - person Eric Pruitt; 06.12.2010

Суть в том, что с VC версии 6 функция tzset() не работает должным образом. Однако с VC версии 8 tzset() теперь работает (я думаю, что это может работать и в версии 7, но у меня нет этой версии, чтобы проверить).

Итак, все, что нужно сделать сейчас, это включить HAVE_WORKING_TZSET в исходном коде и повторно скомпилировать (и протестировать).

По моему опыту, все нужные функции для разных настроек TZ должны иметь рабочий tzset(). Вы должны вызывать tzset() каждый раз, когда вы меняете C Lang TZ var -или- Windows TIME_ZONE_INFORMATION. Это было невозможно в VC версии 6, и поэтому HAVE_WORKING_TZSET не включен (но теперь должен быть включен как минимум для VC версии 8 и выше).

КСТАТИ. Для всего, что я делаю с датой/временем, у меня всегда есть SetUtcTime() и UnsetUtcTime(), которые устанавливают TZ на GMT и соответственно вызывают tzset(). У меня также есть функции для временной установки другого часового пояса. Это ЕДИНСТВЕННЫЙ способ сделать это правильно! По многолетнему опыту я могу сказать, что все остальное — это проблема. И calendar.timegm() неверен. Используйте tzset().

Вот доказательство того, что теперь это работает (так что идите к автору ошибки, чтобы исправить код Windows):

(Я набрал это с другого компьютера, так что, надеюсь, без орфографических ошибок, но это то, что я делаю, а не код).


ПРИМЕЧАНИЕ: ВСЕ НИЖЕ ЯВЛЯЕТСЯ PYTHON (я вызываю C Lang из интерфейса Python ctype) ПРИМЕЧАНИЕ. Поскольку здесь я устанавливаю TZ через границу DLL, локальный поток и все такое дерьмо, его нельзя использовать в качестве обходного пути. Необходимо повторно включить 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 lang)

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) ‹- базовый VC версии 8 теперь работает!

(поэтому, если HAVE_WORKING_TZSET определен для (версия 8 и выше), вы получите это:)

-> ... 11:02:40 ... (python)
-> ... 11:02:40 ... (C lang)


Просто проверьте исходный код, чтобы понять, что я имею в виду.

Я проверил это с последней серией Python «2.0»: 2.7.2 только что.

person Ron Lentjes    schedule 07.08.2011