Creo que se puede afeitarse unas pocas llamadas de método si lo haces de esta manera:
>>> from datetime import datetime
>>> datetime.now(pytz.timezone("Australia/Melbourne")) \
.replace(hour=0, minute=0, second=0, microsecond=0) \
.astimezone(pytz.utc)
PERO ... hay un problema más grande que la estética en su código: se dará un resultado erróneo en el día del cambio hacia o desde el horario de verano.
El motivo es que ni los constructores de fecha y hora ni replace()
tienen en cuenta los cambios de horario de verano.
Por ejemplo:
>>> now = datetime(2012, 4, 1, 5, 0, 0, 0, tzinfo=pytz.timezone("Australia/Melbourne"))
>>> print now
2012-04-01 05:00:00+10:00
>>> print now.replace(hour=0)
2012-04-01 00:00:00+10:00 # wrong! midnight was at 2012-04-01 00:00:00+11:00
>>> print datetime(2012, 3, 1, 0, 0, 0, 0, tzinfo=tz)
2012-03-01 00:00:00+10:00 # wrong again!
Sin embargo, la documentación para tz.localize()
estados:
Este método debe ser usado para construir localtimes, en lugar de pasar un argumento tzinfo a un constructor de fecha y hora.
Por lo tanto, el problema se resuelve de esta manera:
>>> import pytz
>>> from datetime import datetime, date, time
>>> tz = pytz.timezone("Australia/Melbourne")
>>> the_date = date(2012, 4, 1) # use date.today() here
>>> midnight_without_tzinfo = datetime.combine(the_date, time())
>>> print midnight_without_tzinfo
2012-04-01 00:00:00
>>> midnight_with_tzinfo = tz.localize(midnight_without_tzinfo)
>>> print midnight_with_tzinfo
2012-04-01 00:00:00+11:00
>>> print midnight_with_tzinfo.astimezone(pytz.utc)
2012-03-31 13:00:00+00:00
No hay garantías para fechas anteriores al 1582, sin embargo.
no se olvide de milisegundos – joeforker
parece que ignora el horario de verano. En alguna parte '.localize() /. Normalize()' podría ser necesario. – jfs
@ J.F.Sebastian: ¡interesante! ¿Estás seguro? ¿Tienes un ejemplo? es completamente posible. – hop