formato strptime de python con bits opcionales

4 minutos de lectura

Avatar de usuario de Digant C Kasundra
Digant C Kasundra

Ahora mismo tengo:

timestamp = datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S.%f')

Esto funciona muy bien a menos que esté convirtiendo una cadena que no tiene microsegundos. ¿Cómo puedo especificar que los microsegundos son opcionales (y deben considerarse 0 si no están en la cadena)?

Avatar de usuario de Alexander
Alejandro

Podrías usar un try/except bloquear:

try:
    timestamp = datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S.%f')
except ValueError:
    timestamp = datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S')

  • Es un poco triste que esto dependa de excepciones como flujo de control.

    –Joe Sadoski

    15 de junio a las 13:50

  • @JoeSadoski No creo que la solución anterior se ajuste a lo que se describe en su artículo vinculado.

    – Alejandro

    15 de junio a las 15:33

¿Qué tal simplemente agregarlo si no existe?

if '.' not in date_string:
    date_string = date_string + '.0'

timestamp = datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S.%f')

  • Esta es una buena respuesta, pero me decepciona que una biblioteca diseñada para eliminar el dolor de cabeza de transformar cadenas de fecha y hora en objetos de fecha y hora no se ocupe de estos casos de uso bastante simples. El objetivo de una biblioteca de este tipo es eliminar la necesidad de que el usuario se preocupe por esto.

    – Auspicio

    2 mayo 2018 a las 20:48

  • Me gusta mucho esta respuesta en lugar de usar el método try/catch

    – francotirador

    29 mayo 2019 a las 20:09

avatar de usuario de user14608345
usuario14608345

Llego tarde a la fiesta, pero descubrí que si no te importan los bits opcionales, esto cortará el .%f para ti.

datestring.split('.')[0]

  • Gracias. Esto funciona para mi caso de uso mucho mejor que otras soluciones de longitud

    – vu le

    17 de diciembre de 2020 a las 9:32

avatar de usuario de fourfightingfoxes
cuatro zorros de pelea

Prefiero usar coincidencias de expresiones regulares en lugar de probar y excepto. Esto permite muchas alternativas de formatos aceptables.

# full timestamp with milliseconds
match = re.match(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z", date_string)
if match:
    return datetime.strptime(date_string, "%Y-%m-%dT%H:%M:%S.%fZ")

# timestamp missing milliseconds
match = re.match(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z", date_string)
if match:
    return datetime.strptime(date_string, "%Y-%m-%dT%H:%M:%SZ")

# timestamp missing milliseconds & seconds
match = re.match(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}Z", date_string)
if match:
    return datetime.strptime(date_string, "%Y-%m-%dT%H:%MZ")

# unknown timestamp format
return false

No olvide importar “re” y “datetime” para este método.

avatar de usuario de jfs
jfs

datetime(*map(int, re.findall('\d+', date_string)))

puede analizar ambos '%Y-%m-%d %H:%M:%S.%f' y '%Y-%m-%d %H:%M:%S'. Es demasiado permisivo si su entrada no se filtra.

Es rápido y sucio, pero a veces strptime() es demasiado lento Se puede usar si sabe que la entrada tiene el formato de fecha esperado.

  • Esto da resultados incorrectos si, en date_stringlos ceros finales se omiten de la parte de microsegundos.

    – jez

    22 de agosto de 2016 a las 19:07

  • @jez: sí, por eso dije que es “demasiado permisivo”. Funciona solo si la entrada tiene el formato esperado (ninguno o 6 dígitos para microsegundos). 2- sobre tu edición: mira la pregunta: datetime es la clase aquí, no el módulo.

    – jfs

    22 de agosto de 2016 a las 19:14


avatar de usuario de milahu
milahu

usando una expresión regular y algunas expresiones de lista

time_str = "12:34.567"
# time format is [HH:]MM:SS[.FFF]
sum([a*b for a,b in zip(map(lambda x: int(x) if x else 0, re.match(r"(?:(\d{2}):)?(\d{2}):(\d{2})(?:\.(\d{3}))?", time_str).groups()), [3600, 60, 1, 1/1000])])
# result = 754.567

  • Esto da resultados incorrectos si, en date_stringlos ceros finales se omiten de la parte de microsegundos.

    – jez

    22 de agosto de 2016 a las 19:07

  • @jez: sí, por eso dije que es “demasiado permisivo”. Funciona solo si la entrada tiene el formato esperado (ninguno o 6 dígitos para microsegundos). 2- sobre tu edición: mira la pregunta: datetime es la clase aquí, no el módulo.

    – jfs

    22 de agosto de 2016 a las 19:14


Avatar de usuario de JulianWgs
julianwgs

Si está utilizando Pandas, también puede filtrar la serie y concatenarla. El índice se une automáticamente.

import pandas as pd

# Every other row has a different format
df = pd.DataFrame({"datetime_string": ["21-06-08 14:36:09", "21-06-08 14:36:09.50", "21-06-08 14:36:10", "21-06-08 14:36:10.50"]})
df["datetime"] = pd.concat([
    pd.to_datetime(df["datetime_string"].iloc[1::2], format="%y-%m-%d %H:%M:%S.%f"),
    pd.to_datetime(df["datetime_string"].iloc[::2], format="%y-%m-%d %H:%M:%S"),
])

fechahora_cadena fecha y hora
0 21-06-08 14:36:09 2021-06-08 14:36:09
1 21-06-08 14:36:09.50 2021-06-08 14:36:09.500000
2 21-06-08 14:36:10 2021-06-08 14:36:10
3 21-06-08 14:36:10.50 2021-06-08 14:36:10.500000

¿Ha sido útil esta solución?