Python: получить временную зону на основе летнего времени для временной метки - PullRequest
2 голосов
/ 10 августа 2011

Я написал такой код, чтобы получить часовой пояс на основе летнего времени для определенной эпохи:

def getTimeZoneFromEpoch(epoch)
    if time.daylight and time.gmtime(epoch).tm_isdst==1:
        return -time.altzone/3600.0
    else:
        return -time.timezone/3600.0

Но я не уверен, что он правильный, на самом деле в данный момент я делаю ошибки на 1 час.Может быть, я должен поменять местами altzone и timezone в этом коде, но это не то, что я понял из справки python (временного модуля):

timezone -- difference in seconds between UTC and local standard time
altzone -- difference in  seconds between UTC and local DST time
tm_isdst
    1 if summer time is in effect, 0 if not, and -1 if unknown

Я что-то неправильно понял?

Ответы [ 3 ]

4 голосов
/ 10 августа 2011

Короче говоря, используйте time.localtime() вместо time.gmtime().


Проблема в том, что вы используете gmtime(), как результат следующей программы:

from time import *

def getTimeZoneFromEpoch(epoch):
    if daylight and gmtime(epoch).tm_isdst==1:
        return -altzone/3600.0
    else:
        return -timezone/3600.0

print "                               tm_isdst of     tm_isdst of   time zone's\n" + \
      '                    epoch     gmtime(epoch)  localtime(epoch)  offset'
for d in ('13/03/2011', # DST start date in USA
          '14/03/2011',
          '',
          '06/11/2011', # DST end date in USA
          '07/11/2011',
          '',
          '27/03/2011', # DST start date in Europe
          '28/03/2011',
          '',
          '30/10/2011', # DST end date in Europe
          '31/10/2011'):
    if d:
        ds = strptime(d,'%d/%m/%Y')
        epoch = mktime(ds)
        lt = localtime(epoch)
        gt = gmtime(epoch)
        print '%s  %s  %12s %11s  %7s  %17s' % (d,ds.tm_isdst,epoch,gt.tm_isdst,lt.tm_isdst,getTimeZoneFromEpoch(epoch))
    else:
        print

Когда мои часы настроены на часовой пояс UTC-07: 00 Скалистые горы, где летнее время начинается 13 марта 2011 года и заканчивается 6 ноября 2011 года, результат будет:

                               tm_isdst of     tm_isdst of   time zone's
                    epoch     gmtime(epoch)  localtime(epoch)  offset
13/03/2011  -1  1299999600.0           0        0               -7.0
14/03/2011  -1  1300082400.0           0        1               -7.0

06/11/2011  -1  1320559200.0           0        1               -7.0
07/11/2011  -1  1320649200.0           0        0               -7.0

27/03/2011  -1  1301205600.0           0        1               -7.0
28/03/2011  -1  1301292000.0           0        1               -7.0

30/10/2011  -1  1319954400.0           0        1               -7.0
31/10/2011  -1  1320040800.0           0        1               -7.0

Когда мои часы настроены на часовой пояс "UTC + 01: 00 Западная Континентальная Европа", где летнее время начинается 27 марта 2011 года и заканчивается 30 октября 2011 года, результат:

                               tm_isdst of     tm_isdst of   time zone's
                    epoch     gmtime(epoch)  localtime(epoch)  offset
13/03/2011  -1  1299970800.0           0        0                1.0
14/03/2011  -1  1300057200.0           0        0                1.0

06/11/2011  -1  1320534000.0           0        0                1.0
07/11/2011  -1  1320620400.0           0        0                1.0

27/03/2011  -1  1301180400.0           0        0                1.0
28/03/2011  -1  1301263200.0           0        1                1.0

30/10/2011  -1  1319925600.0           0        1                1.0
31/10/2011  -1  1320015600.0           0        0                1.0
4 голосов
/ 10 августа 2011

Я протестировал этот код, чтобы получить смещение UTC локали виртуальной машины.Что, кстати, действительно действительно только в тот момент, когда оно измеряется.Я не уверен, что ваш код эквивалентен или нет.

def local_ephemeral_UTC_offset(epoch_time=None):
  u"Returns a datetime.timedelta object representing the local time offset from UTC at the moment"
  if epoch_time == None:
    epoch_time = time()
  return datetime.fromtimestamp(epoch_time) - datetime.utcfromtimestamp(epoch_time)
1 голос
/ 17 апреля 2014

Спасибо за помощь, кроме двух предложенных вами методов, я также нашел более гибкую (и, возможно, более совместимую) версию, которая также может принимать объект часового пояса (или просто использовать локальную зону) и возвращать смещение UTC

Была только эта часть AmbiguousTimeError, которая смутила меня, но я кое-что сделал, чтобы она (вроде) работала во всех случаях.

from datetime import datetime
import pytz
from tzlocal import get_localzone

def getUtcOffsetByEpoch(epoch, tz=None):
    if not tz:
        tz = get_localzone()
    delta = 0
    while True:
        try:
            return tz.utcoffset(datetime.fromtimestamp(epoch + delta)).total_seconds()
        except pytz.exceptions.AmbiguousTimeError:## FIXME
            #d = datetime.fromtimestamp(epoch+3600)
            #print('AmbiguousTimeError', d.year, d.month, d.day, d.hour, d.minute, d.second)
            delta += 3600
            print('delta = %s'%delta)
        except (
            ValueError,
            OverflowError,
        ):
            return tz._utcoffset.total_seconds()
...