Convertendo Strings para datetime em Python

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-in datetime módulo, mas também módulos de terceiros, como dateutil, 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 datetimes 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.

Carimbo de hora:

Mais de Abuso de pilha