#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
class Date {
private:
int day, month, year;
std::stringstream str;
constexpr static const int
leap[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
constexpr static const int
not_leap[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
struct date {
int year, month, day;
};
int number_by_date() {
int
leap[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int year = this->year - 1;
int kinda_answer = 365 * year + year / 4 - year / 100 + year / 400;
for (int i = 0; i < month - 1; i++) {
if (IsLeap()) {
kinda_answer += leap[i];
} else {
kinda_answer += not_leap[i];
}
}
kinda_answer += day;
return kinda_answer;
}
static date date_by_number(int number) {
int
leap[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int min_year = 1, max_year = 4000;
while (max_year != min_year) {
int mid = (min_year + max_year) / 2;
if (number - (365 * mid + mid / 4 - mid / 100 + mid / 400) < 0) {
max_year = mid;
} else {
min_year = mid + 1;
}
}
int year = min_year - 1;
number -= 365 * year + year / 4 - year / 100 + year / 400;
year++;
bool is_leap = year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
int month = 1;
for (int i = 0; i < 12; i++) {
if (is_leap) {
if (number > leap[i]) {
number -= leap[i];
month++;
} else {
break;
}
} else {
if (number > not_leap[i]) {
number -= not_leap[i];
month++;
} else {
break;
}
}
}
if (month == 13) {
year += 1;
month = 1;
}
int day = number;
return date{year, month, day};
}
public:
Date(int year, int month, int day) {
this->year = year;
this->month = month;
this->day = day;
}
bool IsLeap() {
if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
return true;
}
return false;
}
std::string ToString() {
str << std::setw(2) << std::setfill('0') << day
<< std::setw(0) << "."
<< std::setw(2) << month << std::setw(0) << "."
<< std::setw(4) << year;
std::string answer;
str >> answer;
return answer;
}
Date DaysLater(int days) {
auto smth = date_by_number(number_by_date() + days);
return {smth.year, smth.month, smth.day};
}
int DaysLeft(Date date) {
return date.number_by_date() - number_by_date();
}
};