2010-01-18 52 views
9

Extends使用时区打印正确时间,Python

好的,今天我们没有一个美好的一天。

当您将正确的tzinfo对象附加到日期时间实例,然后strftime()它时,它仍然以UTC出现,看似忽略了我附加到它的美丽的tzinfo对象。

 
    # 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") 

我们得到:

 
Mon Jan 18 17:30:16 
Mon Jan 18 17:30:16 

我发现如果我添加%Z,我可以添加的区别它应该已经计算:

 
Mon Jan 18 17:32:38 
Mon Jan 18 17:32:38 -0800 

它只是钉在-8在那里,好像在说,“你自己动手吧,富”。

但我希望strftime()简单地给我一个字符串与预先设定的本地时间。

当我strftime()它时,如何获得strftime()为我做小时减法运算?

我正在使用的完整代码如下。

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") 
+0

获得在给定的时区当前时间:'现在= datetime.now(太平洋)'' – jfs 2014-09-04 10:06:35

回答

13

.replace没有计算:它只是将新的返回对象中的一个或多个字段替换为,而从所调用的对象中复制所有其他字段。

如果我正确理解你的处境,你开始与一个DateTime对象,你知道(通过其他方式)是UTC,但是不知道自己(是有None一个tzinfo属性,意思是“我米完全一无所知关于我在什么时区)。

所以,第一,你犯了一个时区感知从您输入时区,天真的对象,以便通知它,它在时区UTC(所有其他领域刚刚得到复制):

aware = naive.replace(tzinfo=utc) 

然后,您可以要求有关时区计算,并且因此打印:

print aware.astimezone(Pacific).strftime('%a %b %d %X %z') 
5

随着dt.replace(tzinfo=tz)你没有真正转换的时间价值,你只是说“嘿不,等一下,这一次竟是PDT,而不是在UTC”。你可能会想用datetime.astimezone(tz)代替。

+0

dt.replace(tzinfo = tz)'可以给你一个明显的'datetime'对象,而'datetime。astimezone(tz)'会给你以前的任何种类(无论是否意识到或天真)。 – Shule 2017-09-21 08:47:10

2

我认为Wim had the right idea,只是倒退。如果您想知道您的UTC时间,请使用:

print pst.astimezone(UTC).strftime("%a %b %d %X") 

您必须为UTC时区类挖掘定义。我明白为什么Python不想提供每种可能的tzinfo的默认实现,但UTC应该包含在基本包中。