#include <iostream>
using namespace std;
int ymdToWeekNumber (int y, int m, int d) {
// reject out-of-range input
if ((y < 1965)||(y > 2099)) return 0;
if ((m < 1)||(m > 12)) return 0;
if ((d < 1)||(d > 31)) return 0;
// compute correction for year
// If Jan. 1 falls on: Mo Tu We Th Fr Sa Su
// then the correction is: 0 +1 +2 +3 -3 -2 -1
int corr = ((((y - 1965) * 5) / 4) % 7) - 3;
// compute day of the year (in range 1-366)
int doy = d;
if (m > 1) doy += 31;
if (m > 2) doy += (((y%4)==0) ? 29 : 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 corrected day number
int cdn = corr + doy;
// check for boundary conditions
// if our calculation would give us "week 53",
// we need to find out whether week 53 really exists,
// or whether it is week 1 of the following year
if (cdn > 364) {
// check for year beginning on Thurs.
if (corr==3) return 53;
// check for leap year beginning on Wed.
if (((y%4)==0) && (corr==2)) return 53;
// otherwise, there is no week 53
return 1;
}
// if our calculation would give us "week 0",
// then go to the previous year
// and find out whether we are in week 52 or week 53
if (cdn < 1) {
// first, compute correction for the previous year
corr = ((((y - 1966) * 5) / 4) % 7) - 3;
// then, compute day of year with respect to that same previous year
doy = d + (((y%4)==1)?366:365);
// finally, re-compute the corrected day number
cdn = corr + doy;
}
// compute number of weeks, rounding up to nearest whole week
return ((cdn + 6) / 7);
}
int main() {
cout << "Week number test\n";
int y, m, d;
srand(16028);
for (int i=2020; i<=2050; i++) {
y=i;
m=1;
d=1;
cout << y << "/" << m << "/" << d << " ";
cout << ymdToWeekNumber(y,m,d) << "\n";
m=1+(rand()%3);
d=2+(rand()%27);
cout << y << "/" << m << "/" << d << " ";
cout << ymdToWeekNumber(y,m,d) << "\n";
m=4+(rand()%3);
d=1+(rand()%30);
cout << y << "/" << m << "/" << d << " ";
cout << ymdToWeekNumber(y,m,d) << "\n";
m=7+(rand()%3);
d=1+(rand()%30);
cout << y << "/" << m << "/" << d << " ";
cout << ymdToWeekNumber(y,m,d) << "\n";
m=10+(rand()%3);
d=1+(rand()%30);
cout << y << "/" << m << "/" << d << " ";
cout << ymdToWeekNumber(y,m,d) << "\n";
m=12;
d=31;
cout << y << "/" << m << "/" << d << " ";
cout << ymdToWeekNumber(y,m,d) << "\n";
}
return 0;
}