kennethreitz / maya

Datetimes for Humans™
MIT License
3.41k stars 197 forks source link

Discrepancy Between Hour of Last Element Produced from maya.intervals(...) for Different Start and End Times #159

Open adamkpickering opened 6 years ago

adamkpickering commented 6 years ago

First of all, thanks for your work on this great library. I think I found a bug. When I run the following script:

#!/usr/bin/env python3

import maya
from datetime import timedelta

interval = timedelta(hours=1)

start1 = maya.parse('2018-05-31T16:13:38.439460Z')
end1 = maya.parse('2018-06-05T12:13:38.453775Z')
tests1 = list(maya.intervals(start=start1, end=end1, interval=interval))
print("Hour of start1: {}".format(start1.hour))
print("Hour of end1: {}".format(end1.hour))
print("Hour of first element of tests1: {}".format(tests1[0].hour))
print("Hour of last element of tests1: {}".format(tests1[len(tests1) - 1].hour))

print("-------------------")

start2 = maya.parse('2018-05-31T16:16:38.632940Z')
end2 = maya.parse('2018-06-05T03:16:39.709776Z')
tests2 = list(maya.intervals(start=start2, end=end2, interval=interval))
print("Hour of start2: {}".format(start2.hour))
print("Hour of end2: {}".format(end2.hour))
print("Hour of first element of tests2: {}".format(tests2[0].hour))
print("Hour of last element of tests2: {}".format(tests2[len(tests2) - 1].hour))

I get the output:

Hour of start1: 16
Hour of end1: 12
Hour of first element of tests1: 16
Hour of last element of tests1: 11
-------------------
Hour of start2: 16
Hour of end2: 3
Hour of first element of tests2: 16
Hour of last element of tests2: 3

As you can see the behaviour is inconsistent: the hour of end1 is 12 and the hour of the last element of tests1 is 11 (different), whereas the hour of end2 is 3 and the hour of the last element of tests2 is 3 (the same). I don't imagine this is how things are supposed to work - can anyone reproduce this?

adamkpickering commented 6 years ago

I found the source of my confusion. The seconds part of end2 in my example is about 1.1 seconds greater than the seconds part of start2. Since (as I have discovered after reading the source a bit) intervals are tracked by seconds, and the seconds part of end2 is greater than the seconds part of start2, we get another hour.

I can see why the code was written this way, but it seems like something that others are likely to have trouble with. Also, I can't think of a way to improve it other than documenting this. Perhaps we need a way of doing intervals by the hour/day/month etc in addition to by the second. Perhaps something using cron-like language...

timofurrer commented 5 years ago

Perhaps we need a way of doing intervals by the hour/day/month etc in addition to by the second.

Couldn't you just use start and end times which are precise to an hour? Without any minutes / seconds parts?

Also, I can't think of a way to improve it other than documenting this

Would you like to do that? Since you ran into it and figured it out you might be just the person for the task :) The docs/ folder is not yet populated with content, so I think the best place for now would be the docstring of the intervals function. What do you think?

github-actions[bot] commented 5 years ago

This Issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days