Introdução
Os dados podem ser representados de várias formas – e uma maneira conveniente de representar datas e horas é cordas. No entanto, para trabalhar com essas datas e horas de forma aritmética (como calcular diferenças de fuso horário, adicionar ou remover horas, etc.) – precisamos convertê-las para um datetime
objeto.
Uma das fontes mais comuns de datas formatadas em string são APIs REST que retornam strings agnósticas, que podemos então converter para outros formatos.
Além disso – os fusos horários são uma dor de cabeça comum quando se trata de trabalhar com objetos datetime, então precisaremos pensar nisso durante a conversão também.
Neste guia – veremos como converter uma string de data/hora em um
datetime
objeto em Python, usando o built-indatetime
módulo, mas também módulos de terceiros, comodateutil
,arrow
e Maya, contabilizando fusos horários.
Convertendo Strings Usando DateTime
A datetime O módulo consiste em três tipos de objetos diferentes: date
, time
e datetime
. O date
objeto contém a data, time
detém o tempo e datetime
contém data e hora!
import datetime
print(f'Current date/time: {datetime.datetime.now()}')
Executar este código resultaria em:
Current date/time: 2022-12-01 10:27:03.929149
Quando nenhuma formatação personalizada é fornecida, o formato de string padrão é usado, ou seja, o formato para “2022-12-01 10:27:03.929149” está em ISO 8601 formato (AAAA-MM-DDTHH:MM:SS.mmmmmm). Se nossa string de entrada para criar um datetime
objeto está no mesmo formato ISO 8601 ou se você souber o formato que receberá antecipadamente, podemos facilmente analisá-lo para um datetime
objeto:
import datetime
date_time_str = '2022-12-01 10:27:03.929149'
date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S.%f')
print('Date:', date_time_obj.date())
print('Time:', date_time_obj.time())
print('Date-time:', date_time_obj)
Executá-lo imprimirá a data, hora e data e hora:
Date: 2022-12-01
Time: 10:27:03.929149
Date-time: 2022-12-01 10:27:03.929149
Aqui, usamos o strptime()
método, que aceita dois argumentos:
- A data formatada em string
- O formato do primeiro argumento
Especificar o formato desta forma torna a análise muito mais rápida, pois datetime
não precisa tentar interpretar o formato por conta própria, o que é muito mais caro computacionalmente. O valor de retorno é do tipo datetime
.
Em nosso exemplo, "2022-12-01 10:27:03.929149"
é a string de entrada e "%Y-%m-%d %H:%M:%S.%f"
é o formato da nossa string de data. O retornado datetime
o valor é armazenado como date_time_obj
.
Uma vez que este é um datetime
objeto, podemos chamar o date()
e time()
métodos diretamente nele. Como você pode ver na saída, ele imprime a parte 'data' e 'hora' da string de entrada!
Tokens de formato
Vale a pena dedicar um momento para entender tokens de formato - O "%Y-%m-%d %H:%M:%S.%f"
de antes.
Cada token representa uma parte diferente da data e hora, como dia, mês, ano, dia do mês ou semana, etc. lista de tokens suportados é extenso o suficiente para permitir várias formatações. Alguns dos mais usados, que também usamos anteriormente, são:
%Y
: Ano (4 dígitos)%m
: Mês%d
: Dia do mês%H
: Hora (24 horas)%M
: Minutos%S
: Segundos%f
: Microssegundos
Observação: Espera-se que todos esses tokens, exceto o ano, sejam preenchidos com zeros (ou seja, agosto é o 8º mês e são preenchidos com zeros para 08
).
Usando tokens de formato strptime() para converter string em formato de data e hora diferente
Se o formato de uma string for conhecido, ela poderá ser facilmente analisada para um datetime
objeto usando strptime()
. Vamos dar uma olhada em um exemplo não trivial que é traduzido de um formato para outro:
import datetime
date_time_str = 'Jul 17 2022 9:20AM'
date_time_obj = datetime.datetime.strptime(date_time_str, '%b %d %Y %I:%M%p')
print('Date:', date_time_obj.date())
print('Time:', date_time_obj.time())
print('Date-time:', date_time_obj)
A string de entrada tinha um formato – “17 de julho de 2022 9h20”. Conhecendo este formato, mapeamos os elementos constituintes para o formato ISO 8601 e convertemos para um formato datetime
objeto:
Date: 2022-07-17
Time: 09:20:00
Date-time: 2022-07-17 09:20:00
Aqui está uma pequena lista de datas e horas comuns formatadas em string e seus formatos correspondentes para strptime()
:
"Jun 28 2018 at 7:40AM" -> "%b %d %Y at %I:%M%p"
"September 18, 2017, 22:19:55" -> "%B %d, %Y, %H:%M:%S"
"Sun,05/12/99,12:30PM" -> "%a,%d/%m/%y,%I:%M%p"
"Mon, 21 March, 2015" -> "%a, %d %B, %Y"
"2018-03-12T10:12:45Z" -> "%Y-%m-%dT%H:%M:%SZ"
Você pode analisar uma sequência de data e hora de qualquer formato – desde que use a sequência correta de tokens de formato para a entrada que está recebendo.
Converter string em data e hora com fusos horários
O tratamento de datas e horas torna-se mais complexo ao lidar com fusos horários. Todos os exemplos acima até agora são ingênuos em relação ao fuso horário. Estes são conhecidos como objetos de data e hora ingênuos.
No entanto, a datetime
objetos contêm um campo exatamente para armazenar dados relacionados ao fuso horário - tzinfo
:
import datetime as dt
dtime = dt.datetime.now()
print(dtime)
print(dtime.tzinfo)
A tzinfo
campo pretende ser um datetime.timezone
objeto, denotando as informações de fuso horário. Isso é None
por padrão e denota que o objeto datetime é ingênuo quanto ao fuso horário. Uma biblioteca externa muito comum para lidar com fusos horários é pytz
. Você pode definir PyTz objetos como o tzinfo
campo também.
Se você ainda não o possui, instale-o via:
$ pip install pytz
Usando PyTz, podemos criar uma âncora para datas e horários com reconhecimento de fuso horário, como UTC:
import datetime as dt
import pytz
dtime = dt.datetime.now(pytz.utc)
print(dtime)
print(dtime.tzinfo)
Saída:
2022-12-01 02:07:41.960920+00:00
UTC
Não são mais 11h, mas 2h, porque acertamos o fuso horário algumas horas atrás! Esse muda o fuso horário da datahora.
+00:00
é a diferença entre a hora exibida e a hora UTC como âncora de coordenação global. Definimos a hora como UTC, então o deslocamento é 00:00
. Trata-se de um objeto com reconhecimento de fuso horário.
Da mesma forma, podemos mudar a interpretação da mesma data e hora entre fusos horários. Vamos converter uma string, como “2022-06-29 17:08:00” em uma data e hora e depois localizar para o fuso horário “América/Nova_Iorque”:
import datetime as dt
import pytz
date_time_str = '2022-06-29 17:08:00'
date_time_obj = dt.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S')
timezone = pytz.timezone('America/New_York')
timezone_date_time_obj = timezone.localize(date_time_obj)
print(timezone_date_time_obj)
print(timezone_date_time_obj.tzinfo)
Observação: Localização transforma um datetime ingênuo de fuso horário em um datetime com reconhecimento de fuso horário e trata o fuso horário como local. Assim, o data e hora permanece a mesma, mas dado o fuso horário diferente, ele não representa mais o mesmo ponto no tempo sem associação de fusos horários.
Nós temos o mesmo valor datahora, Deslocado por -04: 00 em comparação com a hora UTC:
2022-06-29 17:08:00-04:00
America/New_York
17h08 em Tóquio não é no mesmo horário das 17h08 em Nova York. 17:08 em Tóquio é 3:08 em Nova York.
Como encontrar todos os códigos/aliases de fuso horário?
Para encontrar todos os fusos horários disponíveis, inspecione o all_timezones
campo, que é uma lista de todos os fusos horários disponíveis:
print(f'There are {len(pytz.all_timezones)} timezones in PyTzn')
for time_zone in pytz.all_timezones:
print(time_zone)
Confira nosso guia prático e prático para aprender Git, com práticas recomendadas, padrões aceitos pelo setor e folha de dicas incluída. Pare de pesquisar comandos Git no Google e realmente aprender -lo!
There are 594 timezones in PyTz
Africa/Abidjan
Africa/Accra
Africa/Addis_Ababa
Africa/Algiers
Africa/Asmara
Africa/Asmera
...
Alterar fuso horário do Datetime
Podemos converter o fuso horário de um fuso horário com reconhecimento de fuso horário datetime
objeto de uma região para outra, em vez de localizar um datetime ingênuo de fuso horário através das lentes de algum fuso horário.
Isso é diferente da localização, pois a localização representa um ponto diferente no tempo, mas a conversão do fuso horário de um objeto representa o mesmo ponto no tempo, através de uma lente diferente:
import datetime as dt
import pytz
timezone_nw = pytz.timezone('America/New_York')
nw_datetime_obj = dt.datetime.now(timezone_nw)
timezone_london = pytz.timezone('Europe/London')
london_datetime_obj = nw_datetime_obj.astimezone(timezone_london)
print('America/New_York:', nw_datetime_obj)
print('Europe/London:', london_datetime_obj)
Primeiro, criamos um objeto datetime com a hora atual e o definimos como o fuso horário “América/Nova_Iorque”. Então usando o astimezone()
método, convertemos este datetime
para o fuso horário “Europa/Londres”. Ambos datetime
s imprimirá valores diferentes, usando o deslocamento UTC como link de referência entre eles:
America/New_York: 2022-11-30 21:24:30.123400-05:00
Europe/London: 2022-12-01 02:24:30.123400+00:00
2:24 do dia seguinte em Londres is no mesmo horário das 21h24 do dia anterior em Nova York já que Londres está 5h à frente.
Como esperado, os horários são diferentes, pois estão separados por cerca de 5 horas.
Converter string em data e hora usando bibliotecas de terceiros
Python's datetime
módulo pode converter todos os diferentes tipos de strings em um datetime
objeto. Mas o principal problema é que, para fazer isso, você precisa criar a sequência de código de formatação apropriada que strptime()
posso entender. A criação dessa string leva tempo e torna o código mais difícil de ler.
Em vez disso, podemos usar outras bibliotecas de terceiros para facilitar.
Em alguns casos, essas bibliotecas de terceiros também possuem melhor suporte integrado para manipulação e comparação de data e hora, e algumas até possuem fusos horários integrados, então você não precisa incluir um pacote PyTz extra.
Vamos dar uma olhada em algumas dessas bibliotecas nas seções a seguir.
Converter String em Datetime com dateutil
A módulo dateutil é uma extensão do datetime
módulo. Uma vantagem é que não precisamos passar nenhum código de análise para analisar uma string!
Para converter automaticamente uma string em data e hora sem um token de formato usando Python dateutil
:
from dateutil.parser import parse
datetime = parse('2018-06-29 22:21:41')
print(datetime)
Esta parse
função analisará a string automaticamente! Você não precisa incluir nenhuma string de formato. Vamos tentar analisar diferentes tipos de strings usando dateutil
:
from dateutil.parser import parse
date_array = [
'2018-06-29 08:15:27.243860',
'Jun 28 2018 7:40AM',
'Jun 28 2018 at 7:40AM',
'September 18, 2017, 22:19:55',
'Sun, 05/12/1999, 12:30PM',
'Mon, 21 March, 2015',
'2018-03-12T10:12:45Z',
'2018-06-29 17:08:00.586525+00:00',
'2018-06-29 17:08:00.586525+05:00',
'Tuesday , 6th September, 2017 at 4:30pm'
]
for date in date_array:
print('Parsing: ' + date)
dt = parse(date)
print(dt.date())
print(dt.time())
print(dt.tzinfo)
print('n')
Saída:
Parsing: 2018-06-29 08:15:27.243860
2018-06-29
08:15:27.243860
None
Parsing: Jun 28 2018 7:40AM
2018-06-28
07:40:00
None
Parsing: Jun 28 2018 at 7:40AM
2018-06-28
07:40:00
None
Parsing: September 18, 2017, 22:19:55
2017-09-18
22:19:55
None
Parsing: Sun, 05/12/1999, 12:30PM
1999-05-12
12:30:00
None
Parsing: Mon, 21 March, 2015
2015-03-21
00:00:00
None
Parsing: 2018-03-12T10:12:45Z
2018-03-12
10:12:45
tzutc()
Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29
17:08:00.586525
tzutc()
Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29
17:08:00.586525
tzoffset(None, 18000)
Parsing: Tuesday , 6th September, 2017 at 4:30pm
2017-09-06
16:30:00
None
Você pode ver que quase qualquer tipo de string pode ser analisado facilmente usando o dateutil
módulo.
Embora isso seja conveniente, lembre-se de que ter que prever o formato torna o código muito mais lento; portanto, se seu código exigir alto desempenho, essa pode não ser a abordagem correta para seu aplicativo.
Converter string em data e hora com Maya
Maya também torna muito fácil analisar uma string e alterar fusos horários. Para converter facilmente uma string com o Maya do Python:
import maya
dt = maya.parse('2018-04-29T17:45:25Z').datetime()
print(dt.date())
print(dt.time())
print(dt.tzinfo)
Saída:
2018-04-29
17:45:25
UTC
Para converter a hora para um fuso horário diferente:
import maya
dt = maya.parse('2018-04-29T17:45:25Z').datetime(to_timezone='America/New_York', naive=False)
print(dt.date())
print(dt.time())
print(dt.tzinfo)
Saída:
2018-04-29
13:45:25
America/New_York
Agora, não é tão fácil de usar? Vamos experimentar maya
com o mesmo conjunto de strings que usamos com dateutil
:
import maya
date_array = [
'2018-06-29 08:15:27.243860',
'Jun 28 2018 7:40AM',
'Jun 28 2018 at 7:40AM',
'September 18, 2017, 22:19:55',
'Sun, 05/12/1999, 12:30PM',
'Mon, 21 March, 2015',
'2018-03-12T10:12:45Z',
'2018-06-29 17:08:00.586525+00:00',
'2018-06-29 17:08:00.586525+05:00',
'Tuesday , 6th September, 2017 at 4:30pm'
]
for date in date_array:
print('Parsing: ' + date)
dt = maya.parse(date).datetime()
print(dt)
Saída:
Parsing: 2018-06-29 08:15:27.243860
2018-06-29 08:15:27.243860+00:00
Parsing: Jun 28 2018 7:40AM
2018-06-28 07:40:00+00:00
Parsing: Jun 28 2018 at 7:40AM
2018-06-28 07:40:00+00:00
Parsing: September 18, 2017, 22:19:55
2017-09-18 22:19:55+00:00
Parsing: Sun, 05/12/1999, 12:30PM
1999-05-12 12:30:00+00:00
Parsing: Mon, 21 March, 2015
2015-03-21 00:00:00+00:00
Parsing: 2018-03-12T10:12:45Z
2018-03-12 10:12:45+00:00
Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29 17:08:00.586525+00:00
Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29 12:08:00.586525+00:00
Parsing: Tuesday , 6th September, 2017 at 4:30pm
2017-09-06 16:30:00+00:00
Como você pode ver, todos os formatos de data foram analisados com sucesso!
Se não fornecermos as informações de fuso horário, ele as converterá automaticamente para UTC. Então, é importante ressaltar que nós devo fornecer a to_timezone
e naive
parâmetros se a hora não estiver em UTC.
Converter string em data e hora com seta
seta é outra biblioteca para lidar com data e hora em Python. E como antes com maya
, ele também descobre o formato de data e hora automaticamente. Uma vez interpretado, ele retorna um Python datetime
objeto do arrow
objeto.
Para converter facilmente uma string em data e hora usando Python arrow
:
import arrow
dt = arrow.get('2018-04-29T17:45:25Z')
print(dt.date())
print(dt.time())
print(dt.tzinfo)
Saída:
2018-04-29
17:45:25
tzutc()
E aqui está como você pode usar arrow
para converter fusos horários usando o to()
método:
import arrow
dt = arrow.get('2018-04-29T17:45:25Z').to('America/New_York')
print(dt)
print(dt.date())
print(dt.time())
Saída:
2018-04-29T13:45:25-04:00
2018-04-29
13:45:25
Como você pode ver, a string de data e hora é convertida para a região “América/Nova_Iorque”.
Agora, vamos usar novamente o mesmo conjunto de strings que usamos acima:
import arrow
date_array = [
'2018-06-29 08:15:27.243860',
'2018-03-12T10:12:45Z',
'2018-06-29 17:08:00.586525+00:00',
'2018-06-29 17:08:00.586525+05:00',
]
for date in date_array:
dt = arrow.get(date)
print('Parsing: ' + date)
print(dt)
Este código falhará nas strings de data e hora que foram comentadas, o que representa mais da metade dos nossos exemplos. A saída para outras strings será:
Parsing: 2018-06-29 08:15:27.243860
2018-06-29T08:15:27.243860+00:00
Parsing: 2018-03-12T10:12:45Z
2018-03-12T10:12:45+00:00
Parsing: 2018-06-29 17:08:00.586525+00:00
2018-06-29T17:08:00.586525+00:00
Parsing: 2018-06-29 17:08:00.586525+05:00
2018-06-29T17:08:00.586525+05:00
Para analisar corretamente as strings de data e hora comentadas, você precisará passar o correspondente tokens de formato para dar pistas à biblioteca sobre como analisá-lo.
Conclusão
Neste artigo, mostramos diferentes maneiras de analisar uma string para um datetime
objeto em Python. Você pode optar pelo Python padrão datetime
biblioteca ou qualquer uma das bibliotecas de terceiros mencionadas neste artigo, entre muitas outras.
O principal problema com o padrão datetime
pacote é que precisamos especificar o código de análise manualmente para quase todos os formatos de string de data e hora. Portanto, se o formato da sua string mudar no futuro, você provavelmente também terá que alterar o seu código. Mas muitas bibliotecas de terceiros, como as mencionadas aqui, lidam com isso automaticamente.
Mais um problema que enfrentamos é lidar com fusos horários. A melhor maneira de lidar com eles é sempre armazenar a hora em seu banco de dados no formato UTC e depois convertê-la para o fuso horário local do usuário quando necessário.
Essas bibliotecas não são boas apenas para analisar strings, mas podem ser usadas para vários tipos diferentes de operações relacionadas a data e hora. Eu encorajo você a ler os documentos para aprender detalhadamente as funcionalidades.