Umesh Malhotra
Umesh Malhotra

Reputation: 1047

Not able to find start of 53rd week using method Date.commercial

Date.commercial method to find start of week (Monday) is not working for 53rd week

Date.commercial(2018, 1, 1)
#=> 2018-01-01
Date.commercial(2018, 52, 1)
#=> 2018-12-24

It throws error when I try to find Monday of 53rd week in years which has 53 weeks.

Date.commercial(2018, 53, 1)
# ArgumentError: invalid date

Also, its definition is also not clear to me. Like how these two are behaving so differently:

Date.commercial(2015, 1, 1)
#=> 2014-12-29

Date.commercial(2016, 1, 1)
#=> 2016-01-04

I think its because definition of Date.commercial() to convert week number to date is different from that of Date.strftime("%W"). Is there any method which can convert year's week number to Monday date of the week consistent with Date.strftime("%W"), i.e. reverse function of Date.strftime("%W")?

Upvotes: 1

Views: 999

Answers (2)

Stefan
Stefan

Reputation: 114218

Is there any method which can convert year's week number to Monday date of the week consistent with Date.strftime("%W"), i.e. reverse function of Date.strftime("%W")?

You could use strptime:

Date.strptime('2018-W53', '%Y-W%W')
#=> #<Date: 2018-12-31 ((2458484j,0s,0n),+0s,2299161j)>

Note that %W and %V (commercial week) are defined differently and produce different results.

%W is defined as:

The week 1 of YYYY starts with a Monday. The days in the year before the first week are in week 0.

%V is defined as:

The week 1 of YYYY starts with a Monday and includes YYYY-01-04. The days in the year before the first week are in the last week of the previous year.

Some examples:

Date.new(2018,  1,  1).strftime('%Y-W%W / %G-CW%V') #=> "2018-W01 / 2018-CW01"
Date.new(2018, 12, 31).strftime('%Y-W%W / %G-CW%V') #=> "2018-W53 / 2019-CW01"

Date.new(2019,  1,  1).strftime('%Y-W%W / %G-CW%V') #=> "2019-W00 / 2019-CW01"
Date.new(2019, 12, 31).strftime('%Y-W%W / %G-CW%V') #=> "2019-W52 / 2020-CW01"

Date.new(2020,  1,  1).strftime('%Y-W%W / %G-CW%V') #=> "2020-W00 / 2020-CW01"
Date.new(2020, 12, 31).strftime('%Y-W%W / %G-CW%V') #=> "2020-W52 / 2020-CW53"

Date.new(2021,  1,  1).strftime('%Y-W%W / %G-CW%V') #=> "2021-W00 / 2020-CW53"
Date.new(2021, 12, 31).strftime('%Y-W%W / %G-CW%V') #=> "2021-W52 / 2021-CW52"

Upvotes: 5

Amadan
Amadan

Reputation: 198436

From API docs:

the first calendar week of the year is the one that includes the first Thursday of that year. In the Gregorian calendar, this is equivalent to the week which includes January 4.

Thus, 2018 doesn't have 53 weeks. The last day of the last week of 2018 is:

Date.commercial(2018, 52, 7)
# => #<Date: 2018-12-30 ((2458483j,0s,0n),+0s,2299161j)> 

followed by the first week of 2019:

Date.commercial(2019, 1, 1)
# => #<Date: 2018-12-31 ((2458484j,0s,0n),+0s,2299161j)> 

You seem to be working under the premise that 2018-12-31 is in 2018. It is not, not in Commercial date. If you're going to use the commercial year instead of the calendar year, use %G, not %Y, to get the commercial year, and %V for the week instead of %W.

date2018_12_31 = Date.commercial(2019, 1, 1)
date2018_12_31.strftime("%Y %W")                  # WRONG
# => "2018 53"
date2018_12_31.strftime("%G %V")                  # CORRECT
# => "2019 01"

Upvotes: 4

Related Questions