/* 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; }