#!/usr/local/bin/perl -w
# Code to print ISO 8601:1988 week number for 'any' date.
# Uses Unix time functions, so works for 1970 - 2038.
#
# A.D.S.Benham, June 1998
#
# If called with no arguments, prints week number of current date/time
#
# Can call with one argument, the seconds since the epoch
#
# Can call with three arguments - day month year
#
#/
my ($given_time,@inp,$year,$daynumber,$day,$x,$week);
use POSIX;
use integer;
if ($#ARGV == 0) {
@inp=localtime($ARGV[0]);
} elsif ($#ARGV == 2) {
$inp[3] = $ARGV[0];
$inp[4] = $ARGV[1]-1;
# Process the year number
# If xx < 50, assume 20xx
# If 50 <= xx < 100, assume 19xx
# If xx >= 100, assume xxxx
if ($ARGV[2] < 50) {
$inp[5] = $ARGV[2]+100;
} elsif ($ARGV[2] < 100) {
$inp[5] = $ARGV[2];
} else {
$inp[5] = $ARGV[2]-1900;
}
$inp[2]=12;
$inp[1]=0;
$inp[0]=0;
$inp[6]=0;
$inp[7]=0;
$inp[8]=-1;
} elsif ($#ARGV == -1) {
@inp=localtime(time);
} else {
printf STDERR "Syntax: %s [day month year] | [seconds_since_epoch]\nReturns week number according to ISO8601:1988\nWritten by ADS Benham\n",$ARGV;
exit 1;
}
# POSIX::mktime seems loathe to fill in the weekday, so do a localtime()
# to force the weekday to be right.
$given_time=POSIX::mktime(@inp);
@inp=localtime($given_time);
$year=$inp[5]+1900;
$daynumber=$inp[7] + 1; # day number in year ( range 1-366)
$day=$inp[6]; # weekday, sunday=0
if ($day == 0) {
$day=7; # Make Sunday day 7 (day range 1-7)
}
$x=$daynumber - $day;
$week=$x/7+1; # Get 'raw' week number
# The raw week number now needs to be worked on. ISO8601:1988 tells
# us that week 1 of a year is the one which includes the first Thursday
# of the year, or equivalently the one which includes 4 January.
# ISO8601:1988 also tells us that the week begins on Monday.
if ($x < 0) {
$week=0;
}
if ($x%7 < 0) {
$x += 7; # x%7 is the date of the 1st Sunday in the year
}
if ($x%7 > 3) {
$week++;
}
if ($week==53) { # Week 53 is usually bogus result of calc
if ( (&is_leap_year($year) and ($x%7 == 5)) or ($x%7 == 4) ) {
# Really is a week 53 under these conditions */
} else {
$week = 1;
$year++;
}
}
if ($week < 1) {
# Need to return the last week of the previous year. This is either 52 or 53.
# To get here, x%7 is either 1, 2, or 3
# If it's 1, then the last week of the previous year is guaranteed to be week 52
# If it's 3, then the last week of the previous year is guaranteed to be week 53
# If it's 2, then it depends on:
# 1. whether this year is a leap year: if so, then the last week of the
# previous year was week 52
# 2. if this year isn't a leap year, was the previous year was a leap year ?
# if it was, then the last week of the previous year was week 53
# if it wasn't, then the last week of the previous year was week 52
if ($x%7 == 1) {
$week = 52;
} elsif ($x%7 == 3) {
$week = 53;
} elsif ($x%7 == 2) {
if (&is_leap_year($year)) {
# Current year is a leap year
$week = 52;
} else {
if (&is_leap_year($year-1)) {
# Previous year is a leap year
$week = 53;
} else {
$week = 52;
}
}
} else {
print STDERR "Logic warning - shouldn't get here\n";
$week=-999;
}
$year--;
}
printf "%dW%.2d\n",$year,$week;
sub is_leap_year
# Return 1 if leap year, 0 if not
# Note: year is 4 digit number
{
if ($_[0] % 400 == 0) {
return 1;
}
if ($_[0] % 100 == 0) {
return 0;
}
if ($_[0] % 4 == 0) {
return 1;
}
return 0;
}