#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;
};