Printing correct time using timezones, Python
扩展
好的,我们今天没有过好日子。
当您将正确的tzinfo对象附加到日期时间实例,然后strftime()它,它仍然以UTC格式出现,似乎忽略了我附加到它的漂亮的tzinfo对象。
1 2 3 4 5 6 | # python 2.5.4 now = datetime.now() print now.strftime("%a %b %d %X" ) # %X is"locale's appropriate time rep" pst = now.replace( tzinfo=Pacific ) print pst.strftime("%a %b %d %X" ) |
我们得到:
1 2 | Mon Jan 18 17:30:16 Mon Jan 18 17:30:16 |
我发现如果我添加%z,我可以添加它应该计算的差异:
1 2 | Mon Jan 18 17:32:38 Mon Jan 18 17:32:38 -0800 |
它只是在那里加-8,好像在说,"你自己做,foo。"
但是我希望strftime()能够简单地给我一个具有预定时间的字符串。
当我strftime()时,如何让strftime()为我做小时减法数学呢?
我正在使用的完整代码如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | from datetime import tzinfo, timedelta, datetime ZERO = timedelta(0) HOUR = timedelta(hours=1) # A UTC class. class UTC(tzinfo): """UTC""" def utcoffset(self, dt): return ZERO def tzname(self, dt): return"UTC" def dst(self, dt): return ZERO utc = UTC() # A class building tzinfo objects for fixed-offset time zones. # Note that FixedOffset(0,"UTC") is a different way to build a # UTC tzinfo object. class FixedOffset(tzinfo): """Fixed offset in minutes east from UTC.""" def __init__(self, offset, name): self.__offset = timedelta(minutes = offset) self.__name = name def utcoffset(self, dt): return self.__offset def tzname(self, dt): return self.__name def dst(self, dt): return ZERO # A class capturing the platform's idea of local time. import time as _time STDOFFSET = timedelta(seconds = -_time.timezone) if _time.daylight: DSTOFFSET = timedelta(seconds = -_time.altzone) else: DSTOFFSET = STDOFFSET DSTDIFF = DSTOFFSET - STDOFFSET class LocalTimezone(tzinfo): def utcoffset(self, dt): if self._isdst(dt): return DSTOFFSET else: return STDOFFSET def dst(self, dt): if self._isdst(dt): return DSTDIFF else: return ZERO def tzname(self, dt): return _time.tzname[self._isdst(dt)] def _isdst(self, dt): tt = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.weekday(), 0, -1) stamp = _time.mktime(tt) tt = _time.localtime(stamp) return tt.tm_isdst > 0 Local = LocalTimezone() # A complete implementation of current DST rules for major US time zones. def first_sunday_on_or_after(dt): days_to_go = 6 - dt.weekday() if days_to_go: dt += timedelta(days_to_go) return dt # In the US, DST starts at 2am (standard time) on the first Sunday in April. DSTSTART = datetime(1, 4, 1, 2) # and ends at 2am (DST time; 1am standard time) on the last Sunday of Oct. # which is the first Sunday on or after Oct 25. DSTEND = datetime(1, 10, 25, 1) class USTimeZone(tzinfo): def __init__(self, hours, reprname, stdname, dstname): self.stdoffset = timedelta(hours=hours) self.reprname = reprname self.stdname = stdname self.dstname = dstname def __repr__(self): return self.reprname def tzname(self, dt): if self.dst(dt): return self.dstname else: return self.stdname def utcoffset(self, dt): return self.stdoffset + self.dst(dt) def dst(self, dt): if dt is None or dt.tzinfo is None: # An exception may be sensible here, in one or both cases. # It depends on how you want to treat them. The default # fromutc() implementation (called by the default astimezone() # implementation) passes a datetime with dt.tzinfo is self. return ZERO assert dt.tzinfo is self # Find first Sunday in April & the last in October. start = first_sunday_on_or_after(DSTSTART.replace(year=dt.year)) end = first_sunday_on_or_after(DSTEND.replace(year=dt.year)) # Can't compare naive to aware objects, so strip the timezone from # dt first. if start <= dt.replace(tzinfo=None) < end: return HOUR else: return ZERO Eastern = USTimeZone(-5,"Eastern", "EST","EDT") #Central = USTimeZone(-6,"Central", "CST","CDT") #Mountain = USTimeZone(-7,"Mountain","MST","MDT") Pacific = USTimeZone(-8,"Pacific", "PST","PDT") now = datetime.now() print now.strftime("%a %b %d %X %z" ) pst = now.replace( tzinfo=Pacific ) print pst.strftime("%a %b %d %X %z" ) |
如果我正确理解你的情况,你可以从一个日期时间对象开始,你知道(通过其他方式)是UTC,但不知道它本身(具有
因此,首先,您从输入的时区初始对象中获取时区感知,以便通知它它是时区UTC(所有其他字段都被复制):
1 | aware = naive.replace(tzinfo=utc) |
然后,您可以请求有关时区的计算,然后打印:
1 | print aware.astimezone(Pacific).strftime('%a %b %d %X %z') |
使用
我认为Wim有正确的想法,只是倒退。如果您想知道UTC时间,请使用:
1 | print pst.astimezone(UTC).strftime("%a %b %d %X" ) |
您必须挖掘UTC时区类的定义。我理解为什么Python不想提供每个可能的tzinfo的默认实现,但UTC应该包含在基础包中。