Coverage Report

Created: 2025-11-16 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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