Given a datetime object, how do I round it up to the next occurrence of 8AM PST?
Asked
Active
Viewed 863 times
2
-
1Make a new datetime, use input from the current datetime year, month, day and set hours, mins, seconds as 8, 0, 0 respectively – Ian Feb 24 '16 at 18:16
-
2@Ian: This would always be today's 8AM. To always round up, you need to add another day on top unless it is before 8AM. – jsfan Feb 24 '16 at 18:19
-
related: [Rounding up to nearest 30 minutes in python](http://stackoverflow.com/q/32723150/4279) – jfs Feb 25 '16 at 12:46
3 Answers
3
Just test whether the time is before or after 8, then add a day if it's after and construct a new datetime.
import datetime
def round_datetime(dt):
t = datetime.time(8)
# If time is after 8am, add a day.
if dt.time() > datetime.time(8):
dt += datetime.timedelta(days=1)
return datetime.datetime.combine(dt, t)

Brendan Abel
- 35,343
- 14
- 88
- 118
-
1Thanks, I didn't realize you could split up the date and time like that. – camomilk Feb 24 '16 at 19:49
-
1if the input is a timezone-aware datetime object then it is more complex (your code is ok if the input is a naive datetime object). – jfs Feb 25 '16 at 12:41
3
If the result is a timezone-aware datetime object in a timezone with a non-fixed UTC offset then you can't just call .replace()
or .combine()
-- it may create a datetime with a wrong UTC offset. The issue is similar to How do I get the UTC time of "midnight" for a given timezone? (00:00
is used instead of 08:00
).
Assuming 8AM always exists and unambiguous in PST:
from datetime import datetime, time as datetime_time, timedelta
import pytz # $ pip install pytz
def next_8am_in_pst(aware_dt, tz=pytz.timezone('America/Los_Angeles')):
pst_aware_dt = tz.normalize(aware_dt.astimezone(tz)) # convert to PST
naive_dt = round_up_to_8am(pst_aware_dt.replace(tzinfo=None))
return tz.localize(naive_dt, is_dst=None)
def round_up_to_8am(dt):
rounded = datetime.combine(dt, datetime_time(8))
return rounded + timedelta(rounded < dt)
Example:
>>> str(next_8am_in_pst(datetime.now(pytz.utc)))
'2016-02-25 08:00:00-08:00'
0
I made an answer based on some ideas from the comments:
def nextDay(d):
pstTime = d.astimezone(pytz.timezone('US/Pacific'))
pstTime = pstTime.replace(hour=8, minute=0, second=0, microsecond=0)
if pstTime < d:
pstTime += datetime.timedelta(days=1)
return pstTime

camomilk
- 763
- 1
- 7
- 15