Rounding time in Python
What would be an elegant, efficient and Pythonic way to perform a h/m/s rounding operation on time related types in Python with control over the rounding resolution?
My guess is that it would require a time modulo operation. Illustrative examples:
- 20:11:13 % (10 seconds) => (3 seconds)
- 20:11:13 % (10 minutes) => (1 minutes and 13 seconds)
Relevant time related types I can think of:
datetime.datetime
\datetime.t开发者_如何学编程ime
struct_time
For a datetime.datetime rounding, see this function: https://stackoverflow.com/a/10854034/1431079
Sample of use:
print roundTime(datetime.datetime(2012,12,31,23,44,59,1234),roundTo=60*60)
2013-01-01 00:00:00
How about use datetime.timedelta
s:
import time
import datetime as dt
hms=dt.timedelta(hours=20,minutes=11,seconds=13)
resolution=dt.timedelta(seconds=10)
print(dt.timedelta(seconds=hms.seconds%resolution.seconds))
# 0:00:03
resolution=dt.timedelta(minutes=10)
print(dt.timedelta(seconds=hms.seconds%resolution.seconds))
# 0:01:13
This will round up time data to a resolution as asked in the question:
import datetime as dt
current = dt.datetime.now()
current_td = dt.timedelta(
hours = current.hour,
minutes = current.minute,
seconds = current.second,
microseconds = current.microsecond)
# to seconds resolution
to_sec = dt.timedelta(seconds = round(current_td.total_seconds()))
print(dt.datetime.combine(current, dt.time(0)) + to_sec)
# to minute resolution
to_min = dt.timedelta(minutes = round(current_td.total_seconds() / 60))
print(dt.datetime.combine(current, dt.time(0)) + to_min)
# to hour resolution
to_hour = dt.timedelta(hours = round(current_td.total_seconds() / 3600))
print(dt.datetime.combine(current, dt.time(0)) + to_hour)
You can convert both times to seconds, do the modulo operati
from datetime import time
def time2seconds(t):
return t.hour*60*60+t.minute*60+t.second
def seconds2time(t):
n, seconds = divmod(t, 60)
hours, minutes = divmod(n, 60)
return time(hours, minutes, seconds)
def timemod(a, k):
a = time2seconds(a)
k = time2seconds(k)
res = a % k
return seconds2time(res)
print(timemod(time(20, 11, 13), time(0,0,10)))
print(timemod(time(20, 11, 13), time(0,10,0)))
Outputs:
00:00:03
00:01:13
I use following code snippet to round to the next hour:
import datetime as dt
tNow = dt.datetime.now()
# round to the next full hour
tNow -= dt.timedelta(minutes = tNow.minute, seconds = tNow.second, microseconds = tNow.microsecond)
tNow += dt.timedelta(hours = 1)
I think I'd convert the time in seconds, and use standard modulo operation from that point.
20:11:13 = 20*3600 + 11*60 + 13
= 72673 seconds
72673 % 10 = 3
72673 % (10*60) = 73
This is the easiest solution I can think about.
Here is a lossy* version of hourly rounding:
dt = datetime.datetime
now = dt.utcnow()
rounded = dt.utcfromtimestamp(round(now.timestamp() / 3600, 0) * 3600)
Same principle can be applied to different time spans.
*The above method assumes UTC is used, as any timezone information will be destroyed in conversion to timestamp.
You could also try pandas.Timestamp.round:
import datetime
import pandas as pd
t = datetime.datetime(2012,12,31,23,44,59,1234)
print(pd.to_datetime(t).round('1min'))
% Timestamp('2012-12-31 23:45:00')
You can perform the following if you want to change the result back to datetime format:
pd.to_datetime(t).round('1min').to_pydatetime()
% datetime.datetime(2012, 12, 31, 23, 45)
精彩评论