2014-04-08 06:51:53 +00:00
|
|
|
|
#pragma once
|
2011-03-10 20:31:02 +00:00
|
|
|
|
|
|
|
|
|
#include <string>
|
2014-10-28 17:55:07 +00:00
|
|
|
|
#include <iomanip>
|
2016-02-03 01:17:58 +00:00
|
|
|
|
#include <exception>
|
|
|
|
|
#include <common/DateLUT.h>
|
|
|
|
|
#include <common/LocalDate.h>
|
2011-03-10 20:31:02 +00:00
|
|
|
|
|
|
|
|
|
|
2011-03-18 20:26:54 +00:00
|
|
|
|
/** Хранит дату и время в broken-down виде.
|
|
|
|
|
* Может быть инициализирован из даты и времени в текстовом виде '2011-01-01 00:00:00' и из time_t.
|
|
|
|
|
* Неявно преобразуется в time_t.
|
|
|
|
|
* Сериализуется в ostream в текстовом виде.
|
|
|
|
|
* Внимание: преобразование в unix timestamp и обратно производится в текущей тайм-зоне!
|
|
|
|
|
* При переводе стрелок назад, возникает неоднозначность - преобразование производится в меньшее значение.
|
|
|
|
|
*
|
2011-03-31 15:38:32 +00:00
|
|
|
|
* packed - для memcmp (из-за того, что m_year - 2 байта, little endian, работает корректно только до 2047 года)
|
2011-03-18 20:26:54 +00:00
|
|
|
|
*/
|
2016-02-03 01:17:58 +00:00
|
|
|
|
class __attribute__ ((__packed__)) LocalDateTime
|
2011-03-10 20:31:02 +00:00
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
unsigned short m_year;
|
|
|
|
|
unsigned char m_month;
|
|
|
|
|
unsigned char m_day;
|
|
|
|
|
unsigned char m_hour;
|
|
|
|
|
unsigned char m_minute;
|
|
|
|
|
unsigned char m_second;
|
2015-03-25 10:08:04 +00:00
|
|
|
|
|
2011-03-10 20:31:02 +00:00
|
|
|
|
void init(time_t time)
|
|
|
|
|
{
|
2012-06-07 20:02:41 +00:00
|
|
|
|
if (unlikely(time > DATE_LUT_MAX || time == 0))
|
|
|
|
|
{
|
|
|
|
|
m_year = 0;
|
|
|
|
|
m_month = 0;
|
|
|
|
|
m_day = 0;
|
|
|
|
|
m_hour = 0;
|
|
|
|
|
m_minute = 0;
|
|
|
|
|
m_second = 0;
|
2015-03-25 10:08:04 +00:00
|
|
|
|
|
2012-06-07 20:02:41 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2015-03-25 10:08:04 +00:00
|
|
|
|
|
2015-07-07 23:11:30 +00:00
|
|
|
|
const auto & date_lut = DateLUT::instance();
|
2015-06-26 15:11:31 +00:00
|
|
|
|
const auto & values = date_lut.getValues(time);
|
2011-03-10 20:31:02 +00:00
|
|
|
|
|
|
|
|
|
m_year = values.year;
|
|
|
|
|
m_month = values.month;
|
|
|
|
|
m_day = values.day_of_month;
|
2016-12-27 06:36:53 +00:00
|
|
|
|
m_hour = date_lut.toHour(time);
|
2012-08-31 20:38:05 +00:00
|
|
|
|
m_minute = date_lut.toMinuteInaccurate(time);
|
|
|
|
|
m_second = date_lut.toSecondInaccurate(time);
|
2011-03-10 20:31:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void init(const char * s, size_t length)
|
|
|
|
|
{
|
|
|
|
|
if (length < 19)
|
2016-02-03 01:17:58 +00:00
|
|
|
|
throw std::runtime_error("Cannot parse LocalDateTime: " + std::string(s, length));
|
2011-03-10 20:31:02 +00:00
|
|
|
|
|
2011-03-15 21:14:05 +00:00
|
|
|
|
m_year = (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0');
|
|
|
|
|
m_month = (s[5] - '0') * 10 + (s[6] - '0');
|
|
|
|
|
m_day = (s[8] - '0') * 10 + (s[9] - '0');
|
2011-03-10 20:31:02 +00:00
|
|
|
|
|
2011-03-15 21:14:05 +00:00
|
|
|
|
m_hour = (s[11] - '0') * 10 + (s[12] - '0');
|
|
|
|
|
m_minute = (s[14] - '0') * 10 + (s[15] - '0');
|
|
|
|
|
m_second = (s[17] - '0') * 10 + (s[18] - '0');
|
2011-03-10 20:31:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2016-02-03 01:17:58 +00:00
|
|
|
|
explicit LocalDateTime(time_t time)
|
2011-03-10 20:31:02 +00:00
|
|
|
|
{
|
|
|
|
|
init(time);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
LocalDateTime(unsigned short year_, unsigned char month_, unsigned char day_,
|
2011-03-10 20:31:02 +00:00
|
|
|
|
unsigned char hour_, unsigned char minute_, unsigned char second_)
|
|
|
|
|
: m_year(year_), m_month(month_), m_day(day_), m_hour(hour_), m_minute(minute_), m_second(second_)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
explicit LocalDateTime(const std::string & s)
|
2011-03-10 20:31:02 +00:00
|
|
|
|
{
|
|
|
|
|
if (s.size() < 19)
|
2016-02-03 01:17:58 +00:00
|
|
|
|
throw std::runtime_error("Cannot parse LocalDateTime: " + s);
|
2011-03-10 20:31:02 +00:00
|
|
|
|
|
2011-04-25 20:31:34 +00:00
|
|
|
|
init(s.data(), s.size());
|
2011-03-10 20:31:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
LocalDateTime() : m_year(0), m_month(0), m_day(0), m_hour(0), m_minute(0), m_second(0)
|
2011-03-10 20:31:02 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
LocalDateTime(const char * data, size_t length)
|
2011-03-10 20:31:02 +00:00
|
|
|
|
{
|
|
|
|
|
init(data, length);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
LocalDateTime(const LocalDateTime & x)
|
2011-04-25 20:31:34 +00:00
|
|
|
|
{
|
|
|
|
|
operator=(x);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
LocalDateTime & operator= (const LocalDateTime & x)
|
2011-04-25 20:31:34 +00:00
|
|
|
|
{
|
|
|
|
|
m_year = x.m_year;
|
|
|
|
|
m_month = x.m_month;
|
|
|
|
|
m_day = x.m_day;
|
|
|
|
|
m_hour = x.m_hour;
|
|
|
|
|
m_minute = x.m_minute;
|
|
|
|
|
m_second = x.m_second;
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
LocalDateTime & operator= (time_t time)
|
2011-03-15 20:56:42 +00:00
|
|
|
|
{
|
|
|
|
|
init(time);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-10 20:31:02 +00:00
|
|
|
|
operator time_t() const
|
|
|
|
|
{
|
2012-06-07 20:22:15 +00:00
|
|
|
|
return m_year == 0
|
|
|
|
|
? 0
|
2014-07-08 23:52:53 +00:00
|
|
|
|
: DateLUT::instance().makeDateTime(m_year, m_month, m_day, m_hour, m_minute, m_second);
|
2011-03-10 20:31:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned short year() const { return m_year; }
|
|
|
|
|
unsigned char month() const { return m_month; }
|
|
|
|
|
unsigned char day() const { return m_day; }
|
|
|
|
|
unsigned char hour() const { return m_hour; }
|
|
|
|
|
unsigned char minute() const { return m_minute; }
|
|
|
|
|
unsigned char second() const { return m_second; }
|
|
|
|
|
|
|
|
|
|
void year(unsigned short x) { m_year = x; }
|
|
|
|
|
void month(unsigned char x) { m_month = x; }
|
|
|
|
|
void day(unsigned char x) { m_day = x; }
|
|
|
|
|
void hour(unsigned char x) { m_hour = x; }
|
|
|
|
|
void minute(unsigned char x) { m_minute = x; }
|
|
|
|
|
void second(unsigned char x) { m_second = x; }
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
LocalDate toDate() const { return LocalDate(m_year, m_month, m_day); }
|
2011-03-15 20:56:42 +00:00
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
LocalDateTime toStartOfDate() { return LocalDateTime(m_year, m_month, m_day, 0, 0, 0); }
|
2012-07-20 19:54:25 +00:00
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
bool operator< (const LocalDateTime & other) const
|
2011-03-10 20:31:02 +00:00
|
|
|
|
{
|
2011-10-14 18:03:25 +00:00
|
|
|
|
return 0 > memcmp(this, &other, sizeof(*this));
|
2011-03-10 20:31:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
bool operator> (const LocalDateTime & other) const
|
2011-03-21 19:46:50 +00:00
|
|
|
|
{
|
2011-10-14 18:03:25 +00:00
|
|
|
|
return 0 < memcmp(this, &other, sizeof(*this));
|
2011-03-21 19:46:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
bool operator<= (const LocalDateTime & other) const
|
2011-03-21 19:46:50 +00:00
|
|
|
|
{
|
|
|
|
|
return 0 >= memcmp(this, &other, sizeof(*this));
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
bool operator>= (const LocalDateTime & other) const
|
2011-03-21 19:46:50 +00:00
|
|
|
|
{
|
|
|
|
|
return 0 <= memcmp(this, &other, sizeof(*this));
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
bool operator== (const LocalDateTime & other) const
|
2011-03-10 20:31:02 +00:00
|
|
|
|
{
|
2011-03-15 20:56:42 +00:00
|
|
|
|
return 0 == memcmp(this, &other, sizeof(*this));
|
2011-03-10 20:31:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
bool operator!= (const LocalDateTime & other) const
|
2011-03-10 20:31:02 +00:00
|
|
|
|
{
|
|
|
|
|
return !(*this == other);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2016-02-03 01:17:58 +00:00
|
|
|
|
inline std::ostream & operator<< (std::ostream & ostr, const LocalDateTime & datetime)
|
2011-03-10 20:31:02 +00:00
|
|
|
|
{
|
2014-11-14 20:55:23 +00:00
|
|
|
|
ostr << std::setfill('0') << std::setw(4) << datetime.year();
|
2014-10-28 17:55:07 +00:00
|
|
|
|
|
|
|
|
|
ostr << '-' << (datetime.month() / 10) << (datetime.month() % 10)
|
2011-03-10 20:31:02 +00:00
|
|
|
|
<< '-' << (datetime.day() / 10) << (datetime.day() % 10)
|
|
|
|
|
<< ' ' << (datetime.hour() / 10) << (datetime.hour() % 10)
|
|
|
|
|
<< ':' << (datetime.minute() / 10) << (datetime.minute() % 10)
|
|
|
|
|
<< ':' << (datetime.second() / 10) << (datetime.second() % 10);
|
2014-10-28 17:55:07 +00:00
|
|
|
|
|
|
|
|
|
return ostr;
|
2011-03-10 20:31:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-25 10:08:04 +00:00
|
|
|
|
|
|
|
|
|
namespace std
|
|
|
|
|
{
|
2016-02-03 01:17:58 +00:00
|
|
|
|
inline string to_string(const LocalDateTime & datetime)
|
2015-03-25 10:08:04 +00:00
|
|
|
|
{
|
|
|
|
|
stringstream str;
|
|
|
|
|
str << datetime;
|
|
|
|
|
return str.str();
|
|
|
|
|
}
|
|
|
|
|
}
|