/* * A Date Time Implementation * Copyright(C) 2003-2013 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * @file: nana/datetime.cpp */ #include #include #if defined(NANA_WINDOWS) #include #endif #include namespace { std::tm localtime() { #if defined(NANA_WINDOWS) && !defined(NANA_MINGW) time_t t; ::time(&t); std::tm tm; if(localtime_s(&tm, &t) != 0) assert(false); return tm; #else time_t t = std::time(nullptr); struct tm * tm_addr = std::localtime(&t); assert(tm_addr); return *tm_addr; #endif } ::nana::date::value to_dateval(const std::tm& t) { return {static_cast(t.tm_year + 1900), static_cast(t.tm_mon + 1), static_cast(t.tm_mday)}; } ::nana::time::value to_timeval(const std::tm& t) { return {static_cast(t.tm_hour), static_cast(t.tm_min), static_cast(t.tm_sec)}; } } // namespace anonymous namespace nana { //class date void date::set(const std::tm& t) { value_ = to_dateval(t); } date::date() : value_(to_dateval(*std::localtime(nullptr))) { } date::date(const std::tm& t) : value_(to_dateval(t)) { } date::date(int year, int month, int day) : value_({static_cast(year), static_cast(month), static_cast(day)}) { if(1601 <= year && year < 30827 && 0 < month && month < 13 && day > 0) { if(day <= static_cast(date::month_days(year, month))) return; } set(localtime()); } date date::operator - (int off) const { if(off < 0) return _m_add(static_cast(-off)); return _m_sub(static_cast(off)); } date date::operator + (int off) const { if(off < 0) return _m_sub(static_cast(-off)); return _m_add(static_cast(off)); } bool date::operator==(const date& r) const { return (r.value_.year == value_.year && r.value_.month == value_.month && r.value_.day == value_.day); } bool date::operator!=(const date& r) const { return ! (this->operator==(r)); } bool date::operator <(const date & r) const { if(value_.year < r.value_.year) { return true; } else if(value_.year == r.value_.year) { if(value_.month < r.value_.month) return true; else if(value_.month == r.value_.month) return (value_.day < r.value_.day); } return false; } bool date::operator>(const date & r) const { if(value_.year > r.value_.year) { return true; } else if(value_.year == r.value_.year) { if(value_.month > r.value_.month) return true; else if(value_.month == r.value_.month) return (value_.day > r.value_.day); } return false; } bool date::operator<=(const date& r) const { return !(this->operator>(r)); } bool date::operator>=(const date& r) const { return !(this->operator<(r)); } int date::day_of_week() const { return day_of_week(static_cast(value_.year), static_cast(value_.month), static_cast(value_.day)); } int date::day_of_week(int year, int month, int day) { //w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1; //the Jan and Feb of Every year are treated as the 13th/14th month of last year. if(month < 3) { month += 12; --year; } int century = year / 100; year = year % 100; int w = year + (year / 4) + (century / 4) - (2 * century) + (26 * ( month + 1) / 10) + day - 1; if(w >= 0) return (w % 7); return ((1 - (w / 7)) * 7 + w); } const date::value & date::read() const { return this->value_; } date date::_m_add(unsigned x) const { date d(*this); while(x) { unsigned off = month_days(d.value_.year, d.value_.month) - d.value_.day; if(off < x) { d.value_.day = 1; if(d.value_.month == 12) { d.value_.month = 1; ++ d.value_.year; } else ++ d.value_.month; x -= (off + 1); } else if(off >= x) { d.value_.day += x; break; } } return d; } date date::_m_sub(unsigned x) const { date d(*this); while(x) { if(d.value_.day <= x) { if(d.value_.month == 1) { d.value_.month = 12; -- d.value_.year; } else -- d.value_.month; d.value_.day = month_days(d.value_.year, d.value_.month); x -= d.value_.day; } else { d.value_.day -= x; break; } } return d; } unsigned date::day_in_year(unsigned y, unsigned m, unsigned d) { unsigned days = 0; for(unsigned i = 1; i < m; ++i) days += month_days(y, i); return days + d; } unsigned date::month_days(unsigned year, unsigned month) { unsigned num[] = {31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if(month != 2) return num[month - 1]; if(((year % 4 == 0) && (year % 100)) || (year % 400 == 0)) return 29; return 28; } unsigned date::year_days(unsigned year) { if(((year % 4 == 0) && (year % 100)) || (year % 400 == 0)) return 366; return 365; } //end class date //class time void time::set(const std::tm& t) { value_ = to_timeval(t); } time::time() : value_(to_timeval(localtime())) { } time::time(const std::tm& t) : value_(to_timeval(t)) { } time::time(unsigned hour, unsigned minute, unsigned second) : value_({hour, minute, second}) { if(hour < 24 && minute < 60 && second < 62) return; set(localtime()); } const time::value& time::read() const { return value_; } //end class time }//end namespace nana