---
# System prepended metadata

title: Data Structure and Graph Algorithms- Date.cpp

---

```cpp =
#include <stdlib.h>
#include <cstdio>
#include <iostream>

bool isLeapYear(int year);
class Date{
    public:
    Date(int d, int m, int y){
        day = d;
        month = m;
        year = y;
    }
     static void DayOfWeek(const Date& date) {
        //確認日期是否在格里高曆或儒略曆
        if(date.isGregorian()){
            std::string dayOfWeek= date.getDoW(date.zeller(date.day, date.month, date.year));
            printf("%s %d, %d is %s\n", date.getMName(date.month).c_str(), date.day,date.year, dayOfWeek.c_str());
        } else if (date.isWithinTransition())//若都不是則日期無效
        {
            printf(" Date invalid \n");
            return;
        }else{
            std::string dayOfWeek= date.getDoW(date.zeller(date.day+10, date.month, date.year));
            printf("%s %d, %d is %s\n", date.getMName(date.month).c_str(), date.day,date.year, dayOfWeek.c_str());
        }}
        
     static void DateSub(const Date& date1, const Date& date2) {
        //確認日期是否有效
        if (date1.isWithinTransition()||date2.isWithinTransition()){
            printf("Date invalid \n");
            return;
        }
        //每月天數 [0] 代表一月很反直覺 因此直接使 [n] 代表 n 月
        int dayInMonth[]= {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
         int days1 = date1.day;
        for (int m = 1; m < date1.month; ++m) {
            days1 += dayInMonth[m];
        }
        // 運算西元元年至當日的總天數
        days1+=365*date1.year+date1.leapUntilYear(date1.year);
        int days2 = date2.day;
        for (int m = 1; m < date1.month; ++m) {
            days2 += dayInMonth[m];
        }
        days2+=365*date2.year+date2.leapUntilYear(date2.year);
        //兩者相減取絕對值
        int diff=abs(days2-days1);
        //由於格里高曆和儒略曆的間隔發生在1582/10/4 ~ 1582/10/15 因此此前採用儒略曆法 此後採用格里高曆法
        if(!((date1.isGregorian() && date2.isGregorian())||(!date1.isGregorian() && !date2.isGregorian()))){
         diff-=10;
        }
        printf("%d days from %s %d, %d to %s %d, %d\n", diff, date1.getMName(date1.month).c_str(), date1.day, date1.year, date2.getMName(date2.month).c_str(), date2.day,date2.year);
        }

    static void DateAdd(const Date& date1, const int n,const int token){
        //確認日期是否有效
        if(date1.isWithinTransition()&&!token){
            printf("Date invalid \n");
            return;
        }

        int dayInMonth[]= {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        int totalDays=date1.day;
       //計算至今日期總和
        totalDays +=365*date1.year+date1.leapUntilYear(date1.year);
         for (int m = 1; m < date1.month; ++m) {
        totalDays += dayInMonth[m];
        
         }
         if (date1.month <= 2 && isLeapYear(date1.year)) {
            totalDays--; 
        }
        totalDays+=n;
        int newYear=0;
        //計算新日期年分
        while(totalDays>=365) {
            totalDays-=365;
            newYear++;
            if(isLeapYear(newYear))
                totalDays--;
        }
        int newMonth = 0;
        int newDay = 0;
        for (int m = 1; m <= 12; ++m) {
            int daysInMonth = dayInMonth[m];
            
            if (totalDays <= daysInMonth) {
                newMonth = m;
                if(m==2 &&isLeapYear(newYear))
                totalDays+=1;
                newDay = totalDays;
                break;
            }
            totalDays -= daysInMonth;
        }
        Date newDate(newDay, newMonth, newYear);
        //token=1 代表二次或以上運算 需要改變輸出
        if(!token){
            printf("%d days after %s %d, %d ",n, date1.getMName(date1.month).c_str(), date1.day, date1.year);
        }
        if (date1.isGregorian()&&!newDate.isGregorian()) {
            DateAdd(newDate, -10,1);
        }
        else if (!(date1.isGregorian()||date1.isWithinTransition())&&(newDate.isGregorian()||newDate.isWithinTransition())) {
            DateAdd(newDate, 10,1);
        }
        else{
        printf("is %s %d, %d\n", date1.getMName(newMonth).c_str(), newDay,newYear);
        }
    }
         
    private:
        int day;
        int month;
        int year;
    //to check if the date is a gregorian date
    bool isGregorian() const {
        return (year > 1582 || (year == 1582 && (month > 10 || (month == 10 && day >= 15))));
    }
    //get month name
        std::string getMName(int month) const{
        const char* monthNames[] = { "January", "February", "March", "April", "May", "June",
            "July", "August", "September", "October", "November", "December" };
        return monthNames[month - 1];

    }
    //to check if the date is within the transition period
    bool isWithinTransition() const {
        return (year == 1582 && month == 10 && day >= 5 && day <= 14);
    }
    
    std::string getDoW(int token) const{
        const char* dayOfWeek[] = { "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };
        return dayOfWeek[token];
    }
   
    //zeller's congruence 
    //formula from https://www.geeksforgeeks.org/zellers-congruence-find-day-date/
    int zeller(int day, int month, int year) const{
        if(month<3){
            month += 12;
            year--;
        }
        int k = year % 100;
        int j = year / 100;

        return (day+(13*(month+1))/5+k+k/4+j/4+5*j)%7;
    }
    //to calculate the number of leap year until the given year
    int leapUntilYear(int y) const{
        return y / 4 - y / 100 + y / 400;
    }
    
};
int main() {
    char input[100];
//事先讀取所有數據
while (scanf("%99[^\n]", input) == 1) {
    int dayInMonth[]= {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int day1, month1, year1,day2, month2, year2;
    int n;
    //依照數據輸入格式選擇不同算式
    if ((sscanf(input,"%d/%d/%d - %d/%d/%d", &year1, &month1, &day1, &year2, &month2, &day2)) ==6) {
        if(day1<0||day2<0||month1<0||month2<0||month1>13||month2>13||(day1>dayInMonth[month1]&&(!isLeapYear(year1)&&(month1==2)&&(day1>29)))
        ||day2>dayInMonth[month2]&&(month2==2&&(!isLeapYear(year2)&&(month2==2)&&(day2>29)))){
            printf("Date invalid \n");
            exit(1);
        }
            Date date1(day1, month1, year1), date2(day2,month2,year2);
            Date::DateSub(date1, date2);
        }
      else if ((sscanf(input,"%d/%d/%d + %d", &year1, &month1,&day1,&n))==4){
        if (day1<0||month1<0||month1>13||(day1>dayInMonth[month1]&&(!isLeapYear(year1)&&(month1==2)&&(day1>29)))){
            printf("Date invalid \n");
            exit(1);
    }
        Date date(day1, month1, year1);
        Date::DateAdd(date, n,0);
    }
    else if ((sscanf(input,"%d/%d/%d", &year1, &month1, &day1))==3) {
        if(day1<0||month1<0||month1>13||(day1>dayInMonth[month1]&&(!isLeapYear(year1)&&(month1==2)&&(day1>29)))){
            printf("Date invalid \n");
            exit(1);
        }
        Date date(day1, month1, year1);
        Date::DayOfWeek(date);
    }
    if ((sscanf(input,"%d", &day1)==1 && day1==-1))
        break;

    }
    return 0;
}

//確認 year是否為閏年
bool isLeapYear(int year){
return ((year % 4 == 0 && year % 100!= 0) || year % 400 == 0);
}
```