ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:96377] [Ruby master Bug#16440] Date range inclusion behaviors are inconsistent
       [not found] <redmine.issue-16440.20191220162254@ruby-lang.org>
@ 2019-12-20 16:22 ` stan001212
  2019-12-20 17:28 ` [ruby-core:96378] " wishdev
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 7+ messages in thread
From: stan001212 @ 2019-12-20 16:22 UTC (permalink / raw)
  To: ruby-core

Issue #16440 has been reported by st0012 (Stan Lo).

----------------------------------------
Bug #16440: Date range inclusion behaviors are inconsistent
https://bugs.ruby-lang.org/issues/16440

* Author: st0012 (Stan Lo)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
It's weird that a Date range can include Time and DateTime objects that were converted from a Date object. But it can't include a newly generated DateTime object. For example:

```
may1 = Date.parse("2019-05-01")
may3 = Date.parse("2019-05-03")
noon_of_may3 = DateTime.parse("2019-05-03 12:00")
may31 = Date.parse("2019-05-31")

(may1..may31).include? may3 # => True
(may1..may31).include? may3.to_time # => True
(may1..may31).include? may3.to_datetime # => True
(may1..may31).include? noon_of_may3 # => False
```

Shouldn't the last case return `true` as well? 

Related Rails issue: https://github.com/rails/rails/issues/36175



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-core:96378] [Ruby master Bug#16440] Date range inclusion behaviors are inconsistent
       [not found] <redmine.issue-16440.20191220162254@ruby-lang.org>
  2019-12-20 16:22 ` [ruby-core:96377] [Ruby master Bug#16440] Date range inclusion behaviors are inconsistent stan001212
@ 2019-12-20 17:28 ` wishdev
  2019-12-20 17:55 ` [ruby-core:96379] " zverok.offline
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 7+ messages in thread
From: wishdev @ 2019-12-20 17:28 UTC (permalink / raw)
  To: ruby-core

Issue #16440 has been updated by wishdev (John Higgins).


Nothing strange with your example - but that doesn't mean it totally works right.

First your example is a DATE range - so adding this line

`(may1..may31).each { |x| puts x }`

That shows that your set is each day within the range at Midnight - therefore any other time is not included (and in fact on my system - the to_time option returns false instead of true).

BUT, on the other hand - one might imagine that something like

`may1 = DateTime.parse("2019-05-01")
may31 = DateTime.parse("2019-05-31")
noon_of_may3 = DateTime.parse("2019-05-03 12:00")
(may1..may31).include? noon_of_may3`

Should get a true for the include

It appears though, that DateTime ranges only use the exact Time each day of the range

`(may1..may31).each { |x| puts x }`

Shows this with the DateTime range.

So I don't believe there is an issue with the code as you have it - but there might be a conversation as to why a DateTime range does not appear to work for your example.

John



----------------------------------------
Bug #16440: Date range inclusion behaviors are inconsistent
https://bugs.ruby-lang.org/issues/16440#change-83299

* Author: st0012 (Stan Lo)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
It's weird that a Date range can include Time and DateTime objects that were converted from a Date object. But it can't include a newly generated DateTime object. For example:

```
may1 = Date.parse("2019-05-01")
may3 = Date.parse("2019-05-03")
noon_of_may3 = DateTime.parse("2019-05-03 12:00")
may31 = Date.parse("2019-05-31")

(may1..may31).include? may3 # => True
(may1..may31).include? may3.to_time # => True
(may1..may31).include? may3.to_datetime # => True
(may1..may31).include? noon_of_may3 # => False
```

Shouldn't the last case return `true` as well? 

Related Rails issue: https://github.com/rails/rails/issues/36175



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-core:96379] [Ruby master Bug#16440] Date range inclusion behaviors are inconsistent
       [not found] <redmine.issue-16440.20191220162254@ruby-lang.org>
  2019-12-20 16:22 ` [ruby-core:96377] [Ruby master Bug#16440] Date range inclusion behaviors are inconsistent stan001212
  2019-12-20 17:28 ` [ruby-core:96378] " wishdev
@ 2019-12-20 17:55 ` zverok.offline
  2019-12-21  3:51 ` [ruby-core:96383] " shevegen
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 7+ messages in thread
From: zverok.offline @ 2019-12-20 17:55 UTC (permalink / raw)
  To: ruby-core

Issue #16440 has been updated by zverok (Victor Shepelev).


`Range#include?` works as `#to_a.include?`. E.g. this:
```ruby
(may1..may31).include? noon_of_may3
# => false 
```
Is equivalent to this:
```ruby
dates = (may1..may31).to_a # => each Date between May 1 and 31
dates.include? noon_of_may3
# => false 
```
What works as you expect (compare value with range begin and end) is `Range#cover?`:
```ruby
(may1..may31).cover? noon_of_may3
# => true 
```

(To make things a bit more complicated, there is a special reimplementation for numbers, so `(1...2).include?(1.5)` is `true`.)

----------------------------------------
Bug #16440: Date range inclusion behaviors are inconsistent
https://bugs.ruby-lang.org/issues/16440#change-83300

* Author: st0012 (Stan Lo)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
It's weird that a Date range can include Time and DateTime objects that were converted from a Date object. But it can't include a newly generated DateTime object. For example:

```
may1 = Date.parse("2019-05-01")
may3 = Date.parse("2019-05-03")
noon_of_may3 = DateTime.parse("2019-05-03 12:00")
may31 = Date.parse("2019-05-31")

(may1..may31).include? may3 # => True
(may1..may31).include? may3.to_time # => True
(may1..may31).include? may3.to_datetime # => True
(may1..may31).include? noon_of_may3 # => False
```

Shouldn't the last case return `true` as well? 

Related Rails issue: https://github.com/rails/rails/issues/36175



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-core:96383] [Ruby master Bug#16440] Date range inclusion behaviors are inconsistent
       [not found] <redmine.issue-16440.20191220162254@ruby-lang.org>
                   ` (2 preceding siblings ...)
  2019-12-20 17:55 ` [ruby-core:96379] " zverok.offline
@ 2019-12-21  3:51 ` shevegen
  2019-12-21 15:05 ` [ruby-core:96389] " stan001212
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 7+ messages in thread
From: shevegen @ 2019-12-21  3:51 UTC (permalink / raw)
  To: ruby-core

Issue #16440 has been updated by shevegen (Robert A. Heiler).


I have no strong opinion either way but I can understand the 
assumption by st0012 to some extent. For example, I personally
always seem to think more about .include? than .cover?, largely
because I simply use .include? a lot more. I once even added
some .partial_include? method to Enumerable (or somewhere else,
I don't remember ... was years ago).

The other thing is DateTime, Date, and Time. Personally I'd love
if we could have just one-ring-to-rule-them-all one day, perhaps
in ruby 4.0 or so - I think that is a partial complaint by Stan,
in the sense of the behaviour he showed (but I am assuming this
here). But again, I have no real strong opinion either way.

Would be interesting to ask Stan Lo whether he knew about 
.cover? or not. :)

----------------------------------------
Bug #16440: Date range inclusion behaviors are inconsistent
https://bugs.ruby-lang.org/issues/16440#change-83306

* Author: st0012 (Stan Lo)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
It's weird that a Date range can include Time and DateTime objects that were converted from a Date object. But it can't include a newly generated DateTime object. For example:

```
may1 = Date.parse("2019-05-01")
may3 = Date.parse("2019-05-03")
noon_of_may3 = DateTime.parse("2019-05-03 12:00")
may31 = Date.parse("2019-05-31")

(may1..may31).include? may3 # => True
(may1..may31).include? may3.to_time # => True
(may1..may31).include? may3.to_datetime # => True
(may1..may31).include? noon_of_may3 # => False
```

Shouldn't the last case return `true` as well? 

Related Rails issue: https://github.com/rails/rails/issues/36175



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-core:96389] [Ruby master Bug#16440] Date range inclusion behaviors are inconsistent
       [not found] <redmine.issue-16440.20191220162254@ruby-lang.org>
                   ` (3 preceding siblings ...)
  2019-12-21  3:51 ` [ruby-core:96383] " shevegen
@ 2019-12-21 15:05 ` stan001212
  2019-12-21 15:25 ` [ruby-core:96390] " zverok.offline
  2019-12-29 19:10 ` [ruby-core:96581] " merch-redmine
  6 siblings, 0 replies; 7+ messages in thread
From: stan001212 @ 2019-12-21 15:05 UTC (permalink / raw)
  To: ruby-core

Issue #16440 has been updated by st0012 (Stan Lo).


To: wishdev (John Higgins)

> (and in fact on my system - the to_time option returns false instead of true).

Sorry that I accidentally tested my code in a Rails console instead of pure irb. The result for that case should be `false` on my machine as well.

Let me correct this:

```
may1 = Date.parse("2019-05-01")
may3 = Date.parse("2019-05-03")
noon_of_may3 = DateTime.parse("2019-05-03 12:00")
may31 = Date.parse("2019-05-31")

(may1..may31).include? may3 # => True
(may1..may31).include? may3.to_time # => False
(may1..may31).include? may3.to_datetime # => True
(may1..may31).include? noon_of_may3 # => False
```


To: zverok (Victor Shepelev) and  shevegen (Robert A. Heiler)

I think semantically, `cover` might be a better API for such cases. But I'm like `shevegen` don't use `cover` that often. In fact, I completely forgot about it!

However, I think my question of this issue is: 

Does a Date range represent a series of individual days between May 1st and May 31th, like `[2019-05-01 00:00:00, 2019-05-02 00:00:00..... 2019-05-31 00:00:00]` ? Or it represents a continuous time range that starts from May 1st's 00:00 to May 31th's 00:00?

If it's the first case, I can understand that `include?` doesn't return `true` for `noon_of_may3`. Because it's not at `00:00:00` of that day. But at the same time, I think it should return `true` for `(may1..may31).include? may3.to_time` as well because it's at `00:00:00` of that day.

```
may3.to_time #=> 2019-05-03 00:00:00 +0000
```

If it's the second case, we should make all 4 cases return `true` because they're all covered by the range.


What do you guys think?


----------------------------------------
Bug #16440: Date range inclusion behaviors are inconsistent
https://bugs.ruby-lang.org/issues/16440#change-83312

* Author: st0012 (Stan Lo)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
It's weird that a Date range can include Time and DateTime objects that were converted from a Date object. But it can't include a newly generated DateTime object. For example:

```
may1 = Date.parse("2019-05-01")
may3 = Date.parse("2019-05-03")
noon_of_may3 = DateTime.parse("2019-05-03 12:00")
may31 = Date.parse("2019-05-31")

(may1..may31).include? may3 # => True
(may1..may31).include? may3.to_time # => True
(may1..may31).include? may3.to_datetime # => True
(may1..may31).include? noon_of_may3 # => False
```

Shouldn't the last case return `true` as well? 

Related Rails issue: https://github.com/rails/rails/issues/36175



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-core:96390] [Ruby master Bug#16440] Date range inclusion behaviors are inconsistent
       [not found] <redmine.issue-16440.20191220162254@ruby-lang.org>
                   ` (4 preceding siblings ...)
  2019-12-21 15:05 ` [ruby-core:96389] " stan001212
@ 2019-12-21 15:25 ` zverok.offline
  2019-12-29 19:10 ` [ruby-core:96581] " merch-redmine
  6 siblings, 0 replies; 7+ messages in thread
From: zverok.offline @ 2019-12-21 15:25 UTC (permalink / raw)
  To: ruby-core

Issue #16440 has been updated by zverok (Victor Shepelev).


> Does a Date range represent a series of individual days between May 1st and May 31th, like `[2019-05-01 00:00:00, 2019-05-02 00:00:00..... 2019-05-31 00:00:00]` ? Or it represents a continuous time range that starts from May 1st's 00:00 to May 31th's 00:00?

It (Range in general, nothing special about date Range) represents both, depending on the context. 

* In Enumerable context (for example, if you'll try to do `(may1..may31).to_a`, or `.select` or `.any?`; or `include?`) it represents a series. 
* In the diapason context (`cover?`, `===`) it represents the entire space between beginning and end. That's true for every kind of range, and even if not entirely obvious always, is easy to explain and remember without edge cases (which the linked Rails PR tries to introduce: "if you don't know `include?` is discontinous, we got you covered, bro!").

> I think it should return true for `(may1..may31).include? may3.to_time`. 

The reason it doesn't is not related to the Range itself, but to the fact that `Date` is library class and `Time` is core class, and they are not compatible. This is also `false`:

```ruby
may3 == may3.to_time
# => false 
```

I hate this fact myself and tried to argue about it (that we need core `Date` class), but Powers That Be think about `date` as "scientific" dates library rarely needed, while Rails team and Rails users used to think about it as a generic "just date" class.

----------------------------------------
Bug #16440: Date range inclusion behaviors are inconsistent
https://bugs.ruby-lang.org/issues/16440#change-83313

* Author: st0012 (Stan Lo)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
It's weird that a Date range can include Time and DateTime objects that were converted from a Date object. But it can't include a newly generated DateTime object. For example:

```
may1 = Date.parse("2019-05-01")
may3 = Date.parse("2019-05-03")
noon_of_may3 = DateTime.parse("2019-05-03 12:00")
may31 = Date.parse("2019-05-31")

(may1..may31).include? may3 # => True
(may1..may31).include? may3.to_time # => True
(may1..may31).include? may3.to_datetime # => True
(may1..may31).include? noon_of_may3 # => False
```

Shouldn't the last case return `true` as well? 

Related Rails issue: https://github.com/rails/rails/issues/36175



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-core:96581] [Ruby master Bug#16440] Date range inclusion behaviors are inconsistent
       [not found] <redmine.issue-16440.20191220162254@ruby-lang.org>
                   ` (5 preceding siblings ...)
  2019-12-21 15:25 ` [ruby-core:96390] " zverok.offline
@ 2019-12-29 19:10 ` merch-redmine
  6 siblings, 0 replies; 7+ messages in thread
From: merch-redmine @ 2019-12-29 19:10 UTC (permalink / raw)
  To: ruby-core

Issue #16440 has been updated by jeremyevans0 (Jeremy Evans).

Status changed from Open to Rejected

As explained in some previous comments, if you want to check if a value is on or after the beginning of the range and on or before the end of the range, use `cover?`.  `include?` should only be used if you want to check the argument is one of the members of the range (i.e. included in the array returned by `to_a`).

----------------------------------------
Bug #16440: Date range inclusion behaviors are inconsistent
https://bugs.ruby-lang.org/issues/16440#change-83546

* Author: st0012 (Stan Lo)
* Status: Rejected
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-darwin19]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
It's weird that a Date range can include Time and DateTime objects that were converted from a Date object. But it can't include a newly generated DateTime object. For example:

```
may1 = Date.parse("2019-05-01")
may3 = Date.parse("2019-05-03")
noon_of_may3 = DateTime.parse("2019-05-03 12:00")
may31 = Date.parse("2019-05-31")

(may1..may31).include? may3 # => True
(may1..may31).include? may3.to_time # => True
(may1..may31).include? may3.to_datetime # => True
(may1..may31).include? noon_of_may3 # => False
```

Shouldn't the last case return `true` as well? 

Related Rails issue: https://github.com/rails/rails/issues/36175



-- 
https://bugs.ruby-lang.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-12-29 19:11 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <redmine.issue-16440.20191220162254@ruby-lang.org>
2019-12-20 16:22 ` [ruby-core:96377] [Ruby master Bug#16440] Date range inclusion behaviors are inconsistent stan001212
2019-12-20 17:28 ` [ruby-core:96378] " wishdev
2019-12-20 17:55 ` [ruby-core:96379] " zverok.offline
2019-12-21  3:51 ` [ruby-core:96383] " shevegen
2019-12-21 15:05 ` [ruby-core:96389] " stan001212
2019-12-21 15:25 ` [ruby-core:96390] " zverok.offline
2019-12-29 19:10 ` [ruby-core:96581] " merch-redmine

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).