/src/poco/Foundation/include/Poco/DateTime.h
Line | Count | Source |
1 | | // |
2 | | // DateTime.h |
3 | | // |
4 | | // Library: Foundation |
5 | | // Package: DateTime |
6 | | // Module: DateTime |
7 | | // |
8 | | // Definition of the DateTime class. |
9 | | // |
10 | | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
11 | | // and Contributors. |
12 | | // |
13 | | // SPDX-License-Identifier: BSL-1.0 |
14 | | // |
15 | | |
16 | | |
17 | | #ifndef Foundation_DateTime_INCLUDED |
18 | | #define Foundation_DateTime_INCLUDED |
19 | | |
20 | | |
21 | | #include "Poco/Foundation.h" |
22 | | #include "Poco/Timestamp.h" |
23 | | #include "Poco/Timespan.h" |
24 | | |
25 | | |
26 | | struct tm; |
27 | | |
28 | | |
29 | | namespace Poco { |
30 | | |
31 | | |
32 | | class Foundation_API DateTime |
33 | | /// This class represents an instant in time, expressed |
34 | | /// in years, months, days, hours, minutes, seconds |
35 | | /// and milliseconds based on the Gregorian calendar. |
36 | | /// The class is mainly useful for conversions between |
37 | | /// UTC, Julian day and Gregorian calendar dates. |
38 | | /// |
39 | | /// The date and time stored in a DateTime is always in UTC |
40 | | /// (Coordinated Universal Time) and thus independent of the |
41 | | /// timezone in effect on the system. |
42 | | /// |
43 | | /// Conversion calculations are based on algorithms |
44 | | /// collected and described by Peter Baum at |
45 | | /// http://vsg.cape.com/~pbaum/date/date0.htm |
46 | | /// |
47 | | /// Internally, this class stores a date/time in two |
48 | | /// forms (UTC and broken down) for performance reasons. Only use |
49 | | /// this class for conversions between date/time representations. |
50 | | /// Use the Timestamp class for everything else. |
51 | | /// |
52 | | /// Notes: |
53 | | /// * Zero is a valid year (in accordance with ISO 8601 and astronomical year numbering) |
54 | | /// * Year zero (0) is a leap year |
55 | | /// * Minimum date/time that can be represented is 12:00:00 UTC Monday, 1 January 4713 BC |
56 | | /// (Julian Day 0, Gregorian -4713-11-24 12:00:00) |
57 | | /// |
58 | | /// For more information, please see: |
59 | | /// * http://en.wikipedia.org/wiki/Gregorian_Calendar |
60 | | /// * http://en.wikipedia.org/wiki/Julian_day |
61 | | /// * http://en.wikipedia.org/wiki/UTC |
62 | | /// * http://en.wikipedia.org/wiki/ISO_8601 |
63 | | { |
64 | | public: |
65 | | enum Months |
66 | | /// Symbolic names for month numbers (1 to 12). |
67 | | { |
68 | | JANUARY = 1, |
69 | | FEBRUARY, |
70 | | MARCH, |
71 | | APRIL, |
72 | | MAY, |
73 | | JUNE, |
74 | | JULY, |
75 | | AUGUST, |
76 | | SEPTEMBER, |
77 | | OCTOBER, |
78 | | NOVEMBER, |
79 | | DECEMBER |
80 | | }; |
81 | | |
82 | | enum DaysOfWeek |
83 | | /// Symbolic names for week day numbers (0 to 6). |
84 | | { |
85 | | SUNDAY = 0, |
86 | | MONDAY, |
87 | | TUESDAY, |
88 | | WEDNESDAY, |
89 | | THURSDAY, |
90 | | FRIDAY, |
91 | | SATURDAY |
92 | | }; |
93 | | |
94 | | DateTime(); |
95 | | /// Creates a DateTime for the current date and time. |
96 | | |
97 | | DateTime(const tm& tmStruct); |
98 | | /// Creates a DateTime from tm struct. |
99 | | |
100 | | DateTime(const Timestamp& timestamp); |
101 | | /// Creates a DateTime for the date and time given in |
102 | | /// a Timestamp. |
103 | | |
104 | | DateTime(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microsecond = 0); |
105 | | /// Creates a DateTime for the given Gregorian date and time. |
106 | | /// * year is from 0 to 9999. |
107 | | /// * month is from 1 to 12. |
108 | | /// * day is from 1 to 31. |
109 | | /// * hour is from 0 to 23. |
110 | | /// * minute is from 0 to 59. |
111 | | /// * second is from 0 to 60. |
112 | | /// * millisecond is from 0 to 999. |
113 | | /// * microsecond is from 0 to 999. |
114 | | /// |
115 | | /// Throws an InvalidArgumentException if an argument date is out of range. |
116 | | |
117 | | DateTime(double julianDay); |
118 | | /// Creates a DateTime for the given Julian day. |
119 | | |
120 | | DateTime(Timestamp::UtcTimeVal utcTime, Timestamp::TimeDiff diff); |
121 | | /// Creates a DateTime from an UtcTimeVal and a TimeDiff. |
122 | | /// |
123 | | /// Mainly used internally by DateTime and friends. |
124 | | |
125 | | DateTime(const DateTime& dateTime); |
126 | | /// Copy constructor. Creates the DateTime from another one. |
127 | | |
128 | | ~DateTime(); |
129 | | /// Destroys the DateTime. |
130 | | |
131 | | DateTime& operator = (const DateTime& dateTime); |
132 | | /// Assigns another DateTime. |
133 | | |
134 | | DateTime& operator = (const Timestamp& timestamp); |
135 | | /// Assigns a Timestamp. |
136 | | |
137 | | DateTime& operator = (double julianDay); |
138 | | /// Assigns a Julian day. |
139 | | |
140 | | DateTime& assign(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microseconds = 0); |
141 | | /// Assigns a Gregorian date and time. |
142 | | /// * year is from 0 to 9999. |
143 | | /// * month is from 1 to 12. |
144 | | /// * day is from 1 to 31. |
145 | | /// * hour is from 0 to 23. |
146 | | /// * minute is from 0 to 59. |
147 | | /// * second is from 0 to 60. |
148 | | /// * millisecond is from 0 to 999. |
149 | | /// * microsecond is from 0 to 999. |
150 | | /// |
151 | | /// Throws an InvalidArgumentException if an argument date is out of range. |
152 | | |
153 | | void swap(DateTime& dateTime) noexcept; |
154 | | /// Swaps the DateTime with another one. |
155 | | |
156 | | int year() const; |
157 | | /// Returns the year. |
158 | | |
159 | | int month() const; |
160 | | /// Returns the month (1 to 12). |
161 | | |
162 | | int week(int firstDayOfWeek = MONDAY) const; |
163 | | /// Returns the week number within the year. |
164 | | /// FirstDayOfWeek should be either SUNDAY (0) or MONDAY (1). |
165 | | /// The returned week number will be from 0 to 53. Week number 1 is the week |
166 | | /// containing January 4. This is in accordance to ISO 8601. |
167 | | /// |
168 | | /// The following example assumes that firstDayOfWeek is MONDAY. For 2005, which started |
169 | | /// on a Saturday, week 1 will be the week starting on Monday, January 3. |
170 | | /// January 1 and 2 will fall within week 0 (or the last week of the previous year). |
171 | | /// |
172 | | /// For 2007, which starts on a Monday, week 1 will be the week starting on Monday, January 1. |
173 | | /// There will be no week 0 in 2007. |
174 | | |
175 | | int day() const; |
176 | | /// Returns the day within the month (1 to 31). |
177 | | |
178 | | int dayOfWeek() const; |
179 | | /// Returns the weekday (0 to 6, where |
180 | | /// 0 = Sunday, 1 = Monday, ..., 6 = Saturday). |
181 | | |
182 | | int dayOfYear() const; |
183 | | /// Returns the number of the day in the year. |
184 | | /// January 1 is 1, February 1 is 32, etc. |
185 | | |
186 | | int hour() const; |
187 | | /// Returns the hour (0 to 23). |
188 | | |
189 | | int hourAMPM() const; |
190 | | /// Returns the hour (0 to 12). |
191 | | |
192 | | bool isAM() const; |
193 | | /// Returns true if hour < 12; |
194 | | |
195 | | bool isPM() const; |
196 | | /// Returns true if hour >= 12. |
197 | | |
198 | | int minute() const; |
199 | | /// Returns the minute (0 to 59). |
200 | | |
201 | | int second() const; |
202 | | /// Returns the second (0 to 59). |
203 | | |
204 | | int millisecond() const; |
205 | | /// Returns the millisecond (0 to 999) |
206 | | |
207 | | int microsecond() const; |
208 | | /// Returns the microsecond (0 to 999) |
209 | | |
210 | | double julianDay() const; |
211 | | /// Returns the julian day for the date and time. |
212 | | |
213 | | Timestamp timestamp() const; |
214 | | /// Returns the date and time expressed as a Timestamp. |
215 | | |
216 | | Timestamp::UtcTimeVal utcTime() const; |
217 | | /// Returns the date and time expressed in UTC-based |
218 | | /// time. UTC base time is midnight, October 15, 1582. |
219 | | /// Resolution is 100 nanoseconds. |
220 | | |
221 | | bool operator == (const DateTime& dateTime) const; |
222 | | bool operator != (const DateTime& dateTime) const; |
223 | | bool operator < (const DateTime& dateTime) const; |
224 | | bool operator <= (const DateTime& dateTime) const; |
225 | | bool operator > (const DateTime& dateTime) const; |
226 | | bool operator >= (const DateTime& dateTime) const; |
227 | | |
228 | | DateTime operator + (const Timespan& span) const; |
229 | | DateTime operator - (const Timespan& span) const; |
230 | | Timespan operator - (const DateTime& dateTime) const; |
231 | | DateTime& operator += (const Timespan& span); |
232 | | DateTime& operator -= (const Timespan& span); |
233 | | |
234 | | tm makeTM() const; |
235 | | /// Converts DateTime to tm struct. |
236 | | |
237 | | void makeUTC(int tzd); |
238 | | /// Converts a local time into UTC, by applying the given time zone differential. |
239 | | |
240 | | void makeLocal(int tzd); |
241 | | /// Converts a UTC time into a local time, by applying the given time zone differential. |
242 | | |
243 | | static bool isLeapYear(int year); |
244 | | /// Returns true if the given year is a leap year; |
245 | | /// false otherwise. |
246 | | |
247 | | static int daysOfMonth(int year, int month); |
248 | | /// Returns the number of days in the given month |
249 | | /// and year. Month is from 1 to 12. |
250 | | |
251 | | static bool isValid(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microsecond = 0); |
252 | | /// Checks if the given date and time is valid |
253 | | /// (all arguments are within a proper range). |
254 | | /// |
255 | | /// Returns true if all arguments are valid, false otherwise. |
256 | | |
257 | | protected: |
258 | | void checkValid(); |
259 | | /// Checks if the given date and time is valid (all arguments are within a proper range). |
260 | | /// Expects all members to be set. |
261 | | /// |
262 | | /// Throws Poco::InvalidArgumentException if any of the arguments is not valid. |
263 | | |
264 | | static double toJulianDay(Timestamp::UtcTimeVal utcTime); |
265 | | /// Computes the Julian day for an UTC time. |
266 | | |
267 | | static double toJulianDay(int year, int month, int day, int hour = 0, int minute = 0, int second = 0, int millisecond = 0, int microsecond = 0); |
268 | | /// Computes the Julian day for a Gregorian calendar date and time. |
269 | | /// See <http://vsg.cape.com/~pbaum/date/jdimp.htm>, section 2.3.1 for the algorithm. |
270 | | |
271 | | static Timestamp::UtcTimeVal toUtcTime(double julianDay); |
272 | | /// Computes the UTC time for a Julian day. |
273 | | |
274 | | void computeGregorian(double julianDay); |
275 | | /// Computes the Gregorian date for the given Julian day. |
276 | | /// See <http://vsg.cape.com/~pbaum/date/injdimp.htm>, section 3.3.1 for the algorithm. |
277 | | |
278 | | void computeDaytime(); |
279 | | /// Extracts the daytime (hours, minutes, seconds, etc.) from the stored utcTime. |
280 | | |
281 | | private: |
282 | | void checkLimit(short& lower, short& higher, short limit); |
283 | | void normalize(); |
284 | | ///utility functions used to correct the overflow in computeGregorian |
285 | | |
286 | | Timestamp::UtcTimeVal _utcTime; |
287 | | short _year; |
288 | | short _month; |
289 | | short _day; |
290 | | short _hour; |
291 | | short _minute; |
292 | | short _second; |
293 | | short _millisecond; |
294 | | short _microsecond; |
295 | | }; |
296 | | |
297 | | |
298 | | // |
299 | | // inlines |
300 | | // |
301 | | |
302 | | |
303 | | inline double DateTime::toJulianDay(Timestamp::UtcTimeVal utcTime) |
304 | 54.6k | { |
305 | 54.6k | double utcDays = double(utcTime)/864000000000.0; |
306 | 54.6k | return utcDays + 2299160.5; // first day of Gregorian reform (Oct 15 1582) |
307 | 54.6k | } |
308 | | |
309 | | |
310 | | inline Timestamp::UtcTimeVal DateTime::toUtcTime(double julianDay) |
311 | 1.75k | { |
312 | 1.75k | return Timestamp::UtcTimeVal((julianDay - 2299160.5)*864000000000.0); |
313 | 1.75k | } |
314 | | |
315 | | |
316 | | inline Timestamp DateTime::timestamp() const |
317 | 20.2k | { |
318 | 20.2k | return Timestamp::fromUtcTime(_utcTime); |
319 | 20.2k | } |
320 | | |
321 | | |
322 | | inline Timestamp::UtcTimeVal DateTime::utcTime() const |
323 | 0 | { |
324 | 0 | return _utcTime; |
325 | 0 | } |
326 | | |
327 | | |
328 | | inline int DateTime::year() const |
329 | 26.3k | { |
330 | 26.3k | return _year; |
331 | 26.3k | } |
332 | | |
333 | | |
334 | | inline int DateTime::month() const |
335 | 26.3k | { |
336 | 26.3k | return _month; |
337 | 26.3k | } |
338 | | |
339 | | |
340 | | inline int DateTime::day() const |
341 | 26.3k | { |
342 | 26.3k | return _day; |
343 | 26.3k | } |
344 | | |
345 | | |
346 | | inline int DateTime::hour() const |
347 | 26.3k | { |
348 | 26.3k | return _hour; |
349 | 26.3k | } |
350 | | |
351 | | |
352 | | inline int DateTime::hourAMPM() const |
353 | 1.84k | { |
354 | 1.84k | if (_hour < 1) |
355 | 195 | return 12; |
356 | 1.64k | else if (_hour > 12) |
357 | 121 | return _hour - 12; |
358 | 1.52k | else |
359 | 1.52k | return _hour; |
360 | 1.84k | } |
361 | | |
362 | | |
363 | | inline bool DateTime::isAM() const |
364 | 1.84k | { |
365 | 1.84k | return _hour < 12; |
366 | 1.84k | } |
367 | | |
368 | | |
369 | | inline bool DateTime::isPM() const |
370 | 0 | { |
371 | 0 | return _hour >= 12; |
372 | 0 | } |
373 | | |
374 | | |
375 | | inline int DateTime::minute() const |
376 | 28.2k | { |
377 | 28.2k | return _minute; |
378 | 28.2k | } |
379 | | |
380 | | |
381 | | inline int DateTime::second() const |
382 | 24.5k | { |
383 | 24.5k | return _second; |
384 | 24.5k | } |
385 | | |
386 | | |
387 | | inline int DateTime::millisecond() const |
388 | 3.68k | { |
389 | 3.68k | return _millisecond; |
390 | 3.68k | } |
391 | | |
392 | | |
393 | | inline int DateTime::microsecond() const |
394 | 3.68k | { |
395 | 3.68k | return _microsecond; |
396 | 3.68k | } |
397 | | |
398 | | |
399 | | inline bool DateTime::operator == (const DateTime& dateTime) const |
400 | 0 | { |
401 | 0 | return _utcTime == dateTime._utcTime; |
402 | 0 | } |
403 | | |
404 | | |
405 | | inline bool DateTime::operator != (const DateTime& dateTime) const |
406 | 0 | { |
407 | 0 | return _utcTime != dateTime._utcTime; |
408 | 0 | } |
409 | | |
410 | | |
411 | | inline bool DateTime::operator < (const DateTime& dateTime) const |
412 | 0 | { |
413 | 0 | return _utcTime < dateTime._utcTime; |
414 | 0 | } |
415 | | |
416 | | |
417 | | inline bool DateTime::operator <= (const DateTime& dateTime) const |
418 | 0 | { |
419 | 0 | return _utcTime <= dateTime._utcTime; |
420 | 0 | } |
421 | | |
422 | | |
423 | | inline bool DateTime::operator > (const DateTime& dateTime) const |
424 | 0 | { |
425 | 0 | return _utcTime > dateTime._utcTime; |
426 | 0 | } |
427 | | |
428 | | |
429 | | inline bool DateTime::operator >= (const DateTime& dateTime) const |
430 | 0 | { |
431 | 0 | return _utcTime >= dateTime._utcTime; |
432 | 0 | } |
433 | | |
434 | | |
435 | | inline bool DateTime::isLeapYear(int year) |
436 | 1.93k | { |
437 | 1.93k | return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0); |
438 | 1.93k | } |
439 | | |
440 | | |
441 | | inline void swap(DateTime& d1, DateTime& d2) noexcept |
442 | 0 | { |
443 | 0 | d1.swap(d2); |
444 | 0 | } |
445 | | |
446 | | |
447 | | } // namespace Poco |
448 | | |
449 | | |
450 | | #endif // Foundation_DateTime_INCLUDED |