Datas e Horários
Nesta página
- Visão geral
- Terminologia
- Horários ingênuos
- Horários cientes
- Localização
- Lendo horários
- Data/hora UTC ingnua
- Data hora UTC ciente
- Data e hora localizada
- Armazenar data/hora
- Tratamento de datas e hora fora do intervalo
- DatetimeConversion.DATETIME
- DatetimeConversion.DATETIME_MS
- DatetimeConversion.DATETIME_AUTO
- DatetimeConversion.DATETIME_CLAMP
- Documentação da API
Visão geral
Neste guia, você pode aprender como lidar com objetos Python datetime
no PyMongo.
Terminologia
O Python utiliza um tipo de dados dedicado, datetime.datetime
, para representar datas e horas. O MongoDB armazena valores datetime
no tempo universal coordenado (UTC), um padrão de hora global local para Londres, Inglaterra.
Horários ingênuos
Um valor datetime
é ingênuo quando não inclui informações adicionais sobre o deslocamento UTC ou fuso zona. Veja a seguir um exemplo de um objeto datetime
ingênuo :
datetime(2002, 10, 27, 14, 0, 0)
Horários cientes
Um valor datetime
está ciente quando inclui um atributo tzinfo
. Este atributo indica o deslocamento do valor em relação à hora UTC, seu fuso horário e se o horário de verão estava em vigor. Veja a seguir um exemplo de um objeto datetime
com reconhecimento:
datetime(2002, 10, 27, 6, 0, tzinfo=<DstTzInfo 'US/Pacific' PST-1 day, 16:00:00 STD>)
Localização
A localização é o processo de adicionar horas ou subtrair horas de um valor de datetime
para traduzir seu valor para outro fuso zona. Para localizar um valor datetime
, execute as seguintes etapas:
Use pip para instalar a biblioteca do
pytz
em seu ambiente Python:pip install pytz
Crie um objeto
pytz.timezone
. Passe o fuso zona de destino para o construtor como uma string.Ligue para o método
localize()
em seu objetotimezone
, passando no valordatetime
para localizar.
O seguinte exemplo de código localiza um valor datetime
para o fuso horário "US/Pacific"
, um deslocamento de oito horas:
from datetime import datetime from pytz import timezone utc_datetime = datetime(2002, 10, 27, 6, 0, 0) pacific = timezone("US/Pacific") local_datetime = pacific.localize(utc_datetime) print(f"UTC datetime: {utc_datetime}") print(f"Local datetime: {local_datetime}")
UTC datetime: 2002-10-27 06:00:00 Local datetime: 2002-10-27 06:00:00-08:00
Para obter uma lista canônica de strings de fuso zona , consulte o Time Zone Database ou seu artigo correspondente na Wikipedia.
Importante
Com o PyMongo, você não pode salvar instâncias datetime.date
, porque não há tipo BSON para datas sem horários. Converta todos os objetos date
em objetos datetime
antes de salvá-los no MongoDB.
Lendo horários
Quando você usa o PyMongo para recuperar um valor datetime
, o driver pode formatá-lo como um UTC ingênuo, UTC ciente ou valor localizado. As seções a seguir descrevem como recuperar cada tipo de valor.
Para estas seções, suponha que uma coleção MongoDB denominada sample_collection
contenha o seguinte documento. O valor do campo "date"
é um valor UTC datetime
.
{"date": datetime(2002, 10, 27, 14, 0, 0)}
Data/hora UTC ingnua
Por padrão, o PyMongo recupera valores UTC datetime
sem informações adicionais. O exemplo de código a seguir recupera o documento de amostra e imprime o valor datetime
. O valor impresso é idêntico ao do documento de amostra .
from datetime import datetime collection = database["sample_collection"] find_result = collection.find_one()["date"] print(f"datetime: {find_result}") print(f"datetime.tzinfo: {find_result.tzinfo}")
datetime: 2002-10-27 14:00:00 datetime.tzinfo: None
Data hora UTC ciente
Para instruir o PyMongo a recuperar um valor de datetime
ciente, crie um objeto CodecOptions
e passe tz_aware = True
para o construtor. Em seguida, passe o objeto CodecOptions
para o método get_collection()
.
O exemplo de código a seguir recupera o valor datetime
do documento de exemplo como um datetime
ciente:
from pymongo import MongoClient from datetime import datetime from bson.codec_options import CodecOptions options = CodecOptions(tz_aware = True) collection = database.get_collection("sample_collection", options) find_result = collection.find_one()["date"] print(f"datetime: {find_result}") print(f"datetime.tzinfo: {find_result.tzinfo}")
datetime: 2002-10-27 14:00:00+00:00 datetime.tzinfo: <bson.tz_util.FixedOffset object at 0x104db2b80>
Data e hora localizada
Se você planeja mostrar valores datetime
para o usuário, poderá instruir o PyMongo a converter automaticamente todos os horários lidos do MongoDB para um fuso horário específico. Para fazer isso, crie um objeto timezone
para o fuso horário de destino, conforme descrito na seção Terminologia . Em seguida, crie um objeto CodecOptions
e passe os seguintes argumentos para o construtor:
tz_aware
: Defina comoTrue
.tzinfo
: O objetotimezone
.
O exemplo de código a seguir recupera o documento de amostra, mas usa os argumentos tz_aware
e tzinfo
para localizar automaticamente o valor datetime
para o fuso zona "US/Pacific"
:
from pymongo import MongoClient from datetime import datetime from bson.codec_options import CodecOptions import pytz from pytz import timezone pacific = timezone("US/Pacific") options = CodecOptions(tz_aware = True, tzinfo = pacific) collection = database.get_collection("sample_collection", options) find_result = collection.find_one()["date"] print(f"datetime: {find_result}") print(f"datetime.tzinfo: {find_result.tzinfo}")
datetime: 2002-10-27 06:00:00-08:00 datetime.tzinfo: US/Pacific
Dica
O exemplo anterior especifica as opções de codec no nível da collection. Você também pode especificar opções de codec no nível do cliente ou do banco de dados.
Armazenar data/hora
Para consistência, armazene somente valores UTC datetime
no MongoDB. Quando você usa o PyMongo para criar ou atualizar um campo contendo um valor datetime
, o driver primeiro verifica se o valor datetime
é ingênuo ou ciente:
Se o
datetime
for ingênuo, o PyMongo pressupõe que odatetime
está em UTC e o armazena no MongoDB inalterado.Se o
datetime
estiver ciente, o PyMongo converte automaticamente o tempo para UTC antes de armazená-lo no MongoDB.
O exemplo de código a seguir insere um documento contendo um valor datetime
localizado no fuso horário "US/Pacific"
. O PyMongo usa o fuso horário anexado para converter a hora local em UTC. Quando o documento é recuperado do MongoDB, o valor datetime
está em UTC.
from pymongo import MongoClient from datetime import datetime from pytz import timezone utc_datetime = datetime(2002, 10, 27, 6, 0, 0) pacific = timezone("US/Pacific") local_datetime = pacific.localize(utc_datetime) print(f"datetime before storage: {local_datetime}") collection.insert_one({"date": local_datetime}) find_result = collection.find_one()["date"] print(f"datetime after storage: {find_result}")
datetime before storage: 2002-10-27 06:00:00-08:00 datetime after storage: 2002-10-27 14:00:00
Importante
datetime. now()
Evite ligar para o método datetime.now()
sem argumentos. Isso retorna a hora local atual.
Em vez disso, sempre chame o método datetime.now(tz=datetime.timezone.utc)
, que retorna a hora atual em UTC.
Tratamento de datas e hora fora do intervalo
A classe datetime
do Python pode representar apenas datetime
valores entre datetime.min
e datetime.max
(anos 1-9999). Você pode representar um intervalo muito maior de datas e horas usando BSON, que permite qualquer 64valor de milissegundo de bits da época do Unix.
Para representar um horário BSON com o PyMongo, crie um objeto datetime_ms.DatetimeMS
, um wrapper para o tipo int
integrado do Python. Você pode criar manualmente um objeto DatetimeMS
passando um dos seguintes valores:
Um
int
representando o número de milissegundos desde a época do UnixUm objeto
datetime
O exemplo de código a seguir constrói um objeto DatetimeMS
passando um valor int
que representa o ano -146136543, uma data fora do intervalo datetime
:
from bson.datetime_ms import DatetimeMS out_of_range = DatetimeMS(-(2**62))
Você também pode instruir o PyMongo a decodificar automaticamente valores UTC datetime
como objetos DatetimeMS
. Para fazer isso, defina o parâmetro datetime_conversion
de CodecOptions
para um valor do enum datetime_ms.DatetimeConversion
. As seções a seguir descrevem esses valores.
Dica
DatetimeMS
os objetos suportam métodos de comparação avançados contra outras instâncias de DatetimeMS
. Você também pode convertê-los em objetos datetime
usando o método DatetimeMS.to_datetime()
.
DatetimeConversion.DATETIME
DatetimeConversion.DATETIME
é o valor padrão. Esse valor faz com que o PyMongo gere um erro ao tentar decodificar uma data fora do intervalo, como mostrado no exemplo a seguir:
from datetime import datetime from bson import encode, decode from bson.datetime_ms import DatetimeMS out_of_range = DatetimeMS(-(2**62)) val = encode({"date": out_of_range}) decoded = decode(val) print(decoded)
... bson.errors.InvalidBSON: year -146136543 is out of range (Consider Using CodecOptions(datetime_conversion=DATETIME_AUTO) or MongoClient(datetime_conversion='DATETIME_AUTO')). ...
DatetimeConversion.DATETIME_MS
Esse valor instrui o PyMongo a retornar somente DatetimeMS
objetos, mesmo que a data esteja dentro do intervalo de datetime
:
from datetime import datetime from bson import encode, decode from bson.datetime_ms import DatetimeMS from bson.codec_options import CodecOptions, DatetimeConversion val = encode({"date": datetime(1970, 1, 2)}) codec_ms = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_MS) decoded = decode(val, codec_options=codec_ms) print(decoded)
{"date": DatetimeMS(86400000)}
DatetimeConversion.DATETIME_AUTO
Esse valor instrui o PyMongo a retornar objetos datetime
se o valor estiver dentro do intervalo datetime
e a retornar um objeto DatetimeMS
caso contrário. O seguinte exemplo de código codifica e decodifica uma data/hora no intervalo datetime
e uma fora do intervalo:
from datetime import datetime from bson import encode, decode from bson.datetime_ms import DatetimeMS from bson.codec_options import CodecOptions, DatetimeConversion in_range = encode({"date": datetime(1970, 1, 1)}) out_of_range = encode({"date": DatetimeMS(-(2**62))}) codec_auto = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_AUTO) in_decoded = decode(in_range, codec_options=codec_auto) out_decoded = decode(out_of_range, codec_options=codec_auto) print(f"in-range date: {in_decoded}") print(f"out-of-range date: {out_decoded}")
in-range date: {"date": datetime.datetime(1970, 1, 1, 0, 0)} out-of-range date: {'x': DatetimeMS(-4611686018427387904)}
DatetimeConversion.DATETIME_CLAMP
Esse valor "grampeia" os objetos datetime
resultantes, forçando-os a estar dentro do intervalo datetime
(cortado para 999 000 microssegundos).
O exemplo de código a seguir codifica e decodifica uma data/hora anterior ao intervalo datetime
e uma data/hora posterior ao intervalo datetime
. Os valores resultantes estão no início e no final do intervalo permitido.
from datetime import datetime from bson import encode, decode from bson.datetime_ms import DatetimeMS from bson.codec_options import CodecOptions, DatetimeConversion before = encode({"date": DatetimeMS(-(2**62))}) after = encode({"date": DatetimeMS(2**62)}) codec_clamp = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_CLAMP) before_decoded = decode(before, codec_options=codec_clamp) after_decoded = decode(after, codec_options=codec_clamp) print(f"datetime before the range: {before_decoded}") print(f"datetime after the range: {after_decoded}")
datetime before the range: {"date": datetime.datetime(1, 1, 1, 0, 0)} datetime after the range: {"date": datetime.datetime(9999, 12, 31, 23, 59, 59, 999000)}
Documentação da API
Para obter mais informações sobre como trabalhar com datas e horários no PyMongo, consulte a seguinte documentação da API:
datetime
em docs.python.orgpytz
em pypi.org