Magne
Magne

Reputation: 17243

Why does between? work differently for Date and DateTime in ruby?

The doc says:

between?(min, max) public

Returns true if the current object’s time is within the specified min and max time.

In Ruby:

>> DateTime.now.between?(DateTime.now, DateTime.now+1)
=> false
>> Date.today.between?(Date.today, Date.today+1)
=> true

By using .current in Rails the discrepancy becomes even clearer, since you'd especially assume this method would have similar behavior on DateTime and Date:

>> DateTime.current.between?(DateTime.current, DateTime.current+1)
=> false
>> Date.current.between?(Date.current, Date.current+1)
=> true

Is this intentional behavior? If so, why? It seems fairly odd that the behavior when dealing with the min edge of the interval is not idiosyncratic. Especially when considering that the max part is idiosyncratic:

>> DateTime.now.between?(DateTime.now-1, DateTime.now)
=> true
>> Date.today.between?(Date.today-1, Date.today)
=> true

Upvotes: 3

Views: 92

Answers (4)

Dmitry Cat
Dmitry Cat

Reputation: 475

Lets launch irb and run those code:

"#{DateTime.now.inspect} \n #{DateTime.now.inspect}"

Result'll be something like this:

#<DateTime: 2017-03-22T11:42:28+03:00 ((2457835j,31348s,373353553n),+10800s,2299161j)>
#<DateTime: 2017-03-22T11:42:28+03:00 ((2457835j,31348s,373449152n),+10800s,2299161j)>

As you can see, there is difference in nanoseconds (373353553n < 373449152n)

Lets imagine that difference is equal to 'x', and DateTime.now is equal to 'Now', then:

1) DateTime.now.between?(DateTime.now, DateTime.now+1.second)

Now.between?(Now+x, Now+x+x+1.second) => false

2) DateTime.now.between?(DateTime.now-1, DateTime.now)

Now.between?(Now+x-1.second, Now+x+x) => true

Upvotes: 5

Eric Duminil
Eric Duminil

Reputation: 54263

As others have mentioned :

a.between?(b,c)

a is interpreted a few milliseconds before b and c.

The shortest way to get the desired result would be :

(now=DateTime.now).between?(now, now+1)
#=> true

You could also reverse the order in which the DateTime objects are initialized :

(DateTime.now..DateTime.now+1).cover? DateTime.now
#=> true

Upvotes: 2

kgunbin
kgunbin

Reputation: 61

That is because times goes by. Your first DateTime.now, which you check against, is a couple of milliseconds before your second DateTime.now, in brackets.

Upvotes: 2

Deepak Mahakale
Deepak Mahakale

Reputation: 23671

Well it seems like its issue of few milliseconds

DateTime.now.between?(DateTime.now, DateTime.now+1)
^ executing first     ^ executing after few milliseconds or nanoseconds

The value of DateTime with what you are comparing is old than the DateTimevalue inbetween?`

But if you save it in variable

now = DateTime.now
now.between?(now,now+1)
#=> true

Also, as @ndn commented

DateTime.now ==  DateTime.now
#=> false

Upvotes: 1

Related Questions