internal/cctz/include/cctz/civil_time.h
Go to the documentation of this file.
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 
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 //
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_day.
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 = prev_weekday(d, weekday::thursday) + 7;
310 // // Gets the previous Thursday if d is not already Thursday
311 // civil_day thurs2 = next_weekday(d, weekday::thursday) - 7;
312 //
315 
316 // Returns the day-of-year for the given civil_day.
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_
CONSTEXPR_F int get_yearday(const civil_day &cd) noexcept
civil_time< second_tag > civil_second
CONSTEXPR_F civil_day next_weekday(civil_day cd, weekday wd) noexcept
CONSTEXPR_F weekday get_weekday(const civil_day &cd) noexcept
Definition: algorithm.h:29
CONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept
civil_time< month_tag > civil_month
civil_time< minute_tag > civil_minute


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:17