Pergunta

O melhor que eu posso vir acima com agora é esta monstruosidade:

>>> datetime.utcnow() \
...   .replace(tzinfo=pytz.UTC) \
...   .astimezone(pytz.timezone("Australia/Melbourne")) \
...   .replace(hour=0,minute=0,second=0,microsecond=0) \
...   .astimezone(pytz.UTC) \
...   .replace(tzinfo=None)
datetime.datetime(2008, 12, 16, 13, 0)

i., Em Inglês, obter o tempo atual (em UTC), convertê-lo para algum outro fuso horário, defina o tempo de meia-noite, em seguida, converter de volta para UTC.

Eu não estou usando agora () ou localtime () como que usaria fuso horário do servidor, não fuso horário do usuário.

Eu não posso ajudar sentindo que estou perdendo algo, alguma idéia?

Foi útil?

Solução

Eu acho que você pode raspar alguns chamadas de método se você fazê-lo como este:

>>> from datetime import datetime
>>> datetime.now(pytz.timezone("Australia/Melbourne")) \
            .replace(hour=0, minute=0, second=0, microsecond=0) \
            .astimezone(pytz.utc)

Mas ... há um problema maior do que a estética em seu código: ele vai dar o resultado errado no dia da mudança de ou para Daylight Saving Time

.

A razão para isso é que nem os construtores de data e hora nem alterações replace() take DST em conta.

Por exemplo:

>>> 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!

No entanto, a documentação para estados tz.localize():

Este método deve ser usado para construir LocalTimes, em vez do que passar um tzinfo argumento para um construtor de data e hora.

Assim, o problema é resolvido assim:

>>> 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

Não há garantias para datas antes de 1582, apesar de tudo.

Outras dicas

@ do hop resposta está errado no dia da transição do horário de verão (DST), por exemplo, 01 de abril de 2012 . Para corrigi-lo tz.localize() poderia ser usado:

tz = pytz.timezone("Australia/Melbourne")
today = datetime.now(tz).date()
midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)
utc_dt = midnight.astimezone(pytz.utc)        

O mesmo com os comentários:

#!/usr/bin/env python
from datetime import datetime, time
import pytz # pip instal pytz

tz = pytz.timezone("Australia/Melbourne") # choose timezone

# 1. get correct date for the midnight using given timezone.
today = datetime.now(tz).date()

# 2. get midnight in the correct timezone (taking into account DST)
#NOTE: tzinfo=None and tz.localize()
# assert that there is no dst transition at midnight (`is_dst=None`)
midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)

# 3. convert to UTC (no need to call `utc.normalize()` due to UTC has no 
#    DST transitions)
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
print midnight.astimezone(pytz.utc).strftime(fmt)

Definir as modifica variáveis ??de ambiente TZ o fuso horário funções de data e hora do Python trabalhar.

>>> time.gmtime()
(2008, 12, 17, 1, 16, 46, 2, 352, 0)
>>> time.localtime()
(2008, 12, 16, 20, 16, 47, 1, 351, 0)
>>> os.environ['TZ']='Australia/Melbourne'
>>> time.localtime()
(2008, 12, 17, 12, 16, 53, 2, 352, 1)

Cada zona de tempo tem um número, por exemplo, US / Central = -6. Esta é definida como o deslocamento em horas de UTC. Desde 0000 é meia-noite, você pode simplesmente usar este deslocamento para encontrar o tempo em qualquer fuso horário quando for meia-noite UTC. Para acesso que, eu acredito que você pode usar

 time.timezone

De acordo com a O Python Docs , time.timezone realmente dá o valor negativo de este número:

time.timezone

O deslocamento do fuso horário local (não-DST), em segundos a oeste de UTC (negativo na maior parte da Europa Ocidental, positivo nos EUA, zero no Reino Unido).

Então, você poderia simplesmente usar esse número para o tempo em horas se é positivo (ou seja, se é meia-noite em Chicago (que tem um valor +6 fuso horário), então é 6000 = 06:00 UTC).

Se o número for negativa, subtrai-se a partir de 24. Por exemplo, Berlim daria -1, então 24 -. 1 => 2300 = 11:00

Este é mais simples com dateutil.tz que pytz:

>>>import datetime
>>>import dateutil.tz
>>>midnight=(datetime.datetime
             .now(dateutil.tz.gettz('Australia/Melbourne'))
             .replace(hour=0, minute=0, second=0, microsecond=0)
             .astimezone(dateutil.tz.tzutc()))
>>>print(midnight)
2019-04-26 14:00:00+00:00

O tzinfo documentação recomenda dateutil.tz desde Python 3.6. O tzinfo objetos de dateutil.tz não tenho problemas com anomalias, como DST, sem exigir a funcionalidade Localize de pytz. Usando o exemplo do user3850:

>>> now = (datetime.datetime(2012, 4, 1, 5,  
...         tzinfo = dateutil.tz.gettz('Australia/Melbourne'))) 
>>> print(now.replace(hour = 0).astimezone(dateutil.tz.tzutc()))
2012-03-31 13:00:00+00:00
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top