/* 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
*
*/
#include
#include
#include
int is_leap_year(int);
int main(int argc,char **argv)
{
time_t given_time;
struct tm in;
struct tm *inp = ∈
int year,daynumber,day,mont,mday,x,week,lastyear;
if (argc == 2) {
given_time=atol(argv[1]);
inp=localtime(&given_time);
} else if (argc == 4) {
inp->tm_mday=atoi(argv[1]);
inp->tm_mon=atoi(argv[2])-1;
/* Process the year number
* If xx < 50, assume 20xx
* If 50 <= xx < 100, assume 19xx
* If xx >= 100, assume xxxx
*/
if (atoi(argv[3]) < 50)
inp->tm_year=atoi(argv[3])+100;
else if (atoi(argv[3]) < 100)
inp->tm_year=atoi(argv[3]);
else
inp->tm_year=atoi(argv[3])-1900;
inp->tm_hour=0;
inp->tm_min=0;
inp->tm_sec=0;
inp->tm_isdst=-1;
} else if (argc == 1) {
time(&given_time);
inp=localtime(&given_time);
} else {
fprintf(stderr,"Syntax: %s [day month year] | [seconds_since_epoch]\nReturns week number according to ISO8601:1988\nWritten by ADS Benham\n",argv[0]);
exit(1);
}
given_time=mktime(inp);
year=inp->tm_year+1900;
daynumber=inp->tm_yday + 1; /* day number in year ( range 1-366) */
day=inp->tm_wday; /* 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) && x%7 == 5) || 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
*/
switch (x%7) {
case 1:
week = 52;
break;
case 3:
week = 53;
break;
case 2:
if (is_leap_year(year)) {
/* Current year is a leap year */
week = 52;
} else {
lastyear = year-1;
if (is_leap_year(lastyear)) {
/* Previous year is a leap year */
week = 53;
} else {
week = 52;
}
}
break;
default:
fprintf(stderr,"Logic warning - shouldn't get here\n");
week=-999;
break;
}
year--;
}
printf("%dW%.2d\n",year,week);
return 0;
}
int is_leap_year(int year)
/* Return 1 if leap year, 0 if not
* Note: year is a 4 digit number (i.e. includes century)
*/
{
if (year % 400 == 0)
return 1;
if (year % 100 == 0)
return 0;
if (year % 4 == 0)
return 1;
return 0;
}