Python: astimezone (Nenhum) fornece data e hora ciente, não reconhece DST

Oct 26 2020

astimezone(None)é uma maneira conveniente de localizar um objeto datetime para a hora local, ou seja, a configuração do seu sistema operacional ( documentos , exemplo ). No entanto, observei que há uma advertência. Uma vez que estou no CET / CEST e acabamos de ter uma mudança de horário de verão, eu estava brincando com datetime e timedelta ciente. 1

from datetime import datetime, timezone
from zoneinfo import ZoneInfo

t_DSTactive = datetime(2020,10,23, tzinfo=ZoneInfo('Europe/Berlin'))
t_DSTinactive = datetime(2020,10,26, tzinfo=ZoneInfo('Europe/Berlin'))
print(t_DSTinactive - t_DSTactive)
# 3 days, 0:00:00

Como esperado, timedeltamostra a diferença de tempo de parede 2 , que é de 3 dias entre esses horários. Devido à mudança de DST ativo para DST inativo, a duração em UTC é de 3 dias e 1 hora:

t_DSTactive = t_DSTactive.astimezone(timezone.utc)
t_DSTinactive = t_DSTinactive.astimezone(timezone.utc)
print(t_DSTinactive - t_DSTactive)
# 3 days, 1:00:00

Usando asttimezone(None)para localizar, tudo parece estar bem (UTC + 2 → UTC + 1):

DSTinactive = datetime(2020,10,26).astimezone(None)
print(DSTactive, DSTinactive)
# 2020-10-23 00:00:00+02:00 2020-10-26 00:00:00+01:00

... mas timedeltainclui +1 hora da transição do horário de verão:

print(DSTinactive - DSTactive)
# 3 days, 1:00:00

O que está acontecendo aqui?


  • 1 Estou usando o MS Windows 10; o resultado pode ser diferente em outras plataformas
  • 2 veja também: Semântica da aritmética de data e hora ciente de fuso horário

Respostas

MrFuppes Oct 26 2020 at 10:37

Olhando para os repr()objetos datetime obtidos com .astimezone(None), vemos que o tzinfoatributo é "apenas" a timedeltaem ambos os casos:

print(repr(DSTactive))
print(repr(DSTinactive))
# datetime.datetime(2020, 10, 23, 0, 0, tzinfo=datetime.timezone(datetime.timedelta(seconds=7200), 'Mitteleuropäische Sommerzeit'))
# datetime.datetime(2020, 10, 26, 0, 0, tzinfo=datetime.timezone(datetime.timedelta(seconds=3600), 'Mitteleuropäische Zeit'))

Em outras palavras, um deslocamento fixo do UTC , não um fuso horário no sentido geográfico (incluindo as alterações de horário de verão prescritas). Um deslocamento fixo, é claro, não reconhece as alterações do horário de verão. Levando em consideração os deslocamentos, o cálculo está dando corretamente 3 dias, 1 hora de diferença.

Contexto: No src do datetime, vemos queastimezone(None)chamadas_local_timezone()para obter o tzinfo, que retorna isso como um deslocamento fixo.

Embora seja conveniente, astimezone(None)pode levar a resultados inesperados aqui. Uma maneira de contornar esse problema é, obviamente, localizar a data e hora no fuso horário local. O tzlocal pode ser de grande ajuda aqui, especialmente no Windows, que é particularmente relutante em revelar o nome do fuso horário.