1 | // Copyright 2016 Google Inc. All Rights Reserved. |
2 | // |
3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | // you may not use this file except in compliance with the License. |
5 | // You may obtain a copy of the License at |
6 | // |
7 | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | // |
9 | // Unless required by applicable law or agreed to in writing, software |
10 | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | // See the License for the specific language governing permissions and |
13 | // limitations under the License. |
14 | |
15 | #ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ |
16 | #define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ |
17 | |
18 | #include "absl/time/internal/cctz/include/cctz/civil_time_detail.h" |
19 | |
20 | namespace absl { |
21 | namespace time_internal { |
22 | namespace cctz { |
23 | |
24 | // The term "civil time" refers to the legally recognized human-scale time |
25 | // that is represented by the six fields YYYY-MM-DD hh:mm:ss. Modern-day civil |
26 | // time follows the Gregorian Calendar and is a time-zone-independent concept. |
27 | // A "date" is perhaps the most common example of a civil time (represented in |
28 | // this library as cctz::civil_day). This library provides six classes and a |
29 | // handful of functions that help with rounding, iterating, and arithmetic on |
30 | // civil times while avoiding complications like daylight-saving time (DST). |
31 | // |
32 | // The following six classes form the core of this civil-time library: |
33 | // |
34 | // * civil_second |
35 | // * civil_minute |
36 | // * civil_hour |
37 | // * civil_day |
38 | // * civil_month |
39 | // * civil_year |
40 | // |
41 | // Each class is a simple value type with the same interface for construction |
42 | // and the same six accessors for each of the civil fields (year, month, day, |
43 | // hour, minute, and second, aka YMDHMS). These classes differ only in their |
44 | // alignment, which is indicated by the type name and specifies the field on |
45 | // which arithmetic operates. |
46 | // |
47 | // Each class can be constructed by passing up to six optional integer |
48 | // arguments representing the YMDHMS fields (in that order) to the |
49 | // constructor. Omitted fields are assigned their minimum valid value. Hours, |
50 | // minutes, and seconds will be set to 0, month and day will be set to 1, and |
51 | // since there is no minimum valid year, it will be set to 1970. So, a |
52 | // default-constructed civil-time object will have YMDHMS fields representing |
53 | // "1970-01-01 00:00:00". Fields that are out-of-range are normalized (e.g., |
54 | // October 32 -> November 1) so that all civil-time objects represent valid |
55 | // values. |
56 | // |
57 | // Each civil-time class is aligned to the civil-time field indicated in the |
58 | // class's name after normalization. Alignment is performed by setting all the |
59 | // inferior fields to their minimum valid value (as described above). The |
60 | // following are examples of how each of the six types would align the fields |
61 | // representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the |
62 | // string format used here is not important; it's just a shorthand way of |
63 | // showing the six YMDHMS fields.) |
64 | // |
65 | // civil_second 2015-11-22 12:34:56 |
66 | // civil_minute 2015-11-22 12:34:00 |
67 | // civil_hour 2015-11-22 12:00:00 |
68 | // civil_day 2015-11-22 00:00:00 |
69 | // civil_month 2015-11-01 00:00:00 |
70 | // civil_year 2015-01-01 00:00:00 |
71 | // |
72 | // Each civil-time type performs arithmetic on the field to which it is |
73 | // aligned. This means that adding 1 to a civil_day increments the day field |
74 | // (normalizing as necessary), and subtracting 7 from a civil_month operates |
75 | // on the month field (normalizing as necessary). All arithmetic produces a |
76 | // valid civil time. Difference requires two similarly aligned civil-time |
77 | // objects and returns the scalar answer in units of the objects' alignment. |
78 | // For example, the difference between two civil_hour objects will give an |
79 | // answer in units of civil hours. |
80 | // |
81 | // In addition to the six civil-time types just described, there are |
82 | // a handful of helper functions and algorithms for performing common |
83 | // calculations. These are described below. |
84 | // |
85 | // Note: In C++14 and later, this library is usable in a constexpr context. |
86 | // |
87 | // CONSTRUCTION: |
88 | // |
89 | // Each of the civil-time types can be constructed in two ways: by directly |
90 | // passing to the constructor up to six (optional) integers representing the |
91 | // YMDHMS fields, or by copying the YMDHMS fields from a differently aligned |
92 | // civil-time type. |
93 | // |
94 | // civil_day default_value; // 1970-01-01 00:00:00 |
95 | // |
96 | // civil_day a(2015, 2, 3); // 2015-02-03 00:00:00 |
97 | // civil_day b(2015, 2, 3, 4, 5, 6); // 2015-02-03 00:00:00 |
98 | // civil_day c(2015); // 2015-01-01 00:00:00 |
99 | // |
100 | // civil_second ss(2015, 2, 3, 4, 5, 6); // 2015-02-03 04:05:06 |
101 | // civil_minute mm(ss); // 2015-02-03 04:05:00 |
102 | // civil_hour hh(mm); // 2015-02-03 04:00:00 |
103 | // civil_day d(hh); // 2015-02-03 00:00:00 |
104 | // civil_month m(d); // 2015-02-01 00:00:00 |
105 | // civil_year y(m); // 2015-01-01 00:00:00 |
106 | // |
107 | // m = civil_month(y); // 2015-01-01 00:00:00 |
108 | // d = civil_day(m); // 2015-01-01 00:00:00 |
109 | // hh = civil_hour(d); // 2015-01-01 00:00:00 |
110 | // mm = civil_minute(hh); // 2015-01-01 00:00:00 |
111 | // ss = civil_second(mm); // 2015-01-01 00:00:00 |
112 | // |
113 | // ALIGNMENT CONVERSION: |
114 | // |
115 | // The alignment of a civil-time object cannot change, but the object may be |
116 | // used to construct a new object with a different alignment. This is referred |
117 | // to as "realigning". When realigning to a type with the same or more |
118 | // precision (e.g., civil_day -> civil_second), the conversion may be |
119 | // performed implicitly since no information is lost. However, if information |
120 | // could be discarded (e.g., civil_second -> civil_day), the conversion must |
121 | // be explicit at the call site. |
122 | // |
123 | // void fun(const civil_day& day); |
124 | // |
125 | // civil_second cs; |
126 | // fun(cs); // Won't compile because data may be discarded |
127 | // fun(civil_day(cs)); // OK: explicit conversion |
128 | // |
129 | // civil_day cd; |
130 | // fun(cd); // OK: no conversion needed |
131 | // |
132 | // civil_month cm; |
133 | // fun(cm); // OK: implicit conversion to civil_day |
134 | // |
135 | // NORMALIZATION: |
136 | // |
137 | // Integer arguments passed to the constructor may be out-of-range, in which |
138 | // case they are normalized to produce a valid civil-time object. This enables |
139 | // natural arithmetic on constructor arguments without worrying about the |
140 | // field's range. Normalization guarantees that there are no invalid |
141 | // civil-time objects. |
142 | // |
143 | // civil_day d(2016, 10, 32); // Out-of-range day; normalized to 2016-11-01 |
144 | // |
145 | // Note: If normalization is undesired, you can signal an error by comparing |
146 | // the constructor arguments to the normalized values returned by the YMDHMS |
147 | // properties. |
148 | // |
149 | // PROPERTIES: |
150 | // |
151 | // All civil-time types have accessors for all six of the civil-time fields: |
152 | // year, month, day, hour, minute, and second. Recall that fields inferior to |
153 | // the type's aligment will be set to their minimum valid value. |
154 | // |
155 | // civil_day d(2015, 6, 28); |
156 | // // d.year() == 2015 |
157 | // // d.month() == 6 |
158 | // // d.day() == 28 |
159 | // // d.hour() == 0 |
160 | // // d.minute() == 0 |
161 | // // d.second() == 0 |
162 | // |
163 | // COMPARISON: |
164 | // |
165 | // Comparison always considers all six YMDHMS fields, regardless of the type's |
166 | // alignment. Comparison between differently aligned civil-time types is |
167 | // allowed. |
168 | // |
169 | // civil_day feb_3(2015, 2, 3); // 2015-02-03 00:00:00 |
170 | // civil_day mar_4(2015, 3, 4); // 2015-03-04 00:00:00 |
171 | // // feb_3 < mar_4 |
172 | // // civil_year(feb_3) == civil_year(mar_4) |
173 | // |
174 | // civil_second feb_3_noon(2015, 2, 3, 12, 0, 0); // 2015-02-03 12:00:00 |
175 | // // feb_3 < feb_3_noon |
176 | // // feb_3 == civil_day(feb_3_noon) |
177 | // |
178 | // // Iterates all the days of February 2015. |
179 | // for (civil_day d(2015, 2, 1); d < civil_month(2015, 3); ++d) { |
180 | // // ... |
181 | // } |
182 | // |
183 | // STREAMING: |
184 | // |
185 | // Each civil-time type may be sent to an output stream using operator<<(). |
186 | // The output format follows the pattern "YYYY-MM-DDThh:mm:ss" where fields |
187 | // inferior to the type's alignment are omitted. |
188 | // |
189 | // civil_second cs(2015, 2, 3, 4, 5, 6); |
190 | // std::cout << cs << "\n"; // Outputs: 2015-02-03T04:05:06 |
191 | // |
192 | // civil_day cd(cs); |
193 | // std::cout << cd << "\n"; // Outputs: 2015-02-03 |
194 | // |
195 | // civil_year cy(cs); |
196 | // std::cout << cy << "\n"; // Outputs: 2015 |
197 | // |
198 | // ARITHMETIC: |
199 | // |
200 | // Civil-time types support natural arithmetic operators such as addition, |
201 | // subtraction, and difference. Arithmetic operates on the civil-time field |
202 | // indicated in the type's name. Difference requires arguments with the same |
203 | // alignment and returns the answer in units of the alignment. |
204 | // |
205 | // civil_day a(2015, 2, 3); |
206 | // ++a; // 2015-02-04 00:00:00 |
207 | // --a; // 2015-02-03 00:00:00 |
208 | // civil_day b = a + 1; // 2015-02-04 00:00:00 |
209 | // civil_day c = 1 + b; // 2015-02-05 00:00:00 |
210 | // int n = c - a; // n = 2 (civil days) |
211 | // int m = c - civil_month(c); // Won't compile: different types. |
212 | // |
213 | // EXAMPLE: Adding a month to January 31. |
214 | // |
215 | // One of the classic questions that arises when considering a civil-time |
216 | // library (or a date library or a date/time library) is this: "What happens |
217 | // when you add a month to January 31?" This is an interesting question |
218 | // because there could be a number of possible answers: |
219 | // |
220 | // 1. March 3 (or 2 if a leap year). This may make sense if the operation |
221 | // wants the equivalent of February 31. |
222 | // 2. February 28 (or 29 if a leap year). This may make sense if the operation |
223 | // wants the last day of January to go to the last day of February. |
224 | // 3. Error. The caller may get some error, an exception, an invalid date |
225 | // object, or maybe false is returned. This may make sense because there is |
226 | // no single unambiguously correct answer to the question. |
227 | // |
228 | // Practically speaking, any answer that is not what the programmer intended |
229 | // is the wrong answer. |
230 | // |
231 | // This civil-time library avoids the problem by making it impossible to ask |
232 | // ambiguous questions. All civil-time objects are aligned to a particular |
233 | // civil-field boundary (such as aligned to a year, month, day, hour, minute, |
234 | // or second), and arithmetic operates on the field to which the object is |
235 | // aligned. This means that in order to "add a month" the object must first be |
236 | // aligned to a month boundary, which is equivalent to the first day of that |
237 | // month. |
238 | // |
239 | // Of course, there are ways to compute an answer the question at hand using |
240 | // this civil-time library, but they require the programmer to be explicit |
241 | // about the answer they expect. To illustrate, let's see how to compute all |
242 | // three of the above possible answers to the question of "Jan 31 plus 1 |
243 | // month": |
244 | // |
245 | // const civil_day d(2015, 1, 31); |
246 | // |
247 | // // Answer 1: |
248 | // // Add 1 to the month field in the constructor, and rely on normalization. |
249 | // const auto ans_normalized = civil_day(d.year(), d.month() + 1, d.day()); |
250 | // // ans_normalized == 2015-03-03 (aka Feb 31) |
251 | // |
252 | // // Answer 2: |
253 | // // Add 1 to month field, capping to the end of next month. |
254 | // const auto next_month = civil_month(d) + 1; |
255 | // const auto last_day_of_next_month = civil_day(next_month + 1) - 1; |
256 | // const auto ans_capped = std::min(ans_normalized, last_day_of_next_month); |
257 | // // ans_capped == 2015-02-28 |
258 | // |
259 | // // Answer 3: |
260 | // // Signal an error if the normalized answer is not in next month. |
261 | // if (civil_month(ans_normalized) != next_month) { |
262 | // // error, month overflow |
263 | // } |
264 | // |
265 | using civil_year = detail::civil_year; |
266 | using civil_month = detail::civil_month; |
267 | using civil_day = detail::civil_day; |
268 | using civil_hour = detail::civil_hour; |
269 | using civil_minute = detail::civil_minute; |
270 | using civil_second = detail::civil_second; |
271 | |
272 | // An enum class with members monday, tuesday, wednesday, thursday, friday, |
273 | // saturday, and sunday. These enum values may be sent to an output stream |
274 | // using operator<<(). The result is the full weekday name in English with a |
275 | // leading capital letter. |
276 | // |
277 | // weekday wd = weekday::thursday; |
278 | // std::cout << wd << "\n"; // Outputs: Thursday |
279 | // |
280 | using detail::weekday; |
281 | |
282 | // Returns the weekday for the given civil-time value. |
283 | // |
284 | // civil_day a(2015, 8, 13); |
285 | // weekday wd = get_weekday(a); // wd == weekday::thursday |
286 | // |
287 | using detail::get_weekday; |
288 | |
289 | // Returns the civil_day that strictly follows or precedes the given |
290 | // civil_day, and that falls on the given weekday. |
291 | // |
292 | // For example, given: |
293 | // |
294 | // August 2015 |
295 | // Su Mo Tu We Th Fr Sa |
296 | // 1 |
297 | // 2 3 4 5 6 7 8 |
298 | // 9 10 11 12 13 14 15 |
299 | // 16 17 18 19 20 21 22 |
300 | // 23 24 25 26 27 28 29 |
301 | // 30 31 |
302 | // |
303 | // civil_day a(2015, 8, 13); // get_weekday(a) == weekday::thursday |
304 | // civil_day b = next_weekday(a, weekday::thursday); // b = 2015-08-20 |
305 | // civil_day c = prev_weekday(a, weekday::thursday); // c = 2015-08-06 |
306 | // |
307 | // civil_day d = ... |
308 | // // Gets the following Thursday if d is not already Thursday |
309 | // civil_day thurs1 = next_weekday(d - 1, weekday::thursday); |
310 | // // Gets the previous Thursday if d is not already Thursday |
311 | // civil_day thurs2 = prev_weekday(d + 1, weekday::thursday); |
312 | // |
313 | using detail::next_weekday; |
314 | using detail::prev_weekday; |
315 | |
316 | // Returns the day-of-year for the given civil-time value. |
317 | // |
318 | // civil_day a(2015, 1, 1); |
319 | // int yd_jan_1 = get_yearday(a); // yd_jan_1 = 1 |
320 | // civil_day b(2015, 12, 31); |
321 | // int yd_dec_31 = get_yearday(b); // yd_dec_31 = 365 |
322 | // |
323 | using detail::get_yearday; |
324 | |
325 | } // namespace cctz |
326 | } // namespace time_internal |
327 | } // namespace absl |
328 | |
329 | #endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_ |
330 | |