Este é um exemplo de como gerar ocorrências a partir do
módulo rrule de python-dateutil e convertê-las adequadamente para UTC antes de salvar no
banco de dados, principalmente se sua entrada estiver localizada em um fuso horário que
observe o horário de verão.
Nota: o horário de verão nos EUA em 2014 começa em 9 de março
import pytz
from dateutil.parser import *
from dateutil.rrule import rrule, WEEKLY, MO
tz = pytz.timezone('America/Chicago')
start = parse('Feb 15 2014, 11am')
end = parse('March 24 2014')
_dates = rrule(WEEKLY, dtstart=start, until=end, byweekday=(MO,))
dates = list(_dates)
print dates
Fora:
[datetime.datetime(2014, 2, 17, 11, 0),
datetime.datetime(2014, 2, 24, 11, 0),
datetime.datetime(2014, 3, 3, 11, 0),
datetime.datetime(2014, 3, 10, 11, 0),
datetime.datetime(2014, 3, 17, 11, 0)]
Esses são horários ingênuos, o que é bom, porque queremos que sejam constantemente
às 11h, independentemente de estarmos no horário de verão ou não. Agora podemos
localizar cada um para o US Central e todos ficarão às 11h.
localized = [tz.localize(dt) for dt in dates]
for dt in localized:
print 'Central: {}; UTC: {}'.format(dt, pytz.utc.normalize(dt))
Fora:
Central: 2014-02-17 11:00:00-06:00; UTC: 2014-02-17 17:00:00+00:00
Central: 2014-02-24 11:00:00-06:00; UTC: 2014-02-24 17:00:00+00:00
Central: 2014-03-03 11:00:00-06:00; UTC: 2014-03-03 17:00:00+00:00
Central: 2014-03-10 11:00:00-05:00; UTC: 2014-03-10 16:00:00+00:00
Central: 2014-03-17 11:00:00-05:00; UTC: 2014-03-17 16:00:00+00:00
A esquerda é o que deve ser exibido para o usuário, mas a direita é o que deve
ser salvo no banco de dados. No entanto, você não pode converter diretamente para UTC, porque
isto é o que aconteceria:
utcified = [pytz.utc.localize(dt) for dt in dates]
for dt in utcified:
print 'Central: {}; UTC: {}'.format(tz.normalize(dt), dt)
Fora:
Central: 2014-02-17 05:00:00-06:00; UTC: 2014-02-17 11:00:00+00:00
Central: 2014-02-24 05:00:00-06:00; UTC: 2014-02-24 11:00:00+00:00
Central: 2014-03-03 05:00:00-06:00; UTC: 2014-03-03 11:00:00+00:00
Central: 2014-03-10 06:00:00-05:00; UTC: 2014-03-10 11:00:00+00:00
Central: 2014-03-17 06:00:00-05:00; UTC: 2014-03-17 11:00:00+00:00
O problema óbvio é que nosso evento local das 11h agora está agendado para as 17h. No entanto,
supondo por um momento que o que realmente queríamos era um evento que ocorreria às 17h no
centro dos EUA todas as segundas-feiras, você pode ver que agora, quando o horário de verão entrar em vigor, ele será
alterado para 18h, o que não é o que queremos.
Etapas para gerar ocorrências de eventos persistentes de banco de dados a partir de uma regra recorrente que respeita o horário de verão
- A solicitação de entrada do usuário inclui uma preferência de fuso horário (ou para eventos locais, certifique-se de ter uma constante que armazena o fuso horário local)
- Localize as datas de início / término ingênuas e as datas geradas por regras ingênuas para o fuso horário configurado. É possível que suas datas de início / término tenham tzinfo (se vier de um formulário Django, por exemplo), e você pode precisar removê-lo.
- Use o
normalize
método de pytz para converter as datas em UTC e salve no banco de dados
Etapas para exibir ocorrências recuperadas do banco de dados no fuso horário apropriado
- Crie um objeto de fuso horário pytz para o fuso horário configurado do usuário ou site
- Chame o
normalize
método do objeto fuso horário , passando cada data UTC, para obter a representação local