Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weirdness in week calculations. #21

Open
kentfredric opened this issue May 15, 2016 · 3 comments
Open

Weirdness in week calculations. #21

kentfredric opened this issue May 15, 2016 · 3 comments

Comments

@kentfredric
Copy link

Seems 2016 and 2017 have some issues.

The first week of 2016 really shouldn't be in Jan 2015 ...
The first week of 2017 really shouldn't be in Jan 2016 ... esp not around Jan 10 ...

perl -MTime::Moment -E' say Time::Moment->new( year => 2014 )->with_week(1) '
#2014-01-01T00:00:00Z
perl -MTime::Moment -E' say Time::Moment->new( year => 2015 )->with_week(1) '
#2015-01-01T00:00:00Z
perl -MTime::Moment -E' say Time::Moment->new( year => 2016 )->with_week(1) '
#2015-01-02T00:00:00Z
perl -MTime::Moment -E' say Time::Moment->new( year => 2017 )->with_week(1) '
#2016-01-10T00:00:00Z

Seems off by a year for the whole year

perl -MTime::Moment -E' say Time::Moment->new( year => 2016 )->with_week(25) '
#2015-06-19T00:00:00Z
perl -MTime::Moment -E' say Time::Moment->new( year => 2017 )->with_week(25) '
#2016-06-26T00:00:00Z
perl -MTime::Moment -E' say Time::Moment->new( year => 2018 )->with_week(25) '
#2018-06-18T00:00:00Z

Also disagrees with Date::ISO8601

perl -MDate::ISO8601 -E' say sprintf q[%s-%s-%s],  Date::ISO8601::cjdn_to_ymd( Date::ISO8601::ywd_to_cjdn( 2014, 1, 1 ) )'
#2013-12-30
perl -MDate::ISO8601 -E' say sprintf q[%s-%s-%s],  Date::ISO8601::cjdn_to_ymd( Date::ISO8601::ywd_to_cjdn( 2015, 1, 1 ) )'
#2014-12-29
perl -MDate::ISO8601 -E' say sprintf q[%s-%s-%s],  Date::ISO8601::cjdn_to_ymd( Date::ISO8601::ywd_to_cjdn( 2016, 1, 1 ) )'
#2016-1-4
perl -MDate::ISO8601 -E' say sprintf q[%s-%s-%s],  Date::ISO8601::cjdn_to_ymd( Date::ISO8601::ywd_to_cjdn( 2017, 1, 1 ) )'
#2017-1-2
perl -MDate::ISO8601 -E' say sprintf q[%s-%s-%s],  Date::ISO8601::cjdn_to_ymd( Date::ISO8601::ywd_to_cjdn( 2018, 1, 1 ) )'
#2018-1-1
@chansen
Copy link
Owner

chansen commented May 15, 2016

The ->with_week() method alters the week of the week based week year, not the calendar year. The week based year can deviate from the calendar year on the first and last week of the week based year:

$ perl -MTime::Moment -wE 'do {
    say Time::Moment->new(year => $_)
                    ->strftime("%Y-%m-%d | %G-W%V-%u") 
} for (2014..2018)'
2014-01-01 | 2014-W01-3
2015-01-01 | 2015-W01-4
2016-01-01 | 2015-W53-5
2017-01-01 | 2016-W52-7
2018-01-01 | 2018-W01-1

Please note that January 4th is always in the first week and the week based year does not deviate from the calendar year:

$ perl -MTime::Moment -wE 'do {
    say Time::Moment->new(year => $_)
                    ->with_day_of_year(4)
                    ->strftime("%Y-%m-%d | %G-W%V-%u")
} for (2014..2018)'
2014-01-04 | 2014-W01-6
2015-01-04 | 2015-W01-7
2016-01-04 | 2016-W01-1
2017-01-04 | 2017-W01-3
2018-01-04 | 2018-W01-4

perl -MTime::Moment -wE 'do {
    say Time::Moment->new(year => $_)
                    ->with_day_of_year(4)
                    ->with_week(25)
                    ->strftime("%Y-%m-%d | %G-W%V-%u")
} for (2014..2018)'
2014-06-21 | 2014-W25-6
2015-06-21 | 2015-W25-7
2016-06-20 | 2016-W25-1
2017-06-21 | 2017-W25-3
2018-06-21 | 2018-W25-4

Time::Moment is in agreement with Date::ISO8601:

$ perl -MTime::Moment -wE 'do {
    say Time::Moment->from_string("${_}-W01-1T00Z")
                    ->strftime("%Y-%m-%d | %G-W%V-%u")
} for (2014..2018)'
2013-12-30 | 2014-W01-1
2014-12-29 | 2015-W01-1
2016-01-04 | 2016-W01-1
2017-01-02 | 2017-W01-1
2018-01-01 | 2018-W01-1

The Wikipedia article ISO week date goes into further details.

@kentfredric
Copy link
Author

I am aware the first week of the year can occur in a different calendar year under ISO .

The confusion pertains to week turning up a whole 50+ weeks earlier than expected in 2016 and 2017

I'm guessing this is of course dependent on the fact ->new( year => y ) implying:

year => y, month => 1, day => 1 , and that by proxy having a week start in y - 1.

But I'm still not sure where its going wrong.

It would probably be more obvious to allow Time::Moment->new() to receive a week value, which in combination with only year and day ( maybe ), or some other simple syntax for defining a Time based on a week number.

@chansen
Copy link
Owner

chansen commented May 15, 2016

The reason it's 50+ weeks earlier in 2016 and 2017 is because the calendar date is the last week of the week based year (of the previous calendar year):

2016-01-01 | 2015-W53-5
2017-01-01 | 2016-W52-7

To construct an instance of Time::Moment set to Monday of the first week of the given week based year:

perl -MTime::Moment -wE 'do {
    say Time::Moment->new(year => $_, day => 4)
                    ->with_day_of_week(1)
                    ->strftime("%Y-%m-%d | %G-W%V-%u")
} for (2014..2018)'

2013-12-30 | 2014-W01-1
2014-12-29 | 2015-W01-1
2016-01-04 | 2016-W01-1
2017-01-02 | 2017-W01-1
2018-01-01 | 2018-W01-1

To construct an instance of Time::Moment set to Monday of the 25th week of the given week based year:

perl -MTime::Moment -wE 'do {
    say Time::Moment->new(year => $_, day => 4)
                    ->with_day_of_week(1)
                    ->with_week(25)
                    ->strftime("%Y-%m-%d | %G-W%V-%u")
} for (2014..2018)'

2014-06-16 | 2014-W25-1
2015-06-15 | 2015-W25-1
2016-06-20 | 2016-W25-1
2017-06-19 | 2017-W25-1
2018-06-18 | 2018-W25-1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants