#include <iostream>
using namespace std;
int days_in_month (int y, int m) {
// Fourth, eleventh, ninth, and sixth,
// thirty days to each we fix.
if ((m==4)||(m==11)||(m==9)||(m==6)) return 30;
// Every other, thirty-one,
// except the second month alone,
if (m!=2) return 31;
// which hath twenty-eight, in fine,
// till leap-year give it twenty-nine.
if ((y%400)==0) return 29; // leap year
if ((y%100)==0) return 28; // not a leap year
if ((y%4)==0) return 29; // leap year
return 28; // not a leap year
}
int ymdToWeekNumber (int y, int m, int d) {
// reject out-of-range dates
if ((y < 1901)||(y > 2099)) return 0;
if ((m < 1)||(m > 12)) return 0;
if ((d < 1)||(d > 31)) return 0;
// (It is useful to know that Jan. 1, 1901 was a Tuesday)
// compute adjustment for dates within the year
// If Jan. 1 falls on: Mo Tu We Th Fr Sa Su
// then the adjustment is: 6 7 8 9 3 4 5
int adj = (((y-1901) + ((y-1901)/4) + 4) % 7) + 3;
// compute day of the year (in range 1-366)
int doy = d;
if (m > 1) doy += 31;
if (m > 2) {
if ((y%4)==0) doy += 29;
else doy += 28;
}
if (m > 3) doy += 31;
if (m > 4) doy += 30;
if (m > 5) doy += 31;
if (m > 6) doy += 30;
if (m > 7) doy += 31;
if (m > 8) doy += 31;
if (m > 9) doy += 30;
if (m > 10) doy += 31;
if (m > 11) doy += 30;
// compute week number
int wknum = (adj + doy) / 7;
// check for boundary conditions
if (wknum < 1) {
// last week of the previous year
// check to see whether that year had 52 or 53 weeks
// re-compute adjustment, this time for previous year
adj = (((y-1902) + ((y-1902)/4) + 4) % 7) + 3;
// all years beginning on Thursday have 53 weeks
if (adj==9) return 53;
// leap years beginning on Wednesday have 53 weeks
if ((adj==8) && ((y%4)==1)) return 53;
// other years have 52 weeks
return 52;
}
if (wknum > 52) {
// check to see whether week 53 exists in this year
// all years beginning on Thursday have 53 weeks
if (adj==9) return 53;
// leap years beginning on Wednesday have 53 weeks
if ((adj==8) && ((y%4)==0)) return 53;
// other years have 52 weeks
return 1;
}
return wknum;
}
int main() {
int errcnt = 0;
int yyyy=1901, mo=1, dd=1, wd=2, wn=1;
cout << "Simple week number test\n";
while (yyyy<2100) {
int wntest = ymdToWeekNumber(yyyy,mo,dd);
if (wn != wntest) {
errcnt++;
if (errcnt <= 50) {
cout << yyyy << "/" << mo << "/" << dd << " " << wn << " " << wntest << "\n";
}
}
dd++;
if (dd > days_in_month(yyyy,mo)) {
dd = 1;
mo++;
if (mo > 12) {
mo = 1;
yyyy++;
}
}
wd++;
if (wd > 7) {
wd = 1;
wn++;
if (((mo==12) && (dd>=29)) || ((mo==1) && (dd<=4))) wn = 1;
}
}
cout << "Error count: " << errcnt << "\n";
return 0;
}