mojombo / chronic

Chronic is a pure Ruby natural language date parser.
http://injekt.github.com/chronic
MIT License
3.23k stars 452 forks source link

Chronic doesn't take into consideration 1st date of the month when computing `nth day this month` #410

Closed zoras closed 8 months ago

zoras commented 1 year ago

Problem: When 1st date of the month falls on the same day where we query nth day this month, then 1st date day is ignored.

Chronic Gem version: 0.10.2

Demo:

For December 2020, there are 5 Tuesdays as seen in calendar below:

$ cal 12 2020
   December 2020
Su Mo Tu We Th Fr Sa
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
$ irb
irb(main):001:0> require 'chronic'
=> true
irb(main):002:0> date=Date.new(2020,12,1)
=> #<Date: 2020-12-01 ((2459185j,0s,0n),+0s,2299161j)>
irb(main):003:0> date.strftime('%A')
=> "Tuesday"
irb(main):004:0> Chronic.parse('1st tuesday this month', now: date)
=> 2020-12-08 12:00:00 +0100
irb(main):005:0> Chronic.parse('2th tuesday this month', now: date)
=> 2020-12-15 12:00:00 +0100
irb(main):006:0> Chronic.parse('3rd tuesday this month', now: date)
=> 2020-12-22 12:00:00 +0100
irb(main):007:0> Chronic.parse('4th tuesday this month', now: date)
=> 2020-12-29 12:00:00 +0100
irb(main):008:0> Chronic.parse('5th tuesday this month', now: date)
=> nil
irb(main):009:0> Chronic.parse('last tuesday this month', now: date)
=> nil

Here chronic doesn't know 1st date is the 1st Tuesday. Chronic assumes there are only 4 Tuesdays on the month instead of 5.

Another example for November 2020, where 1st date of the month falls on a Sunday.

$ cal 11 2020
   November 2020
Su Mo Tu We Th Fr Sa
 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
irb(main):011:0> date=Date.new(2020,11,1)
=> #<Date: 2020-11-01 ((2459155j,0s,0n),+0s,2299161j)>
irb(main):012:0> Chronic.parse('1st tuesday this month', now: date)
=> 2020-11-03 12:00:00 +0100
irb(main):013:0> Chronic.parse('1st sunday this month', now: date)
=> 2020-11-08 12:00:00 +0100
irb(main):014:0> Chronic.parse('2nd sunday this month', now: date)
=> 2020-11-15 12:00:00 +0100
irb(main):015:0> Chronic.parse('3rd sunday this month', now: date)
=> 2020-11-22 12:00:00 +0100
irb(main):016:0> Chronic.parse('4th sunday this month', now: date)
=> 2020-11-29 12:00:00 +0100
irb(main):017:0> Chronic.parse('5th sunday this month', now: date)
=> nil

Here, chronic returns 3rd date as 1st Tuesday but misses the fact that 1st Sunday is 1st date of the month. Please also note that this month has 5 Sundays as well and not 4.

zoras commented 8 months ago

I figured out that this issue can be resolved by passing context: :none

irb(main):003:0> date = Date.new(2020,12,1)
=> Tue, 01 Dec 2020
irb(main):004:0> date.strftime('%A')
=> "Tuesday"
irb(main):005:0> Chronic.parse('1st tuesday this month', now: date)
=> 2020-12-08 12:00:00 +0100
irb(main):006:0> Chronic.parse('1st tuesday this month', context: :none, now: date)
=> 2020-12-01 12:00:00 +0100