Как сохранить микросекунды при преобразовании десятичных меток времени в дату-время? - PullRequest
0 голосов
/ 23 сентября 2018

У меня есть такие значения, как отметки времени из библиотеки dpkt (когда приходят пакеты):

for ts, buffer in dpkt.pcap.Reader(file):
    #whatever...    

Считыватель выдает ts в десятичном формате, например:

print(repr(ts))
Decimal('1536310893.687185000')

Я пытаюсьпреобразовать его в datetime, но я не получаю микросекунд (на самом деле наносекунды, но сейчас важны только микросекунды)

ts_dt = datetime.datetime.utcfromtimestamp(ts) 
ts_dt
datetime.datetime(2018, 9, 7, 9, 1, 33)

По какой-то причине utcfromtimestamp не учитывает дробную часть десятичной дробизначения.

Это ошибка?Это работало в Python 2.7

Я могу конвертировать Decimal в float, и это работает вроде как, но я ненавижу этот подход - поплавки имеют ограниченную точность.Скорее всего, в некоторых версиях это будет нарушено из-за незначительных изменений, или у меня будут неточные значения, что может привести к катастрофе, и устранение проблем будет огромной болью ... Я предпочитаю иметь точные значения и точные расчеты, когда это возможно (особеннов такой мелочи, как преобразование меток времени) ...

Так как сохранить микросекунды при конвертации Decimal меток времени в datetime?

Ответы [ 4 ]

0 голосов
/ 25 сентября 2018

На основе добрых ответов других, я использую этот код:

def datetime_from_decimal(timestamp):
    if isinstance(timestamp, Decimal):
        whole, fractional = divmod(timestamp, 1)
        mcs = int(fractional * 1000000)
        return datetime.datetime.utcfromtimestamp(whole).replace(microsecond = mcs)
    else:
        return datetime.datetime.utcfromtimestamp(timestamp)


datetime_from_decimal(Decimal('1536310895.988003000'))
datetime.datetime(2018, 9, 7, 9, 1, 35, 988003)
0 голосов
/ 23 сентября 2018

Почему вы делаете это десятичным?Тип данных float работает нормально.

>>> import datetime
>>> ts = 1536310893.687185000
>>> ts_dt = datetime.datetime.utcfromtimestamp(ts)
>>> ts_dt
datetime.datetime(2018, 9, 7, 9, 1, 33, 687185)
0 голосов
/ 23 сентября 2018

Не знаю, почему это не работает в Python3.6 +, но один из способов сделать преобразование без плавающей запятой - использовать datetime.replace() для установки микросекунд, например:

Код:

ts_dt = dt.datetime.utcfromtimestamp(ts).replace(microsecond=(ts - int(ts)) * 1000000)

Код теста:

import datetime as dt

ts_dt = dt.datetime.utcfromtimestamp(ts)
print(ts_dt)

ts_dt = dt.datetime.utcfromtimestamp(ts).replace(microsecond=(ts - int(ts)) * 1000000)
print(ts_dt)

Результаты:

2018-09-07 09:01:33
2018-09-07 09:01:33.687185
0 голосов
/ 23 сентября 2018

Почему вы используете Decimal.Кажется, что десятичные числа преобразуются в int перед использованием в datetime.Конвертируйте его явно в число с плавающей точкой:

ts_dt = datetime.datetime.utcfromtimestamp(foat(ts))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...