mercredi 22 juillet 2015

Computing dates on any planet with leap year info

Using values on Earth as an example,

LeapYear<4, 1, 100, 0, 400, 1, ...>(365).getDate(3659)

is supposed to output which year and which day the 3659th day is (we shall forget about months here), given that there are 365 days in each year, except every 4th year has 365+1 days, but every 100th year has 365+0 days, but every 400th year has 365+1 days, and so forth (increments can be negative too).

Here's what I've got so far, which only gives the correct output for the trivial LeapYear<>{365}.getDate(3659).print(); (i.e. no leap years at all). But I'm really butchering up the LeapYear<Leap, Increment, Is...> specialization, and need some help.

#include <iostream>

struct Date {
    int year, day;
    friend Date& operator + (int num, Date& date) {date.year += num;  return date;}
    void print() const {std::cout << "Date is " << year << "th year, " << day << "th day.\n";}
};

template <int... Is>
struct LeapYear {
    int numDaysPerYear;
    LeapYear (int num) : numDaysPerYear(num) {}
    Date getDate (int daysSinceEpoch) const {
        return Date{daysSinceEpoch / numDaysPerYear, daysSinceEpoch % numDaysPerYear};
    }
};

template <int Leap, int Increment, int... Is>
struct LeapYear<Leap, Increment, Is...> : LeapYear<Is...> {
    int numDaysPerYear;
    LeapYear (int num) : LeapYear<Is...>(num), numDaysPerYear(num) {}
    Date getDate (int daysSinceEpoch) const {
        const int numDaysInLeapYears = (daysSinceEpoch / Leap) * (numDaysPerYear + Increment);
        Date date = LeapYear<Is...>::getDate(daysSinceEpoch - numDaysInLeapYears);
        return daysSinceEpoch / Leap + date;
    }
};

int main() {
    LeapYear<>{365}.getDate(3659).print();  // 10th year, 9th day.  (correct, no leap years)
    LeapYear<4, 1, 100, 0, 400, 1>(365).getDate(3659).print();  // Way off! (1st year, 189th day)

Aucun commentaire:

Enregistrer un commentaire