0

I need to find the next datetime which is multiple than 5, here is an example:

if the actual time is 12:18, the variable next should be 12:20, if it's 12:20:01, the variable next should have the value 12:25 and so on.

Is there any way to do this? Right now i managed to do this:

time = datetime.datetime.now()
min = time.minute
next = 5-(min%5)

print(next)

But this will only count how much time there is until the next multiple of 5. Any advice is appreciated!

San9096
  • 231
  • 4
  • 12
  • Does this answer your question? [Ceil a datetime to next quarter of an hour](https://stackoverflow.com/questions/13071384/ceil-a-datetime-to-next-quarter-of-an-hour). See, for example, this answer: https://stackoverflow.com/a/32657466/7851470 `ceil_dt(datetime.now(), timedelta(minutes=5))` will do the job. – Georgy May 19 '20 at 12:01

3 Answers3

1

Something like this

from datetime import datetime, timedelta

def round_by_five(time):
    if time.second == 0 and time.microsecond == 0 and time.minute % 5 == 0:
        return time
    minutes_by_five = time.minute // 5
    # get the difference in times
    diff = (minutes_by_five + 1) * 5 - time.minute
    time = (time + timedelta(minutes=diff)).replace(second=0, microsecond=0)
    return time

time = datetime.now()
round_by_five(time)
  • Fair enough! This works without any proble, thank you! – San9096 May 19 '20 at 10:42
  • I think i found a bug: when it's the minute is :55, it will go one hour behind: for example 12:55 will give 12:00 instead of 13:00 and so on – San9096 May 19 '20 at 11:14
  • This does not work when current minutes are multiples of 5: [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55]. The answer makes it increase by 5 minutes more, which is incorrect in this case. – CypherX May 19 '20 at 11:16
1

Solution

Try this. If ts is your datetime object,

ts.replace(second=0, microsecond=0) + timedelta(minutes=ceil(ts.minute/5)*5)

Example

from math import ceil
from datetime import datetime, timedelta

ts = datetime.now()
print(f'BEFORE: {ts}')
ts = ts.replace(second=0, microsecond=0) + timedelta(minutes=ceil(ts.minute/5)*5)
print(f'AFTER: {ts}')

Output:

BEFORE: 2020-05-19 10:41:33.071380
AFTER: 2020-05-19 10:45:00

Cases tested with

minutes = [33, 35, 37, 39, 40, 41, 43, 45]
expected = [35, 35, 40, 40, 40, 45, 45, 45]

tests = []
for m, e in zip(minutes, expected):
    err = ceil(m/5)*5 - e
    if err!=0:
        tests.append({'m': m, 'e': e, 'err': err})
if tests:
    print("Tests FAILED: \n")
    for test in tests: print(f" {test}")
else:
    print("ALL Tests PASSED.")

## Output
# ALL Tests PASSED.
CypherX
  • 7,019
  • 3
  • 25
  • 37
  • @San9096 Here is another way. Only requires `datetime.datetime`. – CypherX May 19 '20 at 10:45
  • this correctly catches cases where minute%5 == 0 while seconds / microseconds are also == 0 – FObersteiner May 19 '20 at 10:58
  • Hey, thank you for your answer! I have one problem, i tried to set the variable ts to datetime.datetime(2020, 5, 19, 12, 50), and the output was 12:50 in both cases, am i doing something wrong? – San9096 May 19 '20 at 11:17
  • @San9096 Try this: `ts = datetime(year=2020, month=5, day=19, hour=12, minute=50, second=0, microsecond=0)` – CypherX May 19 '20 at 11:23
  • You need to save the `ts.replace()` as `ts`. `ts = ts.replace(...)` – CypherX May 19 '20 at 11:30
  • @San9096 I had updated the solution. Involves: `datetime`, `timedelta` and `ceil`. Please check it out. – CypherX May 19 '20 at 12:07
  • 1
    Sorry for the delay! Here is what i got with the newest snippet of code: File "tm.py", line 6, in ts = ts.replace(second=0, microsecond=0) + timedelta(minute=ceil(ts.minute/5)*5) TypeError: 'minute' is an invalid keyword argument for __new__() – San9096 May 19 '20 at 12:13
  • Ok. Change the `minute` to `minutes`. – CypherX May 20 '20 at 03:47
  • Updated solution posted. There was a typo earlier. Please check now. – CypherX May 20 '20 at 03:51
0

This does exactly what you want:

from datetime import datetime
time = datetime.now()
min = (time.minute // 5 + 1) * 5
next = time.replace(minute=0,second=0, microsecond=0)+timedelta(minutes=min)
print(next)