#python #datetime #timestamp #nanotime
Вопрос:
У меня есть несколько строк, представляющих метки времени. Несколькими примерами могут быть : 19551231
(%Y%m%d) или 20210216154500
(%Y%m%d%H%M%S). Как вы можете видеть, формат может отличаться.
Я ищу способ преобразовать все эти разные строки в уникальный формат DatetimeWithNanoseconds.
Я знаю, что могу преобразовать метку времени в дату с точностью до наносекунд, используя целые числа, подобные этому: DatetimeWithNanoseconds(2020, 6, 22, 17, 1, 30, nanosecond=0)
.
Означает ли это, что я должен вручную анализировать каждую полученную строку, чтобы получить соответствующие целые числа ? Есть ли лучший способ сделать это ? Например, как strptime
работает функция (использование строк, например %Y%m%d
, для определения расположения строки)
Ответ №1:
Я узнал, что из datetime
формата легко извлечь часы, например, просто позвонив date.hour
(то же самое для года, месяца и т. Д.).
Зная это, способ преобразования строки в формат DatetimeWithNanoseconds состоит из следующих 2 простых шагов:
- Преобразуйте строку в формат даты и времени:
date = '19551231'
date = datetime.datetime.strptime(date, '%Y%m%d')
- Преобразование в дату и время в наносекундах:
nano = DatetimeWithNanoseconds(date.year, date.month, date.day, date.hour, date.minute, date.second, nanosecond=0)
Ответ №2:
Вы предложили примеры временных меток из 8 и 14 символов. Похоже, вы хотите добавить 9 или более нулей, преобразовав их в единообразные 23-символьные метки времени, читаемые человеком. В этот момент было бы просто перевести его в формат rfc 3339 и позвонить from_rfc3339()
, чтобы получить время с точностью до наносекунд.
Рассмотрите возможность использования простого while
цикла:
while len(ts) < 23:
ts = '0'
return ts
Лучший способ сделать то же самое:
return ts '0' * (23 - len(ts))
Редактировать
Вам понадобится пара помощников здесь. Каждый из них поддается модульному тестированию и предлагает очень простой API.
Первый из них превращает все в единообразные 23-символьные метки времени, читаемые человеком, как я упоминал выше.
Второй взял бы первые 14 символов и превратил бы их в целые секунды с момента эпохи. Затем переключитесь на наносекунды. У меня есть что-то вроде этого на уме:
import datetime as dt
def to_nanosec(stamp: str):
assert 23 == len(stamp), stamp
d = dt.datetime.strptime(stamp[:14], '%Y%d%m%H%M%S')
return 1e9 * d.timestamp() int(stamp) % 1e9
Эквивалентно, что 2-й термин может быть … int(stamp[14:])
Предпочитаю int(1e9)
, или 1_000_000_000
, если возвращение int
важно.
Вы , конечно, могли бы разбить диапазоны символов и поставить знаки препинания, такие как :
двоеточие и Z
между ними, перед вызовом from_rfc3339()
, но .strptime()
здесь может быть удобнее.
Стоит отметить, что numpy предлагает поддержку наносекундной точности.
Комментарии:
1. К сожалению
from_rfc3339()
, поднимитеValueError
, потому что он не принимает мою строку19551231
, так как формат не соответствует чему-то вроде этого :2019-10-12T07:20:50.52Z
. Добавление нуля в конце моей строки не помогает моей строке быть rfc3339. Есть ли способ правильно преобразовать его ?strptime()
здесь это не помогает, потому что оно преобразуется19551231
в1955-12-31 00:00:00
то, что все еще не принимаетсяfrom_rfc3339()
функцией.2. Плюс: функция
from_rfc3339()
возвращает a<class 'datetime.datetime'>
, а не a<class 'proto.datetime_helpers.DatetimeWithNanoseconds'>
3. Ой! Мы получим обратно микросекундное время даты и времени, которое не будет поддерживать наносекунду? Вздох!