2010-01-18 11 views
9

ExtendsDruck korrekte Zeit mit Zeitzonen, Python

Ok, wir sind nicht heute einen guten Tag haben.

Wenn Sie das richtige TZInfo-Objekt an eine DateTime-Instanz anhängen und dann strftime() es, kommt es immer noch in UTC heraus und ignoriert scheinbar das schöne TZInfo-Objekt, das ich daran angehängt habe.

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

Wir erhalten:

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

fand ich, wenn ich z% hinzufügen, ich den Unterschied hinzufügen kann sein angenommenes berechnet haben:

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

Es nur Angriffe auf die -8 dort, als ob zu sagen, "du machst es selbst, foo."

Aber ich möchte strftime() einfach geben Sie mir eine Zeichenfolge mit vordefinierten lokalen Zeit.

Wie bekomme ich strftime() um die Stunden Subtraktion Mathe für mich zu tun, wenn ich strftime() es?

Der vollständige Code, den ich verwende, ist unten.

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

die aktuelle Zeit in einer bestimmten Zeitzone zu erhalten: 'now = datetime.now (Pacific)' ' – jfs

Antwort

13

.replace führt keine Berechnung durch: es ersetzt einfach ein oder mehrere Felder im neuen zurückgegebenen Objekt, während alle anderen Objekte aus dem aufgerufenen Objekt kopiert werden.

Wenn ich Ihre Situation richtig verstehen, Sie mit einem Datetime-Objekt zu starten, die Sie (durch andere Mittel) wissen ist UTC, aber nicht weiß, dass ich (ein Tzinfo Attribut None hat, was bedeutet, „Ich bin m völlig ahnungslos in Bezug auf welche Zeitzone ich bin in).

So ersten, machen Sie eine Zeitzone-aware aus Ihrer Eingabe Zeitzone-naiven Objekt, um es zu informieren, dass es in Zeitzone UTC ist (alle anderen Felder einfach kopiert werden):

aware = naive.replace(tzinfo=utc) 

Dann können Sie Berechnungen in Bezug auf Zeitzonen fordern und Druck in Folge:

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

Mit dt.replace(tzinfo=tz) bist du nicht wirklich die Zeit Wert konvertieren, sind Sie einfach nur sagen: ‚Hey, nein, warten, diesmal tatsächlich in PDT war, nicht in UTC‘. Wahrscheinlich möchten Sie stattdessen datetime.astimezone(tz) verwenden.

+0

dt.replace (Tzinfo = tz) 'kann Ihnen ein bewusstes' datetime' Objekt geben, während 'datetime.atretimezone (tz) 'wird dir geben, was auch immer du zuvor getan hast (ob es bewusst oder naiv ist). – Shule

2

Ich denke, Wim had the right idea, nur rückwärts. Wenn Sie wissen wollen, was die Zeit in UTC wäre, verwenden:

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

Du musst eine Definition für eine UTC-Zeitzone Klasse raben. Ich verstehe, warum Python keine Standardimplementierung aller möglichen tzinfo liefern wollte, aber UTC sollte in das Basispaket aufgenommen worden sein.