Why is arrow.now() not in a range containing today's day?

1.1k Views Asked by At

I am testing the ability, in arrow, to check whether a date is in a range of dates:

>>> arrow.get('06/09/2017', 'DD/MM/YYYY') in arrow.Arrow.range('day', arrow.get('06/09/2017', 'DD/MM/YYYY'), arrow.get('06/07/2018', 'DD/MM/YYYY'))
True

>>> arrow.get('06/09/2017', 'DD/MM/YYYY') in arrow.Arrow.range('day', arrow.get('07/09/2017', 'DD/MM/YYYY'), arrow.get('06/07/2018', 'DD/MM/YYYY'))
False

So far so good. I then tried to use .now() in the same construction (today is 6 Sept 2017, the date in the tests above):

>>> arrow.now()
<Arrow [2017-09-06T21:09:02.402790+02:00]>

>>> arrow.now() in arrow.Arrow.range('day', arrow.get('06/09/2017', 'DD/MM/YYYY'), arrow.get('06/07/2018', 'DD/MM/YYYY'))
False

Why is the result False despite .now() being in the range?

>>> arrow.Arrow.range('day', arrow.get('06/09/2017', 'DD/MM/YYYY'), arrow.get('06/07/2018', 'DD/MM/YYYY'))
[<Arrow [2017-09-06T00:00:00+00:00]>, <Arrow [2017-09-07T00:00:00+00:00]>, ...
2

There are 2 best solutions below

0
On BEST ANSWER

The way your range is currently constructed is by using a 'day' as your range's frame parameter so, unless your query manages to land exactly at midnight, checking for it the range is going to return False.

Within Arrow itself, the simplest option is probably to use floor() or ceiling() to normalize your query to how the range is constructed:

>> myrange = arrow.Arrow.range('day', arrow.get('06/09/2017', 'DD/MM/YYYY'), arrow.get('06/07/2018', 'DD/MM/YYYY'), tz='local')
>> arrow.now().floor('day') in myrange
True

Note that I've changed the tz parameter to 'local' so the comparison to arrow.now() is correct. I personally try to do everything with UTC or epoch time rather than keeping track of timezones.

Alternatively, you can do a simple logical check to see if the current time is after than your range's minimum and before your range's maximum:

>> myrange = arrow.Arrow.range('day', arrow.get('06/09/2017', 'DD/MM/YYYY'), arrow.get('06/07/2018', 'DD/MM/YYYY'), tz='local')
>> myrange[0] <= arrow.now() <= myrange[-1]
True
0
On

This should give you what you want:

>>> arrow.utcnow().floor('day') in arrow.Arrow.range('day', arrow.get('05/09/2017', 'DD/MM/YYYY'), arrow.get('06/07/2018', 'DD/MM/YYYY'))
True

The key is in the floor() method of the Arrow class: this limits your Arrow object and is required because (as @excaza mentioned) the range gives you day objects at midnight.

I used the utcnow() method instead of the now() method because your arrow.get() usage creates utc dates.