```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);
}
```