http://qs1969.pair.com?node_id=705315
Category: Miscellaneous
Author/Contact Info Sander Venema <sander.venema@gmail.com>
Description: This is a small Perl script to calculate the number of the week from any given date.

This is a small Perl script to calculate the number of the week from any given date, (given in the ISO 8601 format), or uses today's date if no date is specified. It was written just to scratch an itch I had in the past, when I frequently needed to know the number of the week for planning purposes.

See the POD for more information about how it works. This is the first time I share my code here on PerlMonks, and any comments, suggestions or improvements are greatly appreciated.

#!/usr/bin/perl -w
#
# calcweek.pl - Calculate the week number from any given date, 
# or the default, if no date is given.
#
# Sander Venema <sander.venema@gmail.com> version 20080819

use strict;
use Getopt::Long;
use Pod::Usage;
use Data::Dumper;
use Date::ISO;
use POSIX qw(strftime);

# set some defaults
my $verbose    = 0;
my $date      = strftime("%Y%m%d", localtime);

# fetch options
Getopt::Long::Configure(qw(no_ignore_case bundling));
GetOptions(
    'h|help'        => sub { pod2usage({-verbose => 1, -input => \*DAT
+A}); exit; },
    'H|man'            => sub { pod2usage({-verbose => 2, -input => \*
+DATA}); exit; },
    'v|verbose'        => \$verbose,
    'd|date=i'        => \$date,
) or pod2usage(2);

# convert date string to Date::ISO object and calculate the
# year, week and number of the day (starting with Monday)
my $iso                      = Date::ISO->new(iso => $date);
my ($year, $week, $week_day) = ($iso->year, $iso->iso_week, $iso->iso_
+week_day);
    
# print everything, depending on level of $verbose
print "$year-W$week-$week_day\n" if $verbose;
print "$week\n"                  if !$verbose;

__DATA__
=head1 NAME

calcweek.pl - Calculate the week number from any given date

=head1 SYNOPSIS

calcweek.pl [-h] [-H] [-v] [-d yyyymmdd]

=head1 DESCRIPTION

This is a small Perl script to calculate the number of the week from a
+ny given date,
(given in the ISO 8601 format), or uses today's date if no date is spe
+cified. It was 
written just to scratch an itch I had in the past, when I frequently n
+eeded to know
the number of the week for planning purposes.

The program returns the number of the week it is, and if verbose is tu
+rned on, it 
will print the year, weeknumber, and day of the week in ISO 8601 forma
+t (YYYY-Www-D).
When verbose is turned off, it will only output the number of the week
+.

The following options are available:

    -h    --help            Display this help
    -H    --man            Display detailed help (manpage)
    -v    --verbose        Turn more verbose messages on
    -d    --date <yyyymmdd>    Set the date to calculate (default: tod
+ay)
    
=head1 DEPENDENCIES

Date::ISO, POSIX, Getopt::Long, Pod::Usage, Data::Dumper

=head1 SEE ALSO

For more information about ISO 8601:
http://www.iso.org/iso/date_and_time_format

=head1 BUGS

Lots. Probably. Any help on how to improve it is appreciated. :-)

=head1 AUTHOR

Sander Venema
Replies are listed 'Best First'.
Re: calcweek
by Krambambuli (Curate) on Aug 20, 2008 at 11:28 UTC
    Not to muck about it, but where would the main differences/benefits be against something like
    perl -MDate::Manip -e 'print UnixDate( "next Sunday", "%W"), "\n";'

    ?

    Thanks,

    Krambambuli
    ---
    sometimes enjoying Mark Jason Dominus' Higher-Order Perl

      I'm not 100% sure but calendar weeks in Europe and US of A differ. ISO 8601 start with Monday while US weeks start on Sunday.

      Also the definition of the first week differ.

      • in US it's the week containing January 1st.
      • in ISO 8601 it's the week having at least 4 days

      s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
      +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
      I didn't even know about the existence of Date::Manip, and your solution works as well. I'm a relative noob in Perl. But hey, according to the Perl spirit, TIMTOWTDI (there's more than one way to do it). :-) thanks for your reply. Now I know a way to do it that's a lot shorter. :-)