Eu tenho um timestamptz
campo com reconhecimento de fuso horário no PostgreSQL. Quando puxo os dados da tabela, quero subtrair a hora agora para que eu possa obter sua idade.
O problema que estou tendo é que ambos datetime.datetime.now()
e datetime.datetime.utcnow()
parecem retornar fusos horários desconhecidos, o que resulta na obtenção desse erro:
TypeError: can't subtract offset-naive and offset-aware datetimes
Existe uma maneira de evitar isso (de preferência sem a utilização de um módulo de terceiros).
EDIT: Obrigado pelas sugestões, no entanto, tentar ajustar o fuso horário parece me dar erros .. por isso, vou usar fusos horários desconhecidos no PG e inserir sempre usando:
NOW() AT TIME ZONE 'UTC'
Dessa forma, todos os meus carimbos de hora são UTC por padrão (mesmo que seja mais irritante fazer isso).
datetime.timezone.utc
oupytz.utc
. Por exemplo,1970-01-01 00:00:00
é ambígua e você tem que adicionar um fuso horário para disambiguate:1970-01-01 00:00:00 UTC
. Você vê, você precisa adicionar novas informações; o registro de data e hora por si só é ambíguo.utcnow
não deve retornar um objeto ingênuo ou um carimbo de data / hora sem um fuso horário. Nos documentos, "Um objeto consciente é usado para representar um momento específico que não está aberto à interpretação". Qualquer hora no UTC atende a esse critério, por definição.A solução correta é adicionar as informações do fuso horário, por exemplo, para obter o horário atual como um objeto de data e hora ciente no Python 3:
Nas versões mais antigas do Python, você mesmo pode definir o
utc
objeto tzinfo (exemplo dos documentos datetime):então:
fonte
Eu sei que algumas pessoas usam o Django especificamente como uma interface para abstrair esse tipo de interação com o banco de dados. O Django fornece utilitários que podem ser usados para isso:
Você precisa configurar uma infra-estrutura básica de configurações do Django, mesmo se você estiver apenas usando esse tipo de interface (nas configurações, você precisa incluir
USE_TZ=True
para obter uma data e hora conscientes).Por si só, isso provavelmente não está nem perto o suficiente para motivar você a usar o Django como uma interface, mas existem muitas outras vantagens. Por outro lado, se você tropeçou aqui porque estava manipulando seu aplicativo Django (como eu fiz), talvez isso ajude ...
fonte
USE_TZ=True
obter uma data e hora atenta aqui.+ timedelta(hours=5, minutes=30)
ISTEsta é uma solução muito simples e clara
Duas linhas de código
Conclusão: você deve gerenciar suas variáveis datetime com as mesmas informações de tempo
fonte
diff = datetime.now(timezone.utc) - your_timezone_aware_variable
funciona (e a(a - b)
fórmula acima é a explicação por que(a - b)
pode funcionar, mesmo quea.tzinfo
não sejab.tzinfo
).O módulo psycopg2 possui suas próprias definições de fuso horário, então acabei escrevendo meu próprio wrapper em torno do utcnow:
e use
pg_utcnow
sempre que precisar do tempo atual para comparar com um PostgreSQLtimestamptz
fonte
Eu também enfrentei o mesmo problema. Então eu encontrei uma solução depois de muita pesquisa.
O problema era que, quando obtemos o objeto datetime do modelo ou formulário, ele é compensado e, se obtemos o tempo pelo sistema, ele é ingênuo .
Então, o que fiz foi obter o horário atual usando timezone.now () e importar o fuso horário de django.utils import fuso horário e colocar o USE_TZ = True no arquivo de configurações do seu projeto.
fonte
Eu vim com uma solução ultra-simples:
Ele funciona com valores de data e hora com reconhecimento de fuso horário e ingênuos. E não são necessárias bibliotecas ou soluções alternativas adicionais para o banco de dados.
fonte
Eu descobri que
timezone.make_aware(datetime.datetime.now())
é útil no django (eu estou no 1.9.1). Infelizmente, você não pode simplesmente tornar umdatetime
objeto sensível ao deslocamento, entãotimetz()
ele. Você tem que fazerdatetime
e fazer comparações com base nisso.fonte
Existe alguma razão premente para você não poder lidar com o cálculo de idade no próprio PostgreSQL? Algo como
fonte
Sei que isso é antigo, mas pensei em adicionar minha solução caso alguém ache útil.
Eu queria comparar o datetime ingênuo local com um datetime consciente de um servidor de horas. Basicamente, criei um novo objeto datetime ingênuo usando o objeto datetime consciente. É um pouco complicado e não parece muito bonito, mas faz o trabalho.
... aí vem o doce ...
fonte
utc_to_local()
a partir de minha resposta retorna hora local como uma consciência objeto datetime (É Python 3.3+ código)delta = response.tx_time - time.time()
.