c++ - Algorithm to calculate the start day of the next month -
i writing simple calendar class. trying overload operator++
use move calendar next month. however, algorithm find next month's start day not quite right.
calendar calendar::operator ++(int) { int hold; calendar cal = *this; month++; if (month > december) { month = january; year++; if (year == 0) year++; } previousstartday = startday; startday = nextstartday; nextstartday = findnextstartday(); return cal; } int calendar::findnextstartday() const { int monthlength, day = startday; monthlength = findmonthlength(false); monthlength -= 28; day += monthlength; if (day > saturday) day -= saturday; return day; }
january defined 0, december 11, sunday 0, saturday 6. startday, previousstartday, nextstartday, month, , year private class variables
when test 2013, dates correct until march. @ point gives next start day tuesday instead of monday.
i tried this:
int calendar::findnextstartday() const { int monthlength, day = startday; monthlength = findmonthlength(false); monthlength -= 28; day -= monthlength; if (day < sunday) day += saturday; return day; }
however, gives same results.
edit:
i accounting leap years. here code findmonthlength()
determine if or not.
if ((!(year % 4) && (year % 100)) || !(year % 400)) monthlength = 29; else monthlength = 28;
problem analysis
let's assume in march , have correct start day (friday, 5).
your findnextstartday
algorithm find monthlength
equal 3 (31-28), day 2 (8 - 6), tuesday (2) instead of monday (1)...
let's see why wrong running algorithm (first version of findnextstartday
):
january: 31-28 = 3, day = 2 (tuesday) + 3 = 5 (friday), correct start date of february.
february: 28 - 28 = 0, day = 5 (friday) + 0 = 5 (friday), correct start date of march.
march: 31-28 = 3, day = 5 (friday) + 3 - 6 (saturday) = 2 (tuesday), wrong start date of april.
bug explanation
the problem when subtract saturday result in overflow (more saturday), leaving 1 day out of count (i.e.: subtract 1 day less want).
think of case in end day == 7
. want have sunday (one more saturday - circularly increased), have remove 7, not 6, otherwise monday!
the error in circular increment: in correct algorithm 1 beyond 6 (i.e. 7) must go 0, 2 beyond 6 (i.e. 8) must go 1 , on.
in algorithm 1 beyond 6 (i.e. 7) goes 1, leaving out poor 0 (sunday) , making 1 day of week disappear each time end in case.
if subtract saturday + 1
right day of next month in case of "week days overflow".
bug fixing
in short, change line:
day -= saturday;
to
day -= (saturday + 1);
but please, consider reviewing code cleaner version of algorithm!
a small tip use modulo operator circular addition:
day = ((day + monthlength) % (saturday + 1))
Comments
Post a Comment