#include <string>
#include <cstring>

class Date {
 public:
  Date(int year, int month, int day) 
  : _year(year), _month(static_cast<Month>(month)), _day(day) {
	if (!isValidDate())
	  setDefaultDate();
  }

  bool IsLeap() const {
	return (_year % 400 == 0) || (_year % 4 == 0 && _year % 100 != 0);
  }

  std::string ToString() const {
	std::string result{};
	if (_day < 10)
	  result += "0";
	result += std::to_string(_day);
	result += '.';
	auto mon = static_cast<int> (_month);
	if (mon < 10)
	  result += "0";
	result += std::to_string(mon);
	result += '.';
	std::string y = to_string(_year);
	while (strlen((y).c_str()) < 4) {
	  result += "0";
	  y += '0';
	}
	result += std::to_string(_year);
	return result;
  }

  Date DaysLater(int days) const {
	Date newDate = *this;
	for (size_t i = 0; i < static_cast<size_t> (days); ++i)
	  newDate.addDay();
	return newDate;
  }

  int DaysLeft(const Date &date) const {
	int counter{};
	Date greaterDate = *this;
	Date smallestDate = date;
	
	if (!greaterDate.greater(date)) {
	  greaterDate = date;
	  smallestDate = *this;
	}

	if (greaterDate.equal(smallestDate))
	  return 0;

	do {
	  smallestDate.addDay();
	  counter++;
	} while (!greaterDate.equal(smallestDate));

	return counter;
  }
  
  enum class Month {
	Jan = 1, Feb, Mar, Apr, May,
	Jun, Jul, Aug, Sep, Oct, Nov, Dec
  };

 private:
  bool greater(const Date &b) {
	return (strcmp(this->ToString().c_str(), b.ToString().c_str()) > 0);
  }
  
  bool equal(const Date &b) {
	return this->_year == b._year && this->_month == b._month
	&& this->_day == b._day;
  }
  
  int maxDaysInMonth() const {
	auto mon = static_cast<int>(_month);
	if (IsLeap() && mon == static_cast<int> (Month::Feb))
	  return 29;
	else if (!IsLeap() && mon == static_cast<int> (Month::Feb))
	  return 28;
	else
	  return 30 + ((mon + mon / 8) % 2);
  }
  
  bool isValidDate() const {
	return _day >= 1 && _day <= maxDaysInMonth();
  }
  
  void setDefaultDate() {
	_year = 1970;
	_month = Month::Jan;
	_day = 1;
  }
  
  void addMonth() {
	if (_month == Month::Dec) {
	  _month = Month::Jan;
	  _year++;
	} else {
	  _month = static_cast<Month>(static_cast<int>(_month) + 1);
	}
  }
  
  void addDay() {
	if (_day >= maxDaysInMonth()) {
	  _day = 1;
	  addMonth();
	} else
	  _day++;
  }

 private:
  int _year;
  Month _month;
  int _day;
};