2010-01-18 31 views
9

Extendsimpresión hora correcta con zonas horarias, Python

Ok, no están teniendo un buen día hoy.

Cuando adjunta el objeto tzinfo correcto a una instancia de fecha y hora, y luego a strftime(), TODAVÍA sale en UTC, aparentemente ignorando el bello objeto tzinfo que le adjunté.

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

obtenemos:

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

he encontrado si añado% z, puedo añadir la diferencia de que su supone que se han calculado:

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

Simplemente tachuelas en el -8 allí, como diciendo, "hazlo tú mismo, foo".

Pero quiero que strftime() simplemente me dé una secuencia CON TIEMPO LOCAL PRECOMPUESTO.

¿Cómo puedo obtener strftime() para hacer la resta de horas de matemáticas para mí cuando strftime()?

El código completo que estoy usando está por debajo.

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

para obtener la hora actual en una zona horaria determinada: 'ahora = datetime.now (Pacífico)' ' – jfs

Respuesta

13

.replace no hace cálculos: simplemente reemplaza uno o más campos en el nuevo objeto devuelto, mientras copia todos los demás del objeto al que se llama.

Si entiendo su situación correctamente, se empieza con un objeto de fecha y hora que se sabe (por otros medios) es UTC, pero no sabe que en sí mismo (se tiene un atributo de tzinfo None, que significa "yo' m totalmente desorientado con respecto a lo zona horaria estoy en).

Así, primera, se hace una zona horaria consciente de su entrada de objetos zona horaria sin tratamiento previo, con el fin de informarle que está en zona horaria UTC (todos los demás campos acabo de copiarlo):

aware = naive.replace(tzinfo=utc) 

Entonces, puede solicitar cálculos en relación con las zonas horarias, y la impresión en consecuencia:

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

Con dt.replace(tzinfo=tz) que realmente no se va a convertir el valor de tiempo, sólo está diciendo 'bueno no, espera, esta vez era en realidad en la TFD, no en UTC'. Probablemente desee utilizar datetime.astimezone(tz) en su lugar.

+0

dt.replace (tzinfo = tz) 'puede darle un objeto' datetime' consciente, mientras 'datetime.astimezone (tz) 'le dará el tipo que tenía antes (ya sea consciente o ingenuo). – Shule

2

Creo que Wim had the right idea, solo al revés. Si usted quiere saber lo que su tiempo sería en UTC, utilice:

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

Vas a tener que desenterrar una definición para una clase zona UTC. Entiendo por qué Python no quería proporcionar una implementación predeterminada de cada tzinfo posible, pero UTC debería haberse incluido en el paquete base.

Cuestiones relacionadas