Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing datetime strings containing nanoseconds

I have some log files with times in the format HH:MM::SS.nano_seconds (e.g. 01:02:03.123456789). I would like to create a datetime in python so I can neatly do math on the time (e.g. take time differences). strptime works well for microseconds using %f. Do the Python datetime and time modules really not support nanoseconds?

like image 615
user1332148 Avatar asked May 16 '12 02:05

user1332148


People also ask

What is one nano second?

A nanosecond (ns or nsec) is one billionth (10-9) of a second and is a common measurement of read or write access time to random access memory (RAM). Admiral Grace Hopper famously handed out foot-long lengths of wire to students to illustrate how far an electrical signal can travel in a nanosecond.

How do you make a nanosecond in Python?

time_ns() method of Time module is used to get the time in nanoseconds since the epoch. To get the time in seconds since the epoch, we can use time. time() method.

What is the format of datetime?

For example, the "d" standard format string indicates that a date and time value is to be displayed using a short date pattern. For the invariant culture, this pattern is "MM/dd/yyyy". For the fr-FR culture, it is "dd/MM/yyyy". For the ja-JP culture, it is "yyyy/MM/dd".


3 Answers

You can see from the source that datetime objects don't support anything more fine than microseconds. As pointed out by Mike Pennington in the comments, this is likely because computer hardware clocks aren't nearly that precise. Wikipedia says that HPET has frequency "at least 10 MHz," which means one tick per 100 nanoseconds.

If you can live with throwing out the last three digits (which probably aren't too meaningful anyway), you could parse this by just slicing the input string to have only six digits after the decimal point and parsing with %f. Otherwise, it looks like you'll have to implement the subtraction yourself.


Much later update: numpy and pandas now each have (somewhat different) support for timestamps that includes the possibility of tracking nanoseconds, which are often good solutions. See the other answers for how.

Python 3.7+ also has time.time_ns and related functions in time (PEP 564), but still no support for nanoseconds in datetime.

like image 122
Danica Avatar answered Sep 29 '22 07:09

Danica


This is an old thread, but still...

You can use Pandas functionality to achieve this. I had timestamps like '2019-03-22T14:00:01.700311864Z' which I converted to a Timestamp by:

    firstStamp = pd.to_datetime(firstStampString, format='%Y-%m-%dT%H:%M:%S.%fZ')
    lastStamp = pd.to_datetime(lastStampString, format='%Y-%m-%dT%H:%M:%S.%fZ')

    deltaTime = lastStamp - firstStamp

This works fine.

like image 25
WolfiG Avatar answered Sep 29 '22 07:09

WolfiG


You can quite naturally use nanoseconds and even more precise time units (ps, fs, as) with numpy. Numpy has its own Datetimes and Timedeltas implementation, so you can try np.datetime64:

import numpy as np
def str_to_ns(time_str):
     """
     input: time in a format `hh:mm:ss.up_to_9_digits`
     """
     h, m, s = time_str.split(":")
     int_s, ns = s.split(".")
     ns = map(lambda t, unit: np.timedelta64(t, unit),
              [h,m,int_s,ns.ljust(9, '0')],['h','m','s','ns'])
     return sum(ns)

Then you can use this function in a following way:

>>> src = "1:2:34.123456789"
>>> out = str_to_ns(src)
>>> print(out)
3754123456789 nanoseconds
>>> out / np.timedelta64(1,'h')
1.0428120713302778
>>> out / np.timedelta64(1,'m')
62.568724279816664
>>> out / np.timedelta64(1,'s')
3754.123456789

Arithmetic is also possible:

>>> t1, t2 = str_to_ns("1:0:12.12345678"), str_to_ns("1:0:12.12")
>>> t1 - t2
numpy.timedelta64(3456780,'ns')

I agree that it's not that natural, but in this manner you can achieve arbitrary high time precision with just numpy.

like image 34
Yury Kirienko Avatar answered Sep 29 '22 08:09

Yury Kirienko