2011-07-23 22 views
6

Un banco específico tiene sucursales en las principales ciudades del mundo. Todos abren a las 10:00 a.m. hora local. Si dentro de una zona horaria utiliza el horario de verano, entonces, por supuesto, el horario de apertura local también sigue el horario ajustado por horario de verano. Entonces, ¿cómo puedo pasar de la hora local a la hora exacta?Python: desde hora local ajustada por DST a UTC

Lo que necesito es una función to_utc(localdt, tz) así:

Argumentos:

  • localdt: hora local, como objeto de fecha y hora ingenuo, DST-ajustado
  • tz: zona horaria en el TZ-formato, p.ej 'Europa/Berlín'

Devuelve:

  • objeto de fecha y hora, en UTC, zona horaria consciente

EDIT:

El mayor reto es detectar si la hora local está en un período con horario de verano, lo que también significa que está ajustado en horario de verano.

Para 'Europe/Berlin' que tiene 1 DST en el verano:

  • 1 ª Ene 10:00 => Jan 1 ª 09:00 GMT
  • de julio de 1 ª 10:00 => 1st de julio de 08:00 GMT

Por 'África/Lagos', que no tiene el horario de verano:

  • 1 ª Ene 10:00 => Jan 1 ª 09:00 GMT
  • primero de julio de 10:00 primera => Julio 09:00 GMT
+0

escollo: 27 Marzo 2011 a las 01:00, los relojes se establecieron adelante a 02:00. Entonces el intervalo entre 01:00 y 02:00 no es válido. 30 de octubre de 2011 a la 01:00, los relojes volverán a las 00:00. Entonces el intervalo entre 00:00 y 01:00 es ambiguo. –

+1

'pytz' describe que las transiciones DST no funcionan para ninguna zona horaria que tenga una. Si un paquete creado específicamente para ayudar con las zonas horarias no es compatible con eso, entonces es demasiado trabajo para que usted lo haga correctamente. Tendrá que conformarse con casi la derecha. – agf

Respuesta

7

Usando pytz, y en particular su localize method:

import pytz 
import datetime as dt 

def to_utc(localdt,tz): 
    timezone=pytz.timezone(tz) 
    utc=pytz.utc 
    return timezone.localize(localdt).astimezone(utc) 

if __name__=='__main__': 
    for tz in ('Europe/Berlin','Africa/Lagos'): 
     for date in (dt.datetime(2011,1,1,10,0,0), 
       dt.datetime(2011,7,1,10,0,0), 
       ): 
      print('{tz:15} {l} --> {u}'.format(
       tz=tz, 
       l=date.strftime('%b %d %H:%M'), 
       u=to_utc(date,tz).strftime('%b %d %H:%M %Z'))) 

produce

Europe/Berlin Jan 01 10:00 --> Jan 01 09:00 UTC 
Europe/Berlin Jul 01 10:00 --> Jul 01 08:00 UTC 
Africa/Lagos Jan 01 10:00 --> Jan 01 09:00 UTC 
Africa/Lagos Jul 01 10:00 --> Jul 01 09:00 UTC 
+0

Genial, gracias :) –

+2

nota: algunos horarios locales son ambiguos. Aunque es poco probable que un banco abra a la vez durante la transición de DST; puede usar el parámetro 'is_dst = None' para' .localize() 'para afirmar eso. – jfs

1
from datetime import datetime, tzinfo, timedelta 

class GMT1(tzinfo): 
    def utcoffset(self, dt): 
     return timedelta(hours=1) 
    def dst(self, dt): 
     return timedelta(0) 
    def tzname(self,dt): 
     return "Europe/Prague" 
year, month, day = 2011, 7, 23 
dt = datetime(year, month, day, 10) 

class UTC(tzinfo): 
    def utcoffset(self, dt): 
     return timedelta(0) 
    def dst(self, dt): 
     return timedelta(0) 
    def tzname(self,dt): 
     return "UTC" 

def utc(localt, tz): 
    return localt.replace(tzinfo=tz).astimezone(UTC()) 

print utc(dt, GMT1()) 

nueva versión. Esto hace lo que quiere: toma una fecha de inicio ingenua y una zona horaria y devuelve una hora de fecha UTC.

+0

Su solución no resuelve el principal desafío: manejo automático de DST. –

+0

No estoy seguro de entender. Si el 'tzinfo' que utiliza tiene un' timedelta' para el horario de verano, ¿debe ser manejado automáticamente por 'utcnow()'? – agf

+0

Lo entiendo ahora. Actualizado mi respuesta. – agf

Cuestiones relacionadas