Round datetime64 array to nearest second
Question:
I have an array of type datetime64[ns]. Each element looks something like '2019-08-30T14:02:03.684000000'
. How do I round the values to the nearest second such that I would obtain '2019-08-30T14:02:04'
in this example?
I know I can truncate the values by
t = t.astype('datetime64[s]')
but I specifically need to round the values and not truncate them. And the numpy ’round’ function doesn’t seem to like the datetime64[ns] data type.
Answers:
You can do it by converting np.datetime64 to datetime.datetime.
import numpy as np
from datetime import datetime, timedelta
dt64 = np.datetime64('2019-08-30T14:02:03.684000000')
# np to datetime object
ts = (dt64 - np.datetime64('1970-01-01T00:00:00Z')) / np.timedelta64(1, 's')
dt = datetime.utcfromtimestamp(ts)
# Rounding
if dt.microsecond/1000000 > 0.5:
date = (dt + timedelta(seconds=1)).replace(microsecond=0)
else:
date = dt.replace(microsecond=0)
# Datetime to np
date_rounded = np.datetime64(date).astype('datetime64[s]')
Output:
numpy.datetime64(‘2019-08-30T14:02:04’)
Another handy utility for rounding datetime64 by specified interval (‘accuracy’):
from datetime import datetime
from typing import Union
import numpy as np
UNIX_T0 = np.datetime64('1970-01-01T00:00:00')
def round_t64(time: Union[np.datetime64, datetime], dt: Union[np.timedelta64, int]):
"""
Round timestamp by dt
"""
if isinstance(dt, int):
dt = np.timedelta64(dt, 's')
if isinstance(time, datetime):
time = np.datetime64(time)
return time - (time - UNIX_T0) % dt
And use case:
# floor to 1 sec
round_t64(np.datetime64(datetime.now()), np.timedelta64(1, 's'))
# ceil to 1 sec
round_t64(np.datetime64(datetime.now()), -np.timedelta64(1, 's'))
# floor to 5 min
round_t64(np.datetime64(datetime.now()), np.timedelta64(5, 'm'))
I have an array of type datetime64[ns]. Each element looks something like '2019-08-30T14:02:03.684000000'
. How do I round the values to the nearest second such that I would obtain '2019-08-30T14:02:04'
in this example?
I know I can truncate the values by
t = t.astype('datetime64[s]')
but I specifically need to round the values and not truncate them. And the numpy ’round’ function doesn’t seem to like the datetime64[ns] data type.
You can do it by converting np.datetime64 to datetime.datetime.
import numpy as np
from datetime import datetime, timedelta
dt64 = np.datetime64('2019-08-30T14:02:03.684000000')
# np to datetime object
ts = (dt64 - np.datetime64('1970-01-01T00:00:00Z')) / np.timedelta64(1, 's')
dt = datetime.utcfromtimestamp(ts)
# Rounding
if dt.microsecond/1000000 > 0.5:
date = (dt + timedelta(seconds=1)).replace(microsecond=0)
else:
date = dt.replace(microsecond=0)
# Datetime to np
date_rounded = np.datetime64(date).astype('datetime64[s]')
Output:
numpy.datetime64(‘2019-08-30T14:02:04’)
Another handy utility for rounding datetime64 by specified interval (‘accuracy’):
from datetime import datetime
from typing import Union
import numpy as np
UNIX_T0 = np.datetime64('1970-01-01T00:00:00')
def round_t64(time: Union[np.datetime64, datetime], dt: Union[np.timedelta64, int]):
"""
Round timestamp by dt
"""
if isinstance(dt, int):
dt = np.timedelta64(dt, 's')
if isinstance(time, datetime):
time = np.datetime64(time)
return time - (time - UNIX_T0) % dt
And use case:
# floor to 1 sec
round_t64(np.datetime64(datetime.now()), np.timedelta64(1, 's'))
# ceil to 1 sec
round_t64(np.datetime64(datetime.now()), -np.timedelta64(1, 's'))
# floor to 5 min
round_t64(np.datetime64(datetime.now()), np.timedelta64(5, 'm'))