1 #include "lib/datetime.hpp"
2 #include "lib/log.hpp"
3
4 #define LOCALE_TIME_FORMAT "%X"
5 #define LOCALE_DATE_FORMAT "%x"
6 #define ISO_DATE_FORMAT "%Y-%m-%d"
7 #define ISO_DATE_TIME_FORMAT "%Y-%m-%dT%H:%M:%SZ"
8
date_time(const date_time & date)9 lib::date_time::date_time(const date_time &date)
10 {
11 tm = date.tm;
12 }
13
date_time(int year,int month,int day,int hour,int minute,int second)14 lib::date_time::date_time(int year, int month, int day, int hour, int minute, int second)
15 {
16 tm.tm_year = year - c_year_offset;
17 tm.tm_mon = month - 1;
18 tm.tm_mday = day;
19 tm.tm_hour = hour;
20 tm.tm_min = minute;
21 tm.tm_sec = second;
22 }
23
parse(const std::string & value)24 auto lib::date_time::parse(const std::string &value) -> lib::date_time
25 {
26 lib::date_time date;
27
28 // First try to parse as full date and time
29 date.parse(value, ISO_DATE_TIME_FORMAT);
30
31 // Then try to pars as date only
32 if (!date.is_valid())
33 {
34 date.parse(value, ISO_DATE_FORMAT);
35 }
36
37 // If it's still invalid, something is wrong
38 if (!date.is_valid())
39 {
40 log::warn("Failed to parse \"{}\" as a date", value);
41 }
42
43 return date;
44 }
45
now()46 auto lib::date_time::now() -> lib::date_time
47 {
48 lib::date_time date;
49 auto time = std::time(nullptr);
50 date.tm = *std::localtime(&time);
51
52 return date;
53 }
54
now_utc()55 auto lib::date_time::now_utc() -> lib::date_time
56 {
57 lib::date_time date;
58 auto time = std::time(nullptr);
59 date.tm = *std::gmtime(&time);
60
61 return date;
62 }
63
seconds_since_epoch()64 auto lib::date_time::seconds_since_epoch() -> long
65 {
66 return std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now()
67 .time_since_epoch()).count();
68 }
69
is_valid() const70 auto lib::date_time::is_valid() const -> bool
71 {
72 return tm.tm_year > 0
73 || tm.tm_mon > 0
74 || tm.tm_mday > 0;
75 }
76
parse(const std::string & value,const char * format)77 void lib::date_time::parse(const std::string &value, const char *format)
78 {
79 std::istringstream ss(value);
80 ss >> std::get_time(&tm, format);
81 }
82
to_time() const83 auto lib::date_time::to_time() const -> std::string
84 {
85 return format(LOCALE_TIME_FORMAT);
86 }
87
to_date() const88 auto lib::date_time::to_date() const -> std::string
89 {
90 return format(LOCALE_DATE_FORMAT);
91 }
92
to_iso_date() const93 auto lib::date_time::to_iso_date() const -> std::string
94 {
95 return format(ISO_DATE_FORMAT);
96 }
97
to_iso_date_time() const98 auto lib::date_time::to_iso_date_time() const -> std::string
99 {
100 return format(ISO_DATE_TIME_FORMAT);
101 }
102
format(const char * format) const103 auto lib::date_time::format(const char *format) const -> std::string
104 {
105 if (!is_valid())
106 {
107 return std::string();
108 }
109
110 constexpr size_t buffer_size = 64;
111 std::array<char, buffer_size> buffer;
112 std::strftime(buffer.data(), buffer.size(), format, &tm);
113 return std::string(buffer.data());
114 }
115
get_second() const116 auto lib::date_time::get_second() const -> int
117 {
118 return is_valid()
119 ? tm.tm_sec
120 : 0;
121 }
122
get_minute() const123 auto lib::date_time::get_minute() const -> int
124 {
125 return is_valid()
126 ? tm.tm_min
127 : 0;
128 }
129
get_hour() const130 auto lib::date_time::get_hour() const -> int
131 {
132 return is_valid()
133 ? tm.tm_hour
134 : 0;
135 }
136
get_day() const137 auto lib::date_time::get_day() const -> int
138 {
139 return is_valid()
140 ? tm.tm_mday
141 : 0;
142 }
143
get_month() const144 auto lib::date_time::get_month() const -> int
145 {
146 return 1 + (is_valid()
147 ? tm.tm_mon
148 : 0);
149 }
150
get_year() const151 auto lib::date_time::get_year() const -> int
152 {
153 return c_year_offset + (is_valid()
154 ? tm.tm_year
155 : 0);
156 }
157