Samchon Framework for CPP  1.0.0
Date.hpp
1 #pragma once
2 #include <chrono>
3 
4 #include <array>
5 #include <string>
6 
7 #include <samchon/WeakString.hpp>
8 #include <samchon/library/StringUtil.hpp>
9 #include <samchon/library/IOperator.hpp>
10 
11 namespace samchon
12 {
13 namespace library
14 {
38  class Date
39  : public std::chrono::system_clock::time_point
40  {
41  private:
42  typedef std::chrono::system_clock::time_point super;
43 
50  static auto calc_seconds(int year, int month, int date) -> long long
51  {
52  std::array<int, 12> &months = calc_last_dates(year);
53  long long total;
54 
55  //연, 월, 일의 총 일수 total = (year - 1) * 365 + ((year - 1) / 4) - ((year - 1) / 100) + ((year - 1) / 400); //달수만큼 날자를 더함 for (int i = 0; i < month - 1; i++) total += months[i]; total += date; //일자에 3,600을 곱한다 total = (total * 24 * 60 * 60); return total; }; /** * @brief Calculates and gets an array of final date of each month for that year. * * @param year The target year * @return Array of fianl date of each month for that year */ static auto calc_last_dates(int year) -> std::array<int, 12> { //Last dates of each month static std::array<int, 12> months = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; //When the year contains leaf month, then make expiration date of Feburary to 29 if (year % 4 == 0) if (!(year % 100 == 0 && year % 400 != 0)) months[1] = 29; return months; }; public: /* --------------------------------------------------------- CONSTRUCTORS --------------------------------------------------------- */ /** * @brief Default Constructor * * @detail The date will be now (Now's date from operating system) */ Date() : super(std::chrono::system_clock::now()) { }; /** * @brief Copy Constructor * @details Copy the date from another Date * * @param date Target to be copied */ Date(const super &date) : super(date) { }; /** * @briref Move Constructor * @details Gets the date from other and truncate the other * * @param date Target to be moved */ Date(super &&date) : super(move(date)) { }; /** * @brief Construct from date elements * * @param year ex) 2015 * @param month January to December. 1 ~ 12 * @param date day in month. 1 ~ 31 * @throw invalid_argument month or date is invalid. */ Date(int year, int month, int date, int hour = 0, int min = 0, int sec = 0) { set(year, month, date, hour, min, sec); }; /** * @brief Construct from string * * @param str A string represents the date. (1991-01-01) * @throw invalid_argument month or date is invalid. */ Date(const std::string &str) { set(str); }; Date(const WeakString &wstr) { set(wstr); }; /** * @brief Construct from linux_time * * @param linuxTime linux_time to be converted */ Date(long long linuxTime) { set(linuxTime); }; /** * @brief Setter by string * * @param str Y-m-d * @throw invalid_argument month or date is invalid. */ void set(const WeakString &wstr) { int year, month, date, hour = 0, min = 0, sec = 0; WeakString date_wstr; size_t delimiter = wstr.find(" "); if (delimiter == std::string::npos) date_wstr = wstr; else { WeakString time_wstr; date_wstr = wstr.substr(0, delimiter); time_wstr = wstr.substr(delimiter); std::vector<WeakString> &hms = time_wstr.between(" ").split(":"); int hour = std::stoi(hms[0]); int min = std::stoi(hms[1]); int sec; if (hms.size() == 3) sec = std::stoi(hms[2]); else sec = 0; } std::vector<WeakString> &ymd = date_wstr.split("-"); year = std::stoi(ymd[0]); month = std::stoi(ymd[1]); date = std::stoi(ymd[2]); set(year, month, date, hour, min, sec); }; /** * @brief Setter by elements of date * * @param year ex) 2015 * @param month January to December. 1 ~ 12 * @param date day in month. 1 ~ 31 * @throw invalid_argument month or date is invalid. */ void set(int year, int month, int date, int hour = 0, int min = 0, int sec = 0) { std::array<int, 12> &monthArray = calc_last_dates(year); if (month > 12) throw std::invalid_argument("month is over 12"); if (date > monthArray[month - 1]) throw std::invalid_argument("date is over expiration date"); long long linuxTime = calc_seconds(year, month, date); linuxTime -= (calc_seconds(1970, 1, 1) + 9 * 60 * 60); linuxTime += hour * 60 * 60 + min * 60 + sec; set(linuxTime); }; /** * @brief Setter by linux_time * * @param linuxTime linux_time to be converted */ void set(long long linuxTime) { *this = std::chrono::system_clock::from_time_t(linuxTime); }; public: /* ========================================================= ACCESSORS - GETTERS - SETTERS - ADDERS ============================================================ - GETTERS --------------------------------------------------------- */ /** * @brief Get year of the Date * * @return Year */ auto getYear() const -> int { auto &tm = toTM(); return tm.tm_year + 1900; }; /** * @brief Get month of the Date * * @return Month as integer (1: January, 12: December) */ auto getMonth() const -> int { auto &tm = toTM(); return tm.tm_mon + 1; }; /** * @brief Get the day in month of the Date * * @return Day in month (1 to 31) */ auto getDate() const -> int { auto &tm = toTM(); return tm.tm_mon + 1; }; /** * @brief Get the day in week of the Date * * @return Day in week to integer (0: Sunday, 1: Monday, ..., 6: Saturday) */ auto getDay() const -> int { auto &tm = toTM(); return tm.tm_wday; }; /** * @brief Get hour * * @return hour of the Date to integer */ auto getHour() const -> int { struct tm &tm = toTM(); return tm.tm_hour; }; /** * @brief Get minute * * @return minute of the Date to integer */ auto getMinute() const -> int { struct tm &tm = toTM(); return tm.tm_min; }; /** * @brief Get second * * @return second of the Date to integer */ auto getSecond() const -> int { struct tm &tm = toTM(); return tm.tm_sec; }; /* --------------------------------------------------------- SETTERS --------------------------------------------------------- */ /** * @brief Set year of the Date * * @details * If previous date is leaf month's expiration date and * target year what you want is not leaf, the date will be 28 * * \li 2000-02-29 -> setYear(2001) -> 2001-02-28 * \li 2001-02-28 -> setYear(2000) -> 2000-02-08 * * @param val Target year */ void setYear(int year) { int month = getMonth(); int new_date = getDate(); //윤달에 29일인데 addYear을 하려는 경우 if ( month == 2 && new_date == 29 //현재가 윤달 29일 && !( year == 4 && !((year % 100 == 0 && year % 400 != 0)) ) //바꿀 연도의 2월은 윤달이 아님 ) new_date = 28; set(year, month, new_date); }; /** * @brief Set month of the Date * * @details * If the expiration date of the month will be shrinked, the date will be changed to the expiration date * * \li 2000-03-31 -> setMonth(4) -> 2000-04-30 * \li 2007-08-31 -> setMonth(9) -> 2007-09-30 * * @param val Target month (1 - 12) * @throw invalid_argument month is out of range */ void setMonth(int month) { if (month > 12) throw std::invalid_argument("month is over 12"); //달력 int year = getYear(); int new_date = getDate(); std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (new_date > months[month - 1]) new_date = months[month - 1]; set(year, month, new_date); }; /** * Set date of the Date * * @param val Target day in month * @throw invalid_argument When date is over expiration date in month */ void setDate(int val) { set(getYear(), getMonth(), val); }; /** * @brief Set hour * * @param val Target hour (0 - 23) * @throw invalid_argument When hour is out of range */ void setHour(int val) { addHour(val - getHour()); }; /** * @brief Set minute * * @param val Target minute (0 - 59) * @throw invalid_argument When minute is out of range */ void setMinute(int val) { addMinute(val - getMinute()); }; /** * @brief Set hour * * @param val Target second (0 - 59) * @throw invalid_argument When second is out of range */ void setSecond(int val) { addSecond(val - getSecond()); }; /* -------------------------------------------------------------------------- ADDERS -------------------------------------------------------------------------- */ //ADD METHODS /** * @brief Add years to the Date * * @param val Years to add */ void addYear(int val) { //현재가 2012년 2월 29일(윤달)인데 1년을 추가하면 2013년 2월 28일로 변함 setYear(getYear() + val); }; /** * @brief Add months to the Date * * @details * Not a matter to val is over 12. If the month is over 12, * then years will be added. * * @param val Months to add */ void addMonth(int val) { //현재가 3월 31일인데 1월이 추가되면 날짜는 4월 30일로 변한다 int year = getYear(); int month = getMonth() + val; int date = getDate(); if (month > 12) { year = year + (month - 1) / 12; month = month % 13; } //달력 std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (date > months[month - 1]) date = months[month - 1]; set(year, month, date); }; /** * @brief Add weeks to the Date * * @details * Not a matter that val is too huge. If the adding weeks derives * modification in month or year, then it will be. * * @param val Weeks to add */ void addWeek(int val) { addDate(7 * val); }; /** * @brief Add days to the Date * * @details * Not a matter that val is too huge. If the adding dates derives * modification in month or year, then it will be. * * @param val Days to add */ void addDate(int val) { addHour(24 * val); }; /** * @brief Add hours * * @details * <p> It's same with operator+=(chrono::hours(val)) </p> * * <p> Do not worry about the out of range of the hour(val) * Parent items like date, month and years will be adjusted automatically. </p> * * @param val hours to add */ void addHour(int val) { operator+=(std::chrono::hours(val)); }; /** * @brief Add minutes * * \par It's same with operator+=(chrono::minutes(val)) * * \par * Do not worry about the out of range of the minutes(val) * Parent items like date, month and years will be adjusted automatically. * * @param val minutes to add */ void addMinute(int val) { operator+=(std::chrono::minutes(val)); }; /** * @brief Add seconds * * @details * \par It's same with operator+=(chrono::seconds(val)) * * \par * Do not worry about the out of range of the seconds(val) * Parent items like date, month and years will be adjusted automatically. * * @param val seconds to add */ void addSecond(int val) { operator+=(std::chrono::seconds(val)); }; /* -------------------------------------------------------------------------- EXPORTERS -------------------------------------------------------------------------- */ /** * @brief Converts the Date to struct tm * * @return struct tm representing the Date */ auto toTM() const -> struct ::tm { struct tm tm; time_t tt = std::chrono::system_clock::to_time_t(*this); localtime_s(&tm, &tt); return tm; }; /** * @brief Converts the Date to linux_time * * @return linux_time of the Date */ auto toLinuxTime() const -> long long { std::chrono::system_clock::duration duration = *this - std::chrono::system_clock::from_time_t(0); std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); return seconds.count(); }; /** * @brief Converts the Date to std::string * * @return std::string expressing the Date */ auto toString() const -> std::string { struct tm &tm = toTM(); if (tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0) return StringUtil::substitute ( "{1}-{2}-{3}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday ); else return StringUtil::substitute ( "{1}-{2}-{3} {4}:{5}:{6}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec ); }; }; }; };
56  total = (year - 1) * 365 + ((year - 1) / 4) - ((year - 1) / 100) + ((year - 1) / 400);
57 
58  //달수만큼 날자를 더함 for (int i = 0; i < month - 1; i++) total += months[i]; total += date; //일자에 3,600을 곱한다 total = (total * 24 * 60 * 60); return total; }; /** * @brief Calculates and gets an array of final date of each month for that year. * * @param year The target year * @return Array of fianl date of each month for that year */ static auto calc_last_dates(int year) -> std::array<int, 12> { //Last dates of each month static std::array<int, 12> months = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; //When the year contains leaf month, then make expiration date of Feburary to 29 if (year % 4 == 0) if (!(year % 100 == 0 && year % 400 != 0)) months[1] = 29; return months; }; public: /* --------------------------------------------------------- CONSTRUCTORS --------------------------------------------------------- */ /** * @brief Default Constructor * * @detail The date will be now (Now's date from operating system) */ Date() : super(std::chrono::system_clock::now()) { }; /** * @brief Copy Constructor * @details Copy the date from another Date * * @param date Target to be copied */ Date(const super &date) : super(date) { }; /** * @briref Move Constructor * @details Gets the date from other and truncate the other * * @param date Target to be moved */ Date(super &&date) : super(move(date)) { }; /** * @brief Construct from date elements * * @param year ex) 2015 * @param month January to December. 1 ~ 12 * @param date day in month. 1 ~ 31 * @throw invalid_argument month or date is invalid. */ Date(int year, int month, int date, int hour = 0, int min = 0, int sec = 0) { set(year, month, date, hour, min, sec); }; /** * @brief Construct from string * * @param str A string represents the date. (1991-01-01) * @throw invalid_argument month or date is invalid. */ Date(const std::string &str) { set(str); }; Date(const WeakString &wstr) { set(wstr); }; /** * @brief Construct from linux_time * * @param linuxTime linux_time to be converted */ Date(long long linuxTime) { set(linuxTime); }; /** * @brief Setter by string * * @param str Y-m-d * @throw invalid_argument month or date is invalid. */ void set(const WeakString &wstr) { int year, month, date, hour = 0, min = 0, sec = 0; WeakString date_wstr; size_t delimiter = wstr.find(" "); if (delimiter == std::string::npos) date_wstr = wstr; else { WeakString time_wstr; date_wstr = wstr.substr(0, delimiter); time_wstr = wstr.substr(delimiter); std::vector<WeakString> &hms = time_wstr.between(" ").split(":"); int hour = std::stoi(hms[0]); int min = std::stoi(hms[1]); int sec; if (hms.size() == 3) sec = std::stoi(hms[2]); else sec = 0; } std::vector<WeakString> &ymd = date_wstr.split("-"); year = std::stoi(ymd[0]); month = std::stoi(ymd[1]); date = std::stoi(ymd[2]); set(year, month, date, hour, min, sec); }; /** * @brief Setter by elements of date * * @param year ex) 2015 * @param month January to December. 1 ~ 12 * @param date day in month. 1 ~ 31 * @throw invalid_argument month or date is invalid. */ void set(int year, int month, int date, int hour = 0, int min = 0, int sec = 0) { std::array<int, 12> &monthArray = calc_last_dates(year); if (month > 12) throw std::invalid_argument("month is over 12"); if (date > monthArray[month - 1]) throw std::invalid_argument("date is over expiration date"); long long linuxTime = calc_seconds(year, month, date); linuxTime -= (calc_seconds(1970, 1, 1) + 9 * 60 * 60); linuxTime += hour * 60 * 60 + min * 60 + sec; set(linuxTime); }; /** * @brief Setter by linux_time * * @param linuxTime linux_time to be converted */ void set(long long linuxTime) { *this = std::chrono::system_clock::from_time_t(linuxTime); }; public: /* ========================================================= ACCESSORS - GETTERS - SETTERS - ADDERS ============================================================ - GETTERS --------------------------------------------------------- */ /** * @brief Get year of the Date * * @return Year */ auto getYear() const -> int { auto &tm = toTM(); return tm.tm_year + 1900; }; /** * @brief Get month of the Date * * @return Month as integer (1: January, 12: December) */ auto getMonth() const -> int { auto &tm = toTM(); return tm.tm_mon + 1; }; /** * @brief Get the day in month of the Date * * @return Day in month (1 to 31) */ auto getDate() const -> int { auto &tm = toTM(); return tm.tm_mon + 1; }; /** * @brief Get the day in week of the Date * * @return Day in week to integer (0: Sunday, 1: Monday, ..., 6: Saturday) */ auto getDay() const -> int { auto &tm = toTM(); return tm.tm_wday; }; /** * @brief Get hour * * @return hour of the Date to integer */ auto getHour() const -> int { struct tm &tm = toTM(); return tm.tm_hour; }; /** * @brief Get minute * * @return minute of the Date to integer */ auto getMinute() const -> int { struct tm &tm = toTM(); return tm.tm_min; }; /** * @brief Get second * * @return second of the Date to integer */ auto getSecond() const -> int { struct tm &tm = toTM(); return tm.tm_sec; }; /* --------------------------------------------------------- SETTERS --------------------------------------------------------- */ /** * @brief Set year of the Date * * @details * If previous date is leaf month's expiration date and * target year what you want is not leaf, the date will be 28 * * \li 2000-02-29 -> setYear(2001) -> 2001-02-28 * \li 2001-02-28 -> setYear(2000) -> 2000-02-08 * * @param val Target year */ void setYear(int year) { int month = getMonth(); int new_date = getDate(); //윤달에 29일인데 addYear을 하려는 경우 if ( month == 2 && new_date == 29 //현재가 윤달 29일 && !( year == 4 && !((year % 100 == 0 && year % 400 != 0)) ) //바꿀 연도의 2월은 윤달이 아님 ) new_date = 28; set(year, month, new_date); }; /** * @brief Set month of the Date * * @details * If the expiration date of the month will be shrinked, the date will be changed to the expiration date * * \li 2000-03-31 -> setMonth(4) -> 2000-04-30 * \li 2007-08-31 -> setMonth(9) -> 2007-09-30 * * @param val Target month (1 - 12) * @throw invalid_argument month is out of range */ void setMonth(int month) { if (month > 12) throw std::invalid_argument("month is over 12"); //달력 int year = getYear(); int new_date = getDate(); std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (new_date > months[month - 1]) new_date = months[month - 1]; set(year, month, new_date); }; /** * Set date of the Date * * @param val Target day in month * @throw invalid_argument When date is over expiration date in month */ void setDate(int val) { set(getYear(), getMonth(), val); }; /** * @brief Set hour * * @param val Target hour (0 - 23) * @throw invalid_argument When hour is out of range */ void setHour(int val) { addHour(val - getHour()); }; /** * @brief Set minute * * @param val Target minute (0 - 59) * @throw invalid_argument When minute is out of range */ void setMinute(int val) { addMinute(val - getMinute()); }; /** * @brief Set hour * * @param val Target second (0 - 59) * @throw invalid_argument When second is out of range */ void setSecond(int val) { addSecond(val - getSecond()); }; /* -------------------------------------------------------------------------- ADDERS -------------------------------------------------------------------------- */ //ADD METHODS /** * @brief Add years to the Date * * @param val Years to add */ void addYear(int val) { //현재가 2012년 2월 29일(윤달)인데 1년을 추가하면 2013년 2월 28일로 변함 setYear(getYear() + val); }; /** * @brief Add months to the Date * * @details * Not a matter to val is over 12. If the month is over 12, * then years will be added. * * @param val Months to add */ void addMonth(int val) { //현재가 3월 31일인데 1월이 추가되면 날짜는 4월 30일로 변한다 int year = getYear(); int month = getMonth() + val; int date = getDate(); if (month > 12) { year = year + (month - 1) / 12; month = month % 13; } //달력 std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (date > months[month - 1]) date = months[month - 1]; set(year, month, date); }; /** * @brief Add weeks to the Date * * @details * Not a matter that val is too huge. If the adding weeks derives * modification in month or year, then it will be. * * @param val Weeks to add */ void addWeek(int val) { addDate(7 * val); }; /** * @brief Add days to the Date * * @details * Not a matter that val is too huge. If the adding dates derives * modification in month or year, then it will be. * * @param val Days to add */ void addDate(int val) { addHour(24 * val); }; /** * @brief Add hours * * @details * <p> It's same with operator+=(chrono::hours(val)) </p> * * <p> Do not worry about the out of range of the hour(val) * Parent items like date, month and years will be adjusted automatically. </p> * * @param val hours to add */ void addHour(int val) { operator+=(std::chrono::hours(val)); }; /** * @brief Add minutes * * \par It's same with operator+=(chrono::minutes(val)) * * \par * Do not worry about the out of range of the minutes(val) * Parent items like date, month and years will be adjusted automatically. * * @param val minutes to add */ void addMinute(int val) { operator+=(std::chrono::minutes(val)); }; /** * @brief Add seconds * * @details * \par It's same with operator+=(chrono::seconds(val)) * * \par * Do not worry about the out of range of the seconds(val) * Parent items like date, month and years will be adjusted automatically. * * @param val seconds to add */ void addSecond(int val) { operator+=(std::chrono::seconds(val)); }; /* -------------------------------------------------------------------------- EXPORTERS -------------------------------------------------------------------------- */ /** * @brief Converts the Date to struct tm * * @return struct tm representing the Date */ auto toTM() const -> struct ::tm { struct tm tm; time_t tt = std::chrono::system_clock::to_time_t(*this); localtime_s(&tm, &tt); return tm; }; /** * @brief Converts the Date to linux_time * * @return linux_time of the Date */ auto toLinuxTime() const -> long long { std::chrono::system_clock::duration duration = *this - std::chrono::system_clock::from_time_t(0); std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); return seconds.count(); }; /** * @brief Converts the Date to std::string * * @return std::string expressing the Date */ auto toString() const -> std::string { struct tm &tm = toTM(); if (tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0) return StringUtil::substitute ( "{1}-{2}-{3}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday ); else return StringUtil::substitute ( "{1}-{2}-{3} {4}:{5}:{6}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec ); }; }; }; };
59  for (int i = 0; i < month - 1; i++)
60  total += months[i];
61  total += date;
62 
63  //일자에 3,600을 곱한다 total = (total * 24 * 60 * 60); return total; }; /** * @brief Calculates and gets an array of final date of each month for that year. * * @param year The target year * @return Array of fianl date of each month for that year */ static auto calc_last_dates(int year) -> std::array<int, 12> { //Last dates of each month static std::array<int, 12> months = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; //When the year contains leaf month, then make expiration date of Feburary to 29 if (year % 4 == 0) if (!(year % 100 == 0 && year % 400 != 0)) months[1] = 29; return months; }; public: /* --------------------------------------------------------- CONSTRUCTORS --------------------------------------------------------- */ /** * @brief Default Constructor * * @detail The date will be now (Now's date from operating system) */ Date() : super(std::chrono::system_clock::now()) { }; /** * @brief Copy Constructor * @details Copy the date from another Date * * @param date Target to be copied */ Date(const super &date) : super(date) { }; /** * @briref Move Constructor * @details Gets the date from other and truncate the other * * @param date Target to be moved */ Date(super &&date) : super(move(date)) { }; /** * @brief Construct from date elements * * @param year ex) 2015 * @param month January to December. 1 ~ 12 * @param date day in month. 1 ~ 31 * @throw invalid_argument month or date is invalid. */ Date(int year, int month, int date, int hour = 0, int min = 0, int sec = 0) { set(year, month, date, hour, min, sec); }; /** * @brief Construct from string * * @param str A string represents the date. (1991-01-01) * @throw invalid_argument month or date is invalid. */ Date(const std::string &str) { set(str); }; Date(const WeakString &wstr) { set(wstr); }; /** * @brief Construct from linux_time * * @param linuxTime linux_time to be converted */ Date(long long linuxTime) { set(linuxTime); }; /** * @brief Setter by string * * @param str Y-m-d * @throw invalid_argument month or date is invalid. */ void set(const WeakString &wstr) { int year, month, date, hour = 0, min = 0, sec = 0; WeakString date_wstr; size_t delimiter = wstr.find(" "); if (delimiter == std::string::npos) date_wstr = wstr; else { WeakString time_wstr; date_wstr = wstr.substr(0, delimiter); time_wstr = wstr.substr(delimiter); std::vector<WeakString> &hms = time_wstr.between(" ").split(":"); int hour = std::stoi(hms[0]); int min = std::stoi(hms[1]); int sec; if (hms.size() == 3) sec = std::stoi(hms[2]); else sec = 0; } std::vector<WeakString> &ymd = date_wstr.split("-"); year = std::stoi(ymd[0]); month = std::stoi(ymd[1]); date = std::stoi(ymd[2]); set(year, month, date, hour, min, sec); }; /** * @brief Setter by elements of date * * @param year ex) 2015 * @param month January to December. 1 ~ 12 * @param date day in month. 1 ~ 31 * @throw invalid_argument month or date is invalid. */ void set(int year, int month, int date, int hour = 0, int min = 0, int sec = 0) { std::array<int, 12> &monthArray = calc_last_dates(year); if (month > 12) throw std::invalid_argument("month is over 12"); if (date > monthArray[month - 1]) throw std::invalid_argument("date is over expiration date"); long long linuxTime = calc_seconds(year, month, date); linuxTime -= (calc_seconds(1970, 1, 1) + 9 * 60 * 60); linuxTime += hour * 60 * 60 + min * 60 + sec; set(linuxTime); }; /** * @brief Setter by linux_time * * @param linuxTime linux_time to be converted */ void set(long long linuxTime) { *this = std::chrono::system_clock::from_time_t(linuxTime); }; public: /* ========================================================= ACCESSORS - GETTERS - SETTERS - ADDERS ============================================================ - GETTERS --------------------------------------------------------- */ /** * @brief Get year of the Date * * @return Year */ auto getYear() const -> int { auto &tm = toTM(); return tm.tm_year + 1900; }; /** * @brief Get month of the Date * * @return Month as integer (1: January, 12: December) */ auto getMonth() const -> int { auto &tm = toTM(); return tm.tm_mon + 1; }; /** * @brief Get the day in month of the Date * * @return Day in month (1 to 31) */ auto getDate() const -> int { auto &tm = toTM(); return tm.tm_mon + 1; }; /** * @brief Get the day in week of the Date * * @return Day in week to integer (0: Sunday, 1: Monday, ..., 6: Saturday) */ auto getDay() const -> int { auto &tm = toTM(); return tm.tm_wday; }; /** * @brief Get hour * * @return hour of the Date to integer */ auto getHour() const -> int { struct tm &tm = toTM(); return tm.tm_hour; }; /** * @brief Get minute * * @return minute of the Date to integer */ auto getMinute() const -> int { struct tm &tm = toTM(); return tm.tm_min; }; /** * @brief Get second * * @return second of the Date to integer */ auto getSecond() const -> int { struct tm &tm = toTM(); return tm.tm_sec; }; /* --------------------------------------------------------- SETTERS --------------------------------------------------------- */ /** * @brief Set year of the Date * * @details * If previous date is leaf month's expiration date and * target year what you want is not leaf, the date will be 28 * * \li 2000-02-29 -> setYear(2001) -> 2001-02-28 * \li 2001-02-28 -> setYear(2000) -> 2000-02-08 * * @param val Target year */ void setYear(int year) { int month = getMonth(); int new_date = getDate(); //윤달에 29일인데 addYear을 하려는 경우 if ( month == 2 && new_date == 29 //현재가 윤달 29일 && !( year == 4 && !((year % 100 == 0 && year % 400 != 0)) ) //바꿀 연도의 2월은 윤달이 아님 ) new_date = 28; set(year, month, new_date); }; /** * @brief Set month of the Date * * @details * If the expiration date of the month will be shrinked, the date will be changed to the expiration date * * \li 2000-03-31 -> setMonth(4) -> 2000-04-30 * \li 2007-08-31 -> setMonth(9) -> 2007-09-30 * * @param val Target month (1 - 12) * @throw invalid_argument month is out of range */ void setMonth(int month) { if (month > 12) throw std::invalid_argument("month is over 12"); //달력 int year = getYear(); int new_date = getDate(); std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (new_date > months[month - 1]) new_date = months[month - 1]; set(year, month, new_date); }; /** * Set date of the Date * * @param val Target day in month * @throw invalid_argument When date is over expiration date in month */ void setDate(int val) { set(getYear(), getMonth(), val); }; /** * @brief Set hour * * @param val Target hour (0 - 23) * @throw invalid_argument When hour is out of range */ void setHour(int val) { addHour(val - getHour()); }; /** * @brief Set minute * * @param val Target minute (0 - 59) * @throw invalid_argument When minute is out of range */ void setMinute(int val) { addMinute(val - getMinute()); }; /** * @brief Set hour * * @param val Target second (0 - 59) * @throw invalid_argument When second is out of range */ void setSecond(int val) { addSecond(val - getSecond()); }; /* -------------------------------------------------------------------------- ADDERS -------------------------------------------------------------------------- */ //ADD METHODS /** * @brief Add years to the Date * * @param val Years to add */ void addYear(int val) { //현재가 2012년 2월 29일(윤달)인데 1년을 추가하면 2013년 2월 28일로 변함 setYear(getYear() + val); }; /** * @brief Add months to the Date * * @details * Not a matter to val is over 12. If the month is over 12, * then years will be added. * * @param val Months to add */ void addMonth(int val) { //현재가 3월 31일인데 1월이 추가되면 날짜는 4월 30일로 변한다 int year = getYear(); int month = getMonth() + val; int date = getDate(); if (month > 12) { year = year + (month - 1) / 12; month = month % 13; } //달력 std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (date > months[month - 1]) date = months[month - 1]; set(year, month, date); }; /** * @brief Add weeks to the Date * * @details * Not a matter that val is too huge. If the adding weeks derives * modification in month or year, then it will be. * * @param val Weeks to add */ void addWeek(int val) { addDate(7 * val); }; /** * @brief Add days to the Date * * @details * Not a matter that val is too huge. If the adding dates derives * modification in month or year, then it will be. * * @param val Days to add */ void addDate(int val) { addHour(24 * val); }; /** * @brief Add hours * * @details * <p> It's same with operator+=(chrono::hours(val)) </p> * * <p> Do not worry about the out of range of the hour(val) * Parent items like date, month and years will be adjusted automatically. </p> * * @param val hours to add */ void addHour(int val) { operator+=(std::chrono::hours(val)); }; /** * @brief Add minutes * * \par It's same with operator+=(chrono::minutes(val)) * * \par * Do not worry about the out of range of the minutes(val) * Parent items like date, month and years will be adjusted automatically. * * @param val minutes to add */ void addMinute(int val) { operator+=(std::chrono::minutes(val)); }; /** * @brief Add seconds * * @details * \par It's same with operator+=(chrono::seconds(val)) * * \par * Do not worry about the out of range of the seconds(val) * Parent items like date, month and years will be adjusted automatically. * * @param val seconds to add */ void addSecond(int val) { operator+=(std::chrono::seconds(val)); }; /* -------------------------------------------------------------------------- EXPORTERS -------------------------------------------------------------------------- */ /** * @brief Converts the Date to struct tm * * @return struct tm representing the Date */ auto toTM() const -> struct ::tm { struct tm tm; time_t tt = std::chrono::system_clock::to_time_t(*this); localtime_s(&tm, &tt); return tm; }; /** * @brief Converts the Date to linux_time * * @return linux_time of the Date */ auto toLinuxTime() const -> long long { std::chrono::system_clock::duration duration = *this - std::chrono::system_clock::from_time_t(0); std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); return seconds.count(); }; /** * @brief Converts the Date to std::string * * @return std::string expressing the Date */ auto toString() const -> std::string { struct tm &tm = toTM(); if (tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0) return StringUtil::substitute ( "{1}-{2}-{3}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday ); else return StringUtil::substitute ( "{1}-{2}-{3} {4}:{5}:{6}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec ); }; }; }; };
64  total = (total * 24 * 60 * 60);
65  return total;
66  };
67 
74  static auto calc_last_dates(int year) -> std::array<int, 12>
75  {
76  //Last dates of each month
77  static std::array<int, 12> months = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
78 
79  //When the year contains leaf month, then make expiration date of Feburary to 29
80  if (year % 4 == 0)
81  if (!(year % 100 == 0 && year % 400 != 0))
82  months[1] = 29;
83 
84  return months;
85  };
86 
87  public:
88  /* ---------------------------------------------------------
89  CONSTRUCTORS
90  --------------------------------------------------------- */
96  Date() : super(std::chrono::system_clock::now())
97  {
98  };
99 
106  Date(const super &date) : super(date)
107  {
108  };
109 
116  Date(super &&date) : super(move(date))
117  {
118  };
119 
128  Date(int year, int month, int date, int hour = 0, int min = 0, int sec = 0)
129  {
130  set(year, month, date, hour, min, sec);
131  };
132 
139  Date(const std::string &str)
140  {
141  set(str);
142  };
143 
144  Date(const WeakString &wstr)
145  {
146  set(wstr);
147  };
148 
154  Date(long long linuxTime)
155  {
156  set(linuxTime);
157  };
158 
165  void set(const WeakString &wstr)
166  {
167  int year, month, date, hour = 0, min = 0, sec = 0;
168  WeakString date_wstr;
169 
170  size_t delimiter = wstr.find(" ");
171  if (delimiter == std::string::npos)
172  date_wstr = wstr;
173  else
174  {
175  WeakString time_wstr;
176  date_wstr = wstr.substr(0, delimiter);
177  time_wstr = wstr.substr(delimiter);
178 
179  std::vector<WeakString> &hms = time_wstr.between(" ").split(":");
180  int hour = std::stoi(hms[0]);
181  int min = std::stoi(hms[1]);
182  int sec;
183 
184  if (hms.size() == 3)
185  sec = std::stoi(hms[2]);
186  else
187  sec = 0;
188  }
189 
190  std::vector<WeakString> &ymd = date_wstr.split("-");
191  year = std::stoi(ymd[0]);
192  month = std::stoi(ymd[1]);
193  date = std::stoi(ymd[2]);
194 
195  set(year, month, date, hour, min, sec);
196  };
197 
206  void set(int year, int month, int date, int hour = 0, int min = 0, int sec = 0)
207  {
208  std::array<int, 12> &monthArray = calc_last_dates(year);
209 
210  if (month > 12)
211  throw std::invalid_argument("month is over 12");
212  if (date > monthArray[month - 1])
213  throw std::invalid_argument("date is over expiration date");
214 
215  long long linuxTime = calc_seconds(year, month, date);
216  linuxTime -= (calc_seconds(1970, 1, 1) + 9 * 60 * 60);
217  linuxTime += hour * 60 * 60 + min * 60 + sec;
218 
219  set(linuxTime);
220  };
221 
227  void set(long long linuxTime)
228  {
229  *this = std::chrono::system_clock::from_time_t(linuxTime);
230  };
231 
232  public:
233  /* =========================================================
234  ACCESSORS
235  - GETTERS
236  - SETTERS
237  - ADDERS
238  ============================================================
239  - GETTERS
240  --------------------------------------------------------- */
246  auto getYear() const -> int
247  {
248  auto &tm = toTM();
249  return tm.tm_year + 1900;
250  };
251 
257  auto getMonth() const -> int
258  {
259  auto &tm = toTM();
260  return tm.tm_mon + 1;
261  };
262 
268  auto getDate() const -> int
269  {
270  auto &tm = toTM();
271  return tm.tm_mon + 1;
272  };
273 
279  auto getDay() const -> int
280  {
281  auto &tm = toTM();
282  return tm.tm_wday;
283  };
284 
290  auto getHour() const -> int
291  {
292  struct tm &tm = toTM();
293  return tm.tm_hour;
294  };
295 
301  auto getMinute() const -> int
302  {
303  struct tm &tm = toTM();
304  return tm.tm_min;
305  };
306 
312  auto getSecond() const -> int
313  {
314  struct tm &tm = toTM();
315  return tm.tm_sec;
316  };
317 
318  /* ---------------------------------------------------------
319  SETTERS
320  --------------------------------------------------------- */
333  void setYear(int year)
334  {
335  int month = getMonth();
336  int new_date = getDate();
337 
338  //윤달에 29일인데 addYear을 하려는 경우 if ( month == 2 && new_date == 29 //현재가 윤달 29일 && !( year == 4 && !((year % 100 == 0 && year % 400 != 0)) ) //바꿀 연도의 2월은 윤달이 아님 ) new_date = 28; set(year, month, new_date); }; /** * @brief Set month of the Date * * @details * If the expiration date of the month will be shrinked, the date will be changed to the expiration date * * \li 2000-03-31 -> setMonth(4) -> 2000-04-30 * \li 2007-08-31 -> setMonth(9) -> 2007-09-30 * * @param val Target month (1 - 12) * @throw invalid_argument month is out of range */ void setMonth(int month) { if (month > 12) throw std::invalid_argument("month is over 12"); //달력 int year = getYear(); int new_date = getDate(); std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (new_date > months[month - 1]) new_date = months[month - 1]; set(year, month, new_date); }; /** * Set date of the Date * * @param val Target day in month * @throw invalid_argument When date is over expiration date in month */ void setDate(int val) { set(getYear(), getMonth(), val); }; /** * @brief Set hour * * @param val Target hour (0 - 23) * @throw invalid_argument When hour is out of range */ void setHour(int val) { addHour(val - getHour()); }; /** * @brief Set minute * * @param val Target minute (0 - 59) * @throw invalid_argument When minute is out of range */ void setMinute(int val) { addMinute(val - getMinute()); }; /** * @brief Set hour * * @param val Target second (0 - 59) * @throw invalid_argument When second is out of range */ void setSecond(int val) { addSecond(val - getSecond()); }; /* -------------------------------------------------------------------------- ADDERS -------------------------------------------------------------------------- */ //ADD METHODS /** * @brief Add years to the Date * * @param val Years to add */ void addYear(int val) { //현재가 2012년 2월 29일(윤달)인데 1년을 추가하면 2013년 2월 28일로 변함 setYear(getYear() + val); }; /** * @brief Add months to the Date * * @details * Not a matter to val is over 12. If the month is over 12, * then years will be added. * * @param val Months to add */ void addMonth(int val) { //현재가 3월 31일인데 1월이 추가되면 날짜는 4월 30일로 변한다 int year = getYear(); int month = getMonth() + val; int date = getDate(); if (month > 12) { year = year + (month - 1) / 12; month = month % 13; } //달력 std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (date > months[month - 1]) date = months[month - 1]; set(year, month, date); }; /** * @brief Add weeks to the Date * * @details * Not a matter that val is too huge. If the adding weeks derives * modification in month or year, then it will be. * * @param val Weeks to add */ void addWeek(int val) { addDate(7 * val); }; /** * @brief Add days to the Date * * @details * Not a matter that val is too huge. If the adding dates derives * modification in month or year, then it will be. * * @param val Days to add */ void addDate(int val) { addHour(24 * val); }; /** * @brief Add hours * * @details * <p> It's same with operator+=(chrono::hours(val)) </p> * * <p> Do not worry about the out of range of the hour(val) * Parent items like date, month and years will be adjusted automatically. </p> * * @param val hours to add */ void addHour(int val) { operator+=(std::chrono::hours(val)); }; /** * @brief Add minutes * * \par It's same with operator+=(chrono::minutes(val)) * * \par * Do not worry about the out of range of the minutes(val) * Parent items like date, month and years will be adjusted automatically. * * @param val minutes to add */ void addMinute(int val) { operator+=(std::chrono::minutes(val)); }; /** * @brief Add seconds * * @details * \par It's same with operator+=(chrono::seconds(val)) * * \par * Do not worry about the out of range of the seconds(val) * Parent items like date, month and years will be adjusted automatically. * * @param val seconds to add */ void addSecond(int val) { operator+=(std::chrono::seconds(val)); }; /* -------------------------------------------------------------------------- EXPORTERS -------------------------------------------------------------------------- */ /** * @brief Converts the Date to struct tm * * @return struct tm representing the Date */ auto toTM() const -> struct ::tm { struct tm tm; time_t tt = std::chrono::system_clock::to_time_t(*this); localtime_s(&tm, &tt); return tm; }; /** * @brief Converts the Date to linux_time * * @return linux_time of the Date */ auto toLinuxTime() const -> long long { std::chrono::system_clock::duration duration = *this - std::chrono::system_clock::from_time_t(0); std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); return seconds.count(); }; /** * @brief Converts the Date to std::string * * @return std::string expressing the Date */ auto toString() const -> std::string { struct tm &tm = toTM(); if (tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0) return StringUtil::substitute ( "{1}-{2}-{3}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday ); else return StringUtil::substitute ( "{1}-{2}-{3} {4}:{5}:{6}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec ); }; }; }; };
339  if
340  (
341  month == 2 && new_date == 29 //현재가 윤달 29일
342  &&
343  !(
344  year == 4 &&
345  !((year % 100 == 0 && year % 400 != 0))
346  ) //바꿀 연도의 2월은 윤달이 아님 ) new_date = 28; set(year, month, new_date); }; /** * @brief Set month of the Date * * @details * If the expiration date of the month will be shrinked, the date will be changed to the expiration date * * \li 2000-03-31 -> setMonth(4) -> 2000-04-30 * \li 2007-08-31 -> setMonth(9) -> 2007-09-30 * * @param val Target month (1 - 12) * @throw invalid_argument month is out of range */ void setMonth(int month) { if (month > 12) throw std::invalid_argument("month is over 12"); //달력 int year = getYear(); int new_date = getDate(); std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (new_date > months[month - 1]) new_date = months[month - 1]; set(year, month, new_date); }; /** * Set date of the Date * * @param val Target day in month * @throw invalid_argument When date is over expiration date in month */ void setDate(int val) { set(getYear(), getMonth(), val); }; /** * @brief Set hour * * @param val Target hour (0 - 23) * @throw invalid_argument When hour is out of range */ void setHour(int val) { addHour(val - getHour()); }; /** * @brief Set minute * * @param val Target minute (0 - 59) * @throw invalid_argument When minute is out of range */ void setMinute(int val) { addMinute(val - getMinute()); }; /** * @brief Set hour * * @param val Target second (0 - 59) * @throw invalid_argument When second is out of range */ void setSecond(int val) { addSecond(val - getSecond()); }; /* -------------------------------------------------------------------------- ADDERS -------------------------------------------------------------------------- */ //ADD METHODS /** * @brief Add years to the Date * * @param val Years to add */ void addYear(int val) { //현재가 2012년 2월 29일(윤달)인데 1년을 추가하면 2013년 2월 28일로 변함 setYear(getYear() + val); }; /** * @brief Add months to the Date * * @details * Not a matter to val is over 12. If the month is over 12, * then years will be added. * * @param val Months to add */ void addMonth(int val) { //현재가 3월 31일인데 1월이 추가되면 날짜는 4월 30일로 변한다 int year = getYear(); int month = getMonth() + val; int date = getDate(); if (month > 12) { year = year + (month - 1) / 12; month = month % 13; } //달력 std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (date > months[month - 1]) date = months[month - 1]; set(year, month, date); }; /** * @brief Add weeks to the Date * * @details * Not a matter that val is too huge. If the adding weeks derives * modification in month or year, then it will be. * * @param val Weeks to add */ void addWeek(int val) { addDate(7 * val); }; /** * @brief Add days to the Date * * @details * Not a matter that val is too huge. If the adding dates derives * modification in month or year, then it will be. * * @param val Days to add */ void addDate(int val) { addHour(24 * val); }; /** * @brief Add hours * * @details * <p> It's same with operator+=(chrono::hours(val)) </p> * * <p> Do not worry about the out of range of the hour(val) * Parent items like date, month and years will be adjusted automatically. </p> * * @param val hours to add */ void addHour(int val) { operator+=(std::chrono::hours(val)); }; /** * @brief Add minutes * * \par It's same with operator+=(chrono::minutes(val)) * * \par * Do not worry about the out of range of the minutes(val) * Parent items like date, month and years will be adjusted automatically. * * @param val minutes to add */ void addMinute(int val) { operator+=(std::chrono::minutes(val)); }; /** * @brief Add seconds * * @details * \par It's same with operator+=(chrono::seconds(val)) * * \par * Do not worry about the out of range of the seconds(val) * Parent items like date, month and years will be adjusted automatically. * * @param val seconds to add */ void addSecond(int val) { operator+=(std::chrono::seconds(val)); }; /* -------------------------------------------------------------------------- EXPORTERS -------------------------------------------------------------------------- */ /** * @brief Converts the Date to struct tm * * @return struct tm representing the Date */ auto toTM() const -> struct ::tm { struct tm tm; time_t tt = std::chrono::system_clock::to_time_t(*this); localtime_s(&tm, &tt); return tm; }; /** * @brief Converts the Date to linux_time * * @return linux_time of the Date */ auto toLinuxTime() const -> long long { std::chrono::system_clock::duration duration = *this - std::chrono::system_clock::from_time_t(0); std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); return seconds.count(); }; /** * @brief Converts the Date to std::string * * @return std::string expressing the Date */ auto toString() const -> std::string { struct tm &tm = toTM(); if (tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0) return StringUtil::substitute ( "{1}-{2}-{3}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday ); else return StringUtil::substitute ( "{1}-{2}-{3} {4}:{5}:{6}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec ); }; }; }; };
347  )
348  new_date = 28;
349 
350  set(year, month, new_date);
351  };
352 
365  void setMonth(int month)
366  {
367  if (month > 12)
368  throw std::invalid_argument("month is over 12");
369 
370  //달력 int year = getYear(); int new_date = getDate(); std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (new_date > months[month - 1]) new_date = months[month - 1]; set(year, month, new_date); }; /** * Set date of the Date * * @param val Target day in month * @throw invalid_argument When date is over expiration date in month */ void setDate(int val) { set(getYear(), getMonth(), val); }; /** * @brief Set hour * * @param val Target hour (0 - 23) * @throw invalid_argument When hour is out of range */ void setHour(int val) { addHour(val - getHour()); }; /** * @brief Set minute * * @param val Target minute (0 - 59) * @throw invalid_argument When minute is out of range */ void setMinute(int val) { addMinute(val - getMinute()); }; /** * @brief Set hour * * @param val Target second (0 - 59) * @throw invalid_argument When second is out of range */ void setSecond(int val) { addSecond(val - getSecond()); }; /* -------------------------------------------------------------------------- ADDERS -------------------------------------------------------------------------- */ //ADD METHODS /** * @brief Add years to the Date * * @param val Years to add */ void addYear(int val) { //현재가 2012년 2월 29일(윤달)인데 1년을 추가하면 2013년 2월 28일로 변함 setYear(getYear() + val); }; /** * @brief Add months to the Date * * @details * Not a matter to val is over 12. If the month is over 12, * then years will be added. * * @param val Months to add */ void addMonth(int val) { //현재가 3월 31일인데 1월이 추가되면 날짜는 4월 30일로 변한다 int year = getYear(); int month = getMonth() + val; int date = getDate(); if (month > 12) { year = year + (month - 1) / 12; month = month % 13; } //달력 std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (date > months[month - 1]) date = months[month - 1]; set(year, month, date); }; /** * @brief Add weeks to the Date * * @details * Not a matter that val is too huge. If the adding weeks derives * modification in month or year, then it will be. * * @param val Weeks to add */ void addWeek(int val) { addDate(7 * val); }; /** * @brief Add days to the Date * * @details * Not a matter that val is too huge. If the adding dates derives * modification in month or year, then it will be. * * @param val Days to add */ void addDate(int val) { addHour(24 * val); }; /** * @brief Add hours * * @details * <p> It's same with operator+=(chrono::hours(val)) </p> * * <p> Do not worry about the out of range of the hour(val) * Parent items like date, month and years will be adjusted automatically. </p> * * @param val hours to add */ void addHour(int val) { operator+=(std::chrono::hours(val)); }; /** * @brief Add minutes * * \par It's same with operator+=(chrono::minutes(val)) * * \par * Do not worry about the out of range of the minutes(val) * Parent items like date, month and years will be adjusted automatically. * * @param val minutes to add */ void addMinute(int val) { operator+=(std::chrono::minutes(val)); }; /** * @brief Add seconds * * @details * \par It's same with operator+=(chrono::seconds(val)) * * \par * Do not worry about the out of range of the seconds(val) * Parent items like date, month and years will be adjusted automatically. * * @param val seconds to add */ void addSecond(int val) { operator+=(std::chrono::seconds(val)); }; /* -------------------------------------------------------------------------- EXPORTERS -------------------------------------------------------------------------- */ /** * @brief Converts the Date to struct tm * * @return struct tm representing the Date */ auto toTM() const -> struct ::tm { struct tm tm; time_t tt = std::chrono::system_clock::to_time_t(*this); localtime_s(&tm, &tt); return tm; }; /** * @brief Converts the Date to linux_time * * @return linux_time of the Date */ auto toLinuxTime() const -> long long { std::chrono::system_clock::duration duration = *this - std::chrono::system_clock::from_time_t(0); std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); return seconds.count(); }; /** * @brief Converts the Date to std::string * * @return std::string expressing the Date */ auto toString() const -> std::string { struct tm &tm = toTM(); if (tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0) return StringUtil::substitute ( "{1}-{2}-{3}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday ); else return StringUtil::substitute ( "{1}-{2}-{3} {4}:{5}:{6}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec ); }; }; }; };
371  int year = getYear();
372  int new_date = getDate();
373 
374  std::array<int, 12> &months = calc_last_dates(year);
375 
376  //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (new_date > months[month - 1]) new_date = months[month - 1]; set(year, month, new_date); }; /** * Set date of the Date * * @param val Target day in month * @throw invalid_argument When date is over expiration date in month */ void setDate(int val) { set(getYear(), getMonth(), val); }; /** * @brief Set hour * * @param val Target hour (0 - 23) * @throw invalid_argument When hour is out of range */ void setHour(int val) { addHour(val - getHour()); }; /** * @brief Set minute * * @param val Target minute (0 - 59) * @throw invalid_argument When minute is out of range */ void setMinute(int val) { addMinute(val - getMinute()); }; /** * @brief Set hour * * @param val Target second (0 - 59) * @throw invalid_argument When second is out of range */ void setSecond(int val) { addSecond(val - getSecond()); }; /* -------------------------------------------------------------------------- ADDERS -------------------------------------------------------------------------- */ //ADD METHODS /** * @brief Add years to the Date * * @param val Years to add */ void addYear(int val) { //현재가 2012년 2월 29일(윤달)인데 1년을 추가하면 2013년 2월 28일로 변함 setYear(getYear() + val); }; /** * @brief Add months to the Date * * @details * Not a matter to val is over 12. If the month is over 12, * then years will be added. * * @param val Months to add */ void addMonth(int val) { //현재가 3월 31일인데 1월이 추가되면 날짜는 4월 30일로 변한다 int year = getYear(); int month = getMonth() + val; int date = getDate(); if (month > 12) { year = year + (month - 1) / 12; month = month % 13; } //달력 std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (date > months[month - 1]) date = months[month - 1]; set(year, month, date); }; /** * @brief Add weeks to the Date * * @details * Not a matter that val is too huge. If the adding weeks derives * modification in month or year, then it will be. * * @param val Weeks to add */ void addWeek(int val) { addDate(7 * val); }; /** * @brief Add days to the Date * * @details * Not a matter that val is too huge. If the adding dates derives * modification in month or year, then it will be. * * @param val Days to add */ void addDate(int val) { addHour(24 * val); }; /** * @brief Add hours * * @details * <p> It's same with operator+=(chrono::hours(val)) </p> * * <p> Do not worry about the out of range of the hour(val) * Parent items like date, month and years will be adjusted automatically. </p> * * @param val hours to add */ void addHour(int val) { operator+=(std::chrono::hours(val)); }; /** * @brief Add minutes * * \par It's same with operator+=(chrono::minutes(val)) * * \par * Do not worry about the out of range of the minutes(val) * Parent items like date, month and years will be adjusted automatically. * * @param val minutes to add */ void addMinute(int val) { operator+=(std::chrono::minutes(val)); }; /** * @brief Add seconds * * @details * \par It's same with operator+=(chrono::seconds(val)) * * \par * Do not worry about the out of range of the seconds(val) * Parent items like date, month and years will be adjusted automatically. * * @param val seconds to add */ void addSecond(int val) { operator+=(std::chrono::seconds(val)); }; /* -------------------------------------------------------------------------- EXPORTERS -------------------------------------------------------------------------- */ /** * @brief Converts the Date to struct tm * * @return struct tm representing the Date */ auto toTM() const -> struct ::tm { struct tm tm; time_t tt = std::chrono::system_clock::to_time_t(*this); localtime_s(&tm, &tt); return tm; }; /** * @brief Converts the Date to linux_time * * @return linux_time of the Date */ auto toLinuxTime() const -> long long { std::chrono::system_clock::duration duration = *this - std::chrono::system_clock::from_time_t(0); std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); return seconds.count(); }; /** * @brief Converts the Date to std::string * * @return std::string expressing the Date */ auto toString() const -> std::string { struct tm &tm = toTM(); if (tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0) return StringUtil::substitute ( "{1}-{2}-{3}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday ); else return StringUtil::substitute ( "{1}-{2}-{3} {4}:{5}:{6}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec ); }; }; }; };
377  //EX-> 4월인데 31일이면 4월 30일로 조정
378  if (new_date > months[month - 1])
379  new_date = months[month - 1];
380 
381  set(year, month, new_date);
382  };
383 
390  void setDate(int val)
391  {
392  set(getYear(), getMonth(), val);
393  };
394 
401  void setHour(int val)
402  {
403  addHour(val - getHour());
404  };
405 
412  void setMinute(int val)
413  {
414  addMinute(val - getMinute());
415  };
416 
423  void setSecond(int val)
424  {
425  addSecond(val - getSecond());
426  };
427 
428  /* --------------------------------------------------------------------------
429  ADDERS
430  -------------------------------------------------------------------------- */
431  //ADD METHODS
437  void addYear(int val)
438  {
439  //현재가 2012년 2월 29일(윤달)인데 1년을 추가하면 2013년 2월 28일로 변함
440  setYear(getYear() + val);
441  };
442 
452  void addMonth(int val)
453  {
454  //현재가 3월 31일인데 1월이 추가되면 날짜는 4월 30일로 변한다 int year = getYear(); int month = getMonth() + val; int date = getDate(); if (month > 12) { year = year + (month - 1) / 12; month = month % 13; } //달력 std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (date > months[month - 1]) date = months[month - 1]; set(year, month, date); }; /** * @brief Add weeks to the Date * * @details * Not a matter that val is too huge. If the adding weeks derives * modification in month or year, then it will be. * * @param val Weeks to add */ void addWeek(int val) { addDate(7 * val); }; /** * @brief Add days to the Date * * @details * Not a matter that val is too huge. If the adding dates derives * modification in month or year, then it will be. * * @param val Days to add */ void addDate(int val) { addHour(24 * val); }; /** * @brief Add hours * * @details * <p> It's same with operator+=(chrono::hours(val)) </p> * * <p> Do not worry about the out of range of the hour(val) * Parent items like date, month and years will be adjusted automatically. </p> * * @param val hours to add */ void addHour(int val) { operator+=(std::chrono::hours(val)); }; /** * @brief Add minutes * * \par It's same with operator+=(chrono::minutes(val)) * * \par * Do not worry about the out of range of the minutes(val) * Parent items like date, month and years will be adjusted automatically. * * @param val minutes to add */ void addMinute(int val) { operator+=(std::chrono::minutes(val)); }; /** * @brief Add seconds * * @details * \par It's same with operator+=(chrono::seconds(val)) * * \par * Do not worry about the out of range of the seconds(val) * Parent items like date, month and years will be adjusted automatically. * * @param val seconds to add */ void addSecond(int val) { operator+=(std::chrono::seconds(val)); }; /* -------------------------------------------------------------------------- EXPORTERS -------------------------------------------------------------------------- */ /** * @brief Converts the Date to struct tm * * @return struct tm representing the Date */ auto toTM() const -> struct ::tm { struct tm tm; time_t tt = std::chrono::system_clock::to_time_t(*this); localtime_s(&tm, &tt); return tm; }; /** * @brief Converts the Date to linux_time * * @return linux_time of the Date */ auto toLinuxTime() const -> long long { std::chrono::system_clock::duration duration = *this - std::chrono::system_clock::from_time_t(0); std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); return seconds.count(); }; /** * @brief Converts the Date to std::string * * @return std::string expressing the Date */ auto toString() const -> std::string { struct tm &tm = toTM(); if (tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0) return StringUtil::substitute ( "{1}-{2}-{3}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday ); else return StringUtil::substitute ( "{1}-{2}-{3} {4}:{5}:{6}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec ); }; }; }; };
455  int year = getYear();
456  int month = getMonth() + val;
457  int date = getDate();
458 
459  if (month > 12)
460  {
461  year = year + (month - 1) / 12;
462  month = month % 13;
463  }
464 
465  //달력 std::array<int, 12> &months = calc_last_dates(year); //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (date > months[month - 1]) date = months[month - 1]; set(year, month, date); }; /** * @brief Add weeks to the Date * * @details * Not a matter that val is too huge. If the adding weeks derives * modification in month or year, then it will be. * * @param val Weeks to add */ void addWeek(int val) { addDate(7 * val); }; /** * @brief Add days to the Date * * @details * Not a matter that val is too huge. If the adding dates derives * modification in month or year, then it will be. * * @param val Days to add */ void addDate(int val) { addHour(24 * val); }; /** * @brief Add hours * * @details * <p> It's same with operator+=(chrono::hours(val)) </p> * * <p> Do not worry about the out of range of the hour(val) * Parent items like date, month and years will be adjusted automatically. </p> * * @param val hours to add */ void addHour(int val) { operator+=(std::chrono::hours(val)); }; /** * @brief Add minutes * * \par It's same with operator+=(chrono::minutes(val)) * * \par * Do not worry about the out of range of the minutes(val) * Parent items like date, month and years will be adjusted automatically. * * @param val minutes to add */ void addMinute(int val) { operator+=(std::chrono::minutes(val)); }; /** * @brief Add seconds * * @details * \par It's same with operator+=(chrono::seconds(val)) * * \par * Do not worry about the out of range of the seconds(val) * Parent items like date, month and years will be adjusted automatically. * * @param val seconds to add */ void addSecond(int val) { operator+=(std::chrono::seconds(val)); }; /* -------------------------------------------------------------------------- EXPORTERS -------------------------------------------------------------------------- */ /** * @brief Converts the Date to struct tm * * @return struct tm representing the Date */ auto toTM() const -> struct ::tm { struct tm tm; time_t tt = std::chrono::system_clock::to_time_t(*this); localtime_s(&tm, &tt); return tm; }; /** * @brief Converts the Date to linux_time * * @return linux_time of the Date */ auto toLinuxTime() const -> long long { std::chrono::system_clock::duration duration = *this - std::chrono::system_clock::from_time_t(0); std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); return seconds.count(); }; /** * @brief Converts the Date to std::string * * @return std::string expressing the Date */ auto toString() const -> std::string { struct tm &tm = toTM(); if (tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0) return StringUtil::substitute ( "{1}-{2}-{3}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday ); else return StringUtil::substitute ( "{1}-{2}-{3} {4}:{5}:{6}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec ); }; }; }; };
466  std::array<int, 12> &months = calc_last_dates(year);
467 
468  //해당 월의 마지막 일을 초과할 때, 조정한다 //EX-> 4월인데 31일이면 4월 30일로 조정 if (date > months[month - 1]) date = months[month - 1]; set(year, month, date); }; /** * @brief Add weeks to the Date * * @details * Not a matter that val is too huge. If the adding weeks derives * modification in month or year, then it will be. * * @param val Weeks to add */ void addWeek(int val) { addDate(7 * val); }; /** * @brief Add days to the Date * * @details * Not a matter that val is too huge. If the adding dates derives * modification in month or year, then it will be. * * @param val Days to add */ void addDate(int val) { addHour(24 * val); }; /** * @brief Add hours * * @details * <p> It's same with operator+=(chrono::hours(val)) </p> * * <p> Do not worry about the out of range of the hour(val) * Parent items like date, month and years will be adjusted automatically. </p> * * @param val hours to add */ void addHour(int val) { operator+=(std::chrono::hours(val)); }; /** * @brief Add minutes * * \par It's same with operator+=(chrono::minutes(val)) * * \par * Do not worry about the out of range of the minutes(val) * Parent items like date, month and years will be adjusted automatically. * * @param val minutes to add */ void addMinute(int val) { operator+=(std::chrono::minutes(val)); }; /** * @brief Add seconds * * @details * \par It's same with operator+=(chrono::seconds(val)) * * \par * Do not worry about the out of range of the seconds(val) * Parent items like date, month and years will be adjusted automatically. * * @param val seconds to add */ void addSecond(int val) { operator+=(std::chrono::seconds(val)); }; /* -------------------------------------------------------------------------- EXPORTERS -------------------------------------------------------------------------- */ /** * @brief Converts the Date to struct tm * * @return struct tm representing the Date */ auto toTM() const -> struct ::tm { struct tm tm; time_t tt = std::chrono::system_clock::to_time_t(*this); localtime_s(&tm, &tt); return tm; }; /** * @brief Converts the Date to linux_time * * @return linux_time of the Date */ auto toLinuxTime() const -> long long { std::chrono::system_clock::duration duration = *this - std::chrono::system_clock::from_time_t(0); std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); return seconds.count(); }; /** * @brief Converts the Date to std::string * * @return std::string expressing the Date */ auto toString() const -> std::string { struct tm &tm = toTM(); if (tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0) return StringUtil::substitute ( "{1}-{2}-{3}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday ); else return StringUtil::substitute ( "{1}-{2}-{3} {4}:{5}:{6}", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec ); }; }; }; };
469  //EX-> 4월인데 31일이면 4월 30일로 조정
470  if (date > months[month - 1])
471  date = months[month - 1];
472 
473  set(year, month, date);
474  };
475 
485  void addWeek(int val)
486  {
487  addDate(7 * val);
488  };
489 
499  void addDate(int val)
500  {
501  addHour(24 * val);
502  };
503 
515  void addHour(int val)
516  {
517  operator+=(std::chrono::hours(val));
518  };
519 
531  void addMinute(int val)
532  {
533  operator+=(std::chrono::minutes(val));
534  };
535 
548  void addSecond(int val)
549  {
550  operator+=(std::chrono::seconds(val));
551  };
552 
553  /* --------------------------------------------------------------------------
554  EXPORTERS
555  -------------------------------------------------------------------------- */
561  auto toTM() const -> struct ::tm
562  {
563  struct tm tm;
564  time_t tt = std::chrono::system_clock::to_time_t(*this);
565  localtime_s(&tm, &tt);
566 
567  return tm;
568  };
569 
575  auto toLinuxTime() const -> long long
576  {
577  std::chrono::system_clock::duration duration = *this - std::chrono::system_clock::from_time_t(0);
578  std::chrono::seconds seconds = std::chrono::duration_cast<std::chrono::seconds>(duration);
579 
580  return seconds.count();
581  };
582 
588  auto toString() const -> std::string
589  {
590  struct tm &tm = toTM();
591 
592  if (tm.tm_hour == 0 && tm.tm_min == 0 && tm.tm_sec == 0)
594  (
595  "{1}-{2}-{3}",
596  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday
597  );
598  else
600  (
601  "{1}-{2}-{3} {4}:{5}:{6}",
602  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
603  tm.tm_hour, tm.tm_min, tm.tm_sec
604  );
605  };
606  };
607 };
608 };
auto getYear() const -> int
Get year of the Date.
Definition: Date.hpp:246
auto getHour() const -> int
Get hour.
Definition: Date.hpp:290
Date(long long linuxTime)
Construct from linux_time.
Definition: Date.hpp:154
Date()
Default Constructor.
Definition: Date.hpp:96
void setHour(int val)
Set hour.
Definition: Date.hpp:401
Date(const super &date)
Copy Constructor.
Definition: Date.hpp:106
Date(const std::string &str)
Construct from string.
Definition: Date.hpp:139
void setYear(int year)
Set year of the Date.
Definition: Date.hpp:333
void setSecond(int val)
Set hour.
Definition: Date.hpp:423
static auto calc_seconds(int year, int month, int date) -> long long
Calculates how many seconds have flowen since 0000-01-01 00:00:00.
Definition: Date.hpp:50
static auto substitute(const std::string &format, const T &val, const _Args &...args) -> std::string
Substitutes "{n}" tokens within the specified string with the respective arguments passed in...
Definition: StringUtil.hpp:54
void addMonth(int val)
Add months to the Date.
Definition: Date.hpp:452
auto between(const WeakString &start={}, const WeakString &end={}) const -> WeakString
Generates a substring.
Definition: WeakString.hpp:475
auto toString() const -> std::string
Converts the Date to std::string.
Definition: Date.hpp:588
void addHour(int val)
Add hours.
Definition: Date.hpp:515
auto getSecond() const -> int
Get second.
Definition: Date.hpp:312
void setDate(int val)
Definition: Date.hpp:390
auto find(const WeakString &delim, size_t startIndex=NULL) const -> size_t
Finds first occurence in string.
Definition: WeakString.hpp:273
void addDate(int val)
Add days to the Date.
Definition: Date.hpp:499
auto getMonth() const -> int
Get month of the Date.
Definition: Date.hpp:257
auto getDate() const -> int
Get the day in month of the Date.
Definition: Date.hpp:268
void setMonth(int month)
Set month of the Date.
Definition: Date.hpp:365
Date(super &&date)
Definition: Date.hpp:116
static auto calc_last_dates(int year) -> std::array< int, 12 >
Calculates and gets an array of final date of each month for that year.
Definition: Date.hpp:74
auto substr(size_t startIndex, size_t size=SIZE_MAX) const -> WeakString
Generates a substring.
Definition: WeakString.hpp:419
auto toTM() const -> struct::tm
Converts the Date to struct tm.
Definition: Date.hpp:561
auto getMinute() const -> int
Get minute.
Definition: Date.hpp:301
void addSecond(int val)
Add seconds.
Definition: Date.hpp:548
Date (year, month, day in month)
Definition: Date.hpp:38
auto getDay() const -> int
Get the day in week of the Date.
Definition: Date.hpp:279
void setMinute(int val)
Set minute.
Definition: Date.hpp:412
Date(int year, int month, int date, int hour=0, int min=0, int sec=0)
Construct from date elements.
Definition: Date.hpp:128
auto split(const WeakString &delim) const -> std::vector< WeakString >
Generates substrings.
Definition: WeakString.hpp:502
void addWeek(int val)
Add weeks to the Date.
Definition: Date.hpp:485
void addYear(int val)
Add years to the Date.
Definition: Date.hpp:437
auto toLinuxTime() const -> long long
Converts the Date to linux_time.
Definition: Date.hpp:575
A string class only references characeters, reference only.
Definition: WeakString.hpp:35
void addMinute(int val)
Add minutes.
Definition: Date.hpp:531