Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Another date question

by sshingor (Initiate)
on Aug 27, 2018 at 10:06 UTC ( #1221170=perlquestion: print w/replies, xml ) Need Help??

sshingor has asked for the wisdom of the Perl Monks concerning the following question:

Hello Perl gurus,

I did read few threads on PerMonks before posting this question here.

Friday 01-01-2016, starts and ends the week. Inspite of this being the first day in the first week of year, the week indicated by DateTime is 53.

I also tried using localtime function and evantually calculating week# based of yearday. Although, it returns week 1, the calculation based on yearday, returns week 1 for the week beginning 04/01/2016 - 08/01/2016, which is actually week 2.

cal -w 1 2016 command starts with week 1 and goes on .. finally shows last week of 2016 as week 53, which as per me is correct.

I think most of you would agree that the cal command output is correct.

Question is, how do I get it right in perl ?

==== #!/usr/bin/env perl #use 5.012; use strict; use warnings; use DateTime; use Time::Local; my $dt = DateTime->new(year => 2016, month => 1, day => 1); print "DateTIme confirms that 01-01-2016 was a => " . $dt->day_name . +"\n"; print "DateTime return the Week no for 01-01-2016 => " . $dt->week . " +\n"; $dt = DateTime->new(year => 2016, month => 1, day => 4); print "DateTIme confirms that 04-01-2016 was a => " . $dt->day_name . +"\n"; print "DateTime return the Week no for 04-01-2016 => " . $dt->week . " +\n"; my ($MONTHDAY, $WEEKDAY, $YEARDAY) = (localtime (timelocal(0,0,0,1,0,2 +016)))[3,6,7]; my $WEEKNUM = int($YEARDAY / 7) + 1; print "using localtime to calculate weekno (01/01/2016) => " . $WEEKNU +M . "\n"; ($MONTHDAY, $WEEKDAY, $YEARDAY) = (localtime (timelocal(0,0,0,4,0,2016 +)))[3,6,7]; $WEEKNUM = int($YEARDAY / 7) + 1; print "using localtime to calculate weekno (04/01/2016) => " . $WEEKNU +M . "\n"; print "UNIX system cal command output for 1st month \n"; system("cal -w 1 2016"); ===

Output:

Perl DateTIme confirms that 01-01-2016 was a => Friday
Perl DateTime return the Week no for 01-01-2016 => 53

Perl DateTIme confirms that 04-01-2016 was a => Monday
Perl DateTime return the Week no for 04-01-2016 => 1

using localtime to calculate weekno (01/01/2016) => 1
using localtime to calculate weekno (04/01/2016) => 1

UNIX system cal command output for 1st month

January 2016

Su Mo Tu We Th Fr Sa

1 1 2

2 3 4 5 6 7 8 9

3 10 11 12 13 14 15 16

4 17 18 19 20 21 22 23

5 24 25 26 27 28 29 30

6 31

Replies are listed 'Best First'.
Re: Another date question
by haukex (Bishop) on Aug 27, 2018 at 10:28 UTC
    I think most of you would agree that the cal command output is correct.

    That depends... Wikipedia says that the ISO week number 1 "has 4 January in it." So it appears to me that your output of the cal command does not correspond to that definition, and in fact cal (or rather, ncal, since my cal doesn't have -w) on my system outputs something different:

    $ ncal -w 1 2016 Januar 2016 Mo 4 11 18 25 Di 5 12 19 26 Mi 6 13 20 27 Do 7 14 21 28 Fr 1 8 15 22 29 Sa 2 9 16 23 30 So 3 10 17 24 31 53 1 2 3 4

    Is your cal's -w option perhaps giving you the "week of month"? (DateTime's ->week_of_month, see also)

    So DateTime's output for ->week_number seems to match the ISO definition:

    use warnings; use strict; use DateTime; my $dt = DateTime->new(year=>2015,month=>12,day=>30); for (1..10) { print $dt->ymd, " week ",$dt->week_number,"\n"; $dt->add(days=>1); } __END__ 2015-12-30 week 53 2015-12-31 week 53 2016-01-01 week 53 2016-01-02 week 53 2016-01-03 week 53 2016-01-04 week 1 2016-01-05 week 1 2016-01-06 week 1 2016-01-07 week 1 2016-01-08 week 1

    If you have a different definition of "week number" from those two (week of month, or ISO week), you'll have to define that clearly, and then there's probably a way to do some DateTime math to derive that week number.

Re: Another date question
by Corion (Pope) on Aug 27, 2018 at 10:33 UTC

    As documented, the ->week() method is defined as follows:

    The first week of the year is defined by ISO 8601 as the one which contains the fourth day of January, which is equivalent to saying that it's the first week to overlap the new year by at least four days.

    Given that definition, I think your expectation is wrong, as that week belongs to week 53 of 2015.

    If you want a different definition than what ISO 8601 defines, maybe say that the week number is the number of Fridays that have passed since (and including) the start of the year, then you will have to write some code.

Re: Another date question
by thanos1983 (Parson) on Aug 27, 2018 at 11:00 UTC

    Hello sshingor,

    Welcome to the Monastery. I will agree with the fellow Monks that have already replied to your question. Just to add something minor here on how the week numbers are calculated.

    Read the documentation from ISO_8601/Week_dates:

    Minor sample of code with Date::Manip:

    Hope this helps, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!

      I agree with others that in most cases, you're better off sticking with the ISO 8601 definitions. But, just in case you're interested, Date::Manip defaults to ISO 8601, but you can specify other definitions of week using some of the config variables that are built in. For example:

      • FirstDay can be used to specify a different day of the week as the first day
      • Jan1Week1 can be used to say that Jan 1 is in the first week of the year
      Most of the time I would discourage using these... but they are there if you need them.

        Hello SBECK,

        Thanks a lot for this information I had no idea about that. Just to add more information in case that someone is interested those variables can be set at the config file. More information can be found in the official documentation Date::Manip::Config/BASIC CONFIGURATION VARIABLES.

        Update: Just for future reference in case that someone is interested to overwrite the ISO 8601 (not recommended). As fellow Monk SBECK indicated we can use the Jan1Week1=1 a small sample of code:

        #!/usr/bin/perl use strict; use warnings; use Date::Manip; use feature 'say'; my $datestr = ParseDate("01/01/2016"); say UnixDate($datestr,"%J"); Date_Init("Jan1Week1=1"); say UnixDate($datestr,"%J"); __END__ $ perl test.pl 2015-W53-5 2016-W01-5

        In case that someone does not want to define the config file is can load the configurations like this. More information on the official documentation. Sample of config file can be found here Date::Manip::ConfigFile - sample config file.

        BR / Thanos

        Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: Another date question
by sshingor (Initiate) on Aug 27, 2018 at 11:31 UTC

    Thanks to all of you for your time and suggestion.

    I'll concentrate on the ISO date format in order to perform the date calculateion

    Kind regards

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1221170]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (7)
As of 2020-11-24 00:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?