arrow-py / arrow

🏹 Better dates & times for Python
https://arrow.readthedocs.io
Apache License 2.0
8.71k stars 673 forks source link

Improve handling of imaginary datetimes #845

Closed systemcatch closed 4 years ago

systemcatch commented 4 years ago

Pull Request Checklist

Thank you for taking the time to improve Arrow! Before submitting your pull request, please check all appropriate boxes:

If you have any questions about your code changes or any of the points above, please submit your questions along with the pull request and we will try our best to help!

Description of Changes

closes #72

Pendulum example is now fixed.

(arrow) chris@ThinkPad:~/arrow$ python
Python 3.8.3 (default, Jul  7 2020, 18:57:36) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import arrow
>>> just_before = arrow.get(2013, 3, 31, 1, 55, "Europe/Paris")
>>> just_before = arrow.get(2013, 3, 31, 1, 55, tzinfo= "Europe/Paris")
>>> just_before
<Arrow [2013-03-31T01:55:00+01:00]>
>>> just_before.shift(minutes=+10)
<Arrow [2013-03-31T03:05:00+02:00]>

Range duplication no longer occurs.

>>> before = arrow.get('2018-03-10 23:00:00', 'YYYY-MM-DD HH:mm:ss', tzinfo='US/Pacific')
>>> after = arrow.get('2018-03-11 04:00:00', 'YYYY-MM-DD HH:mm:ss', tzinfo='US/Pacific')
>>> result=[ (t, t.to('utc')) for t in arrow.Arrow.range('hour', before, after) ]
>>> for r in result:
...     print(r)
... 
(<Arrow [2018-03-10T23:00:00-08:00]>, <Arrow [2018-03-11T07:00:00+00:00]>)
(<Arrow [2018-03-11T00:00:00-08:00]>, <Arrow [2018-03-11T08:00:00+00:00]>)
(<Arrow [2018-03-11T01:00:00-08:00]>, <Arrow [2018-03-11T09:00:00+00:00]>)
(<Arrow [2018-03-11T03:00:00-07:00]>, <Arrow [2018-03-11T10:00:00+00:00]>)
(<Arrow [2018-03-11T04:00:00-07:00]>, <Arrow [2018-03-11T11:00:00+00:00]>)

I was also considering wrapping dateutil's resolve_imaginary function as an utility method for our users.

codecov[bot] commented 4 years ago

Codecov Report

Merging #845 into master will not change coverage. The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##            master      #845   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            9         9           
  Lines         1786      1791    +5     
  Branches       307       308    +1     
=========================================
+ Hits          1786      1791    +5     
Impacted Files Coverage Δ
arrow/arrow.py 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 80aa80c...7d225c1. Read the comment docs.

systemcatch commented 4 years ago

First pass looks solid. Is this seriously all the places where we need to cover imaginary dates/times?

I think so, by fixing shift we can use it in range and span which then propagate to other methods.

Does this address https://github.com/arrow-py/arrow/issues/686 as well? If so, we should add a regression test for it.

No and looking at it I don't think that issue can be fixed in arrow. Those comparison results are baked into datetime itself.

systemcatch commented 4 years ago

@pganssle any thoughts to add here?

systemcatch commented 4 years ago

Should we also resolve imaginary datetimes if they are constructed via the arrow.get or arrow.Arrow?

I tend to think not as datetime lets you construct imaginary instances directly. Users might have a reason for needing them and with the new imaginary property it's easy to check it

systemcatch commented 4 years ago

Hey @jadchaar I've made the change you suggested, let me know if you're happy and I will merge this in.

jadchaar commented 4 years ago

Looks great! Ship it!