Menu Docs

Página inicial do DocsDesenvolver aplicaçõesDrivers PythonPyMongo

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

Neste guia, você pode aprender como lidar com objetos Python datetime no PyMongo.

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.

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)

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

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:

  1. Use pip para instalar a biblioteca do pytz em seu ambiente Python: pip install pytz

  2. Crie um objeto pytz.timezone . Passe o fuso zona de destino para o construtor como uma string.

  3. Ligue para o método localize() em seu objeto timezone , passando no valor datetime 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 horário, consulte o Banco de dados de fuso horário 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.

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

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}")

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}")

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 como True.

  • tzinfo: O objeto timezone .

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}")

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.

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 o datetime 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}")

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.

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 Unix

  • Um 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 é 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')).
...

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

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

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

Para obter mais informações sobre como trabalhar com datas e horários no PyMongo, consulte a seguinte documentação da API:

← Tipos personalizados