Coverage Report

Created: 2026-09-20 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wxwidgets/include/wx/datetime.h
Line
Count
Source
1
/////////////////////////////////////////////////////////////////////////////
2
// Name:        wx/datetime.h
3
// Purpose:     declarations of time/date related classes (wxDateTime,
4
//              wxTimeSpan)
5
// Author:      Vadim Zeitlin
6
// Created:     10.02.99
7
// Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8
// Licence:     wxWindows licence
9
/////////////////////////////////////////////////////////////////////////////
10
11
#ifndef _WX_DATETIME_H
12
#define _WX_DATETIME_H
13
14
#include "wx/defs.h"
15
16
#if wxUSE_DATETIME
17
18
#include <time.h>
19
20
#include <vector>
21
22
#include "wx/longlong.h"
23
#include "wx/anystr.h"
24
25
class WXDLLIMPEXP_FWD_BASE wxDateTime;
26
class WXDLLIMPEXP_FWD_BASE wxTimeSpan;
27
class WXDLLIMPEXP_FWD_BASE wxDateSpan;
28
#ifdef __WINDOWS__
29
struct _SYSTEMTIME;
30
#endif
31
32
#include "wx/dynarray.h"
33
34
// not all c-runtimes are based on 1/1/1970 being (time_t) 0
35
// set this to the corresponding value in seconds 1/1/1970 has on your
36
// systems c-runtime
37
38
41.0k
#define WX_TIME_BASE_OFFSET 0
39
40
/*
41
 * TODO
42
 *
43
 * + 1. Time zones with minutes (make TimeZone a class)
44
 * ? 2. getdate() function like under Solaris
45
 * + 3. text conversion for wxDateSpan
46
 * + 4. pluggable modules for the workdays calculations
47
 *   5. wxDateTimeHolidayAuthority Christian feasts outside of US
48
 */
49
50
/*
51
  The three (main) classes declared in this header represent:
52
53
  1. An absolute moment in the time (wxDateTime)
54
  2. A difference between two moments in the time, positive or negative
55
     (wxTimeSpan)
56
  3. A logical difference between two dates expressed in
57
     years/months/weeks/days (wxDateSpan)
58
59
  The following arithmetic operations are permitted (all others are not):
60
61
  addition
62
  --------
63
64
  wxDateTime + wxTimeSpan = wxDateTime
65
  wxDateTime + wxDateSpan = wxDateTime
66
  wxTimeSpan + wxTimeSpan = wxTimeSpan
67
  wxDateSpan + wxDateSpan = wxDateSpan
68
69
  subtraction
70
  ------------
71
  wxDateTime - wxDateTime = wxTimeSpan
72
  wxDateTime - wxTimeSpan = wxDateTime
73
  wxDateTime - wxDateSpan = wxDateTime
74
  wxTimeSpan - wxTimeSpan = wxTimeSpan
75
  wxDateSpan - wxDateSpan = wxDateSpan
76
77
  multiplication
78
  --------------
79
  wxTimeSpan * number = wxTimeSpan
80
  number * wxTimeSpan = wxTimeSpan
81
  wxDateSpan * number = wxDateSpan
82
  number * wxDateSpan = wxDateSpan
83
84
  unitary minus
85
  -------------
86
  -wxTimeSpan = wxTimeSpan
87
  -wxDateSpan = wxDateSpan
88
89
  For each binary operation OP (+, -, *) we have the following operatorOP=() as
90
  a method and the method with a symbolic name OPER (Add, Subtract, Multiply)
91
  as a synonym for it and another const method with the same name which returns
92
  the changed copy of the object and operatorOP() as a global function which is
93
  implemented in terms of the const version of OPEN. For the unary - we have
94
  operator-() as a method, Neg() as synonym for it and Negate() which returns
95
  the copy of the object with the changed sign.
96
*/
97
98
// an invalid/default date time object which may be used as the default
99
// argument for arguments of type wxDateTime; it is also returned by all
100
// functions returning wxDateTime on failure (this is why it is also called
101
// wxInvalidDateTime)
102
class WXDLLIMPEXP_FWD_BASE wxDateTime;
103
104
extern WXDLLIMPEXP_DATA_BASE(const char) wxDefaultDateTimeFormat[];
105
extern WXDLLIMPEXP_DATA_BASE(const char) wxDefaultTimeSpanFormat[];
106
extern WXDLLIMPEXP_DATA_BASE(const wxDateTime) wxDefaultDateTime;
107
108
0
#define wxInvalidDateTime wxDefaultDateTime
109
110
111
// ----------------------------------------------------------------------------
112
// conditional compilation
113
// ----------------------------------------------------------------------------
114
115
// if configure detected strftime(), we have it too
116
#ifdef HAVE_STRFTIME
117
    #define wxHAS_STRFTIME
118
// suppose everyone else has strftime
119
#else
120
    #define wxHAS_STRFTIME
121
#endif
122
123
// ----------------------------------------------------------------------------
124
// wxDateTime represents an absolute moment in the time
125
// ----------------------------------------------------------------------------
126
127
class WXDLLIMPEXP_BASE wxWARN_UNUSED wxDateTime
128
{
129
public:
130
    // types
131
    // ------------------------------------------------------------------------
132
133
        // a small unsigned integer type for storing things like minutes,
134
        // seconds &c. It should be at least short (i.e. not char) to contain
135
        // the number of milliseconds - it may also be 'int' because there is
136
        // no size penalty associated with it in our code, we don't store any
137
        // data in this format
138
    typedef unsigned short wxDateTime_t;
139
140
    // constants
141
    // ------------------------------------------------------------------------
142
143
        // the timezones
144
    enum TZ
145
    {
146
        // the time in the current time zone
147
        Local,
148
149
        // zones from GMT (= Greenwich Mean Time): they're guaranteed to be
150
        // consequent numbers, so writing something like `GMT0 + offset` is
151
        // safe if abs(offset) <= 12
152
153
        // underscore stands for minus
154
        GMT_12, GMT_11, GMT_10, GMT_9, GMT_8, GMT_7,
155
        GMT_6, GMT_5, GMT_4, GMT_3, GMT_2, GMT_1,
156
        GMT0,
157
        GMT1, GMT2, GMT3, GMT4, GMT5, GMT6,
158
        GMT7, GMT8, GMT9, GMT10, GMT11, GMT12, GMT13,
159
        // Note that GMT12 and GMT_12 are not the same: there is a difference
160
        // of exactly one day between them
161
162
        // some symbolic names for TZ
163
164
        // Europe
165
        WET = GMT0,                         // Western Europe Time
166
        WEST = GMT1,                        // Western Europe Summer Time
167
        CET = GMT1,                         // Central Europe Time
168
        CEST = GMT2,                        // Central Europe Summer Time
169
        EET = GMT2,                         // Eastern Europe Time
170
        EEST = GMT3,                        // Eastern Europe Summer Time
171
        MSK = GMT3,                         // Moscow Time
172
        MSD = GMT4,                         // Moscow Summer Time
173
174
        // US and Canada
175
        AST = GMT_4,                        // Atlantic Standard Time
176
        ADT = GMT_3,                        // Atlantic Daylight Time
177
        EST = GMT_5,                        // Eastern Standard Time
178
        EDT = GMT_4,                        // Eastern Daylight Saving Time
179
        CST = GMT_6,                        // Central Standard Time
180
        CDT = GMT_5,                        // Central Daylight Saving Time
181
        MST = GMT_7,                        // Mountain Standard Time
182
        MDT = GMT_6,                        // Mountain Daylight Saving Time
183
        PST = GMT_8,                        // Pacific Standard Time
184
        PDT = GMT_7,                        // Pacific Daylight Saving Time
185
        HST = GMT_10,                       // Hawaiian Standard Time
186
        AKST = GMT_9,                       // Alaska Standard Time
187
        AKDT = GMT_8,                       // Alaska Daylight Saving Time
188
189
        // Australia
190
191
        A_WST = GMT8,                       // Western Standard Time
192
        A_CST = GMT13 + 1,                  // Central Standard Time (+9.5)
193
        A_EST = GMT10,                      // Eastern Standard Time
194
        A_ESST = GMT11,                     // Eastern Summer Time
195
196
        // New Zealand
197
        NZST = GMT12,                       // Standard Time
198
        NZDT = GMT13,                       // Daylight Saving Time
199
200
        // TODO add more symbolic timezone names here
201
202
        // Universal Coordinated Time = the new and politically correct name
203
        // for GMT
204
        UTC = GMT0
205
    };
206
207
        // the calendar systems we know about: notice that it's valid (for
208
        // this classes purpose anyhow) to work with any of these calendars
209
        // even with the dates before the historical appearance of the
210
        // calendar
211
    enum Calendar
212
    {
213
        Gregorian,  // current calendar
214
        Julian      // calendar in use since -45 until the 1582 (or later)
215
216
        // TODO Hebrew, Chinese, Maya, ... (just kidding) (or then may be not?)
217
    };
218
219
        // the country parameter is used so far for calculating the start and
220
        // the end of DST period and for deciding whether the date is a work
221
        // day or not
222
        //
223
        // TODO move this to intl.h
224
225
    enum Country
226
    {
227
        Country_Unknown, // no special information for this country
228
        Country_Default, // set the default country with SetCountry() method
229
                         // or use the default country with any other
230
231
        // TODO add more countries (for this we must know about DST and/or
232
        //      holidays for this country)
233
234
        // Western European countries: we assume that they all follow the same
235
        // DST rules (true or false?)
236
        Country_WesternEurope_Start,
237
        Country_EEC = Country_WesternEurope_Start,
238
        France,
239
        Germany,
240
        UK,
241
        Country_WesternEurope_End = UK,
242
243
        Russia,
244
        USA
245
    };
246
        // symbolic names for the months
247
    enum Month
248
    {
249
        Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec, Inv_Month
250
    };
251
252
        // symbolic names for the weekdays
253
    enum WeekDay
254
    {
255
        Sun, Mon, Tue, Wed, Thu, Fri, Sat, Inv_WeekDay
256
    };
257
258
        // invalid value for the year
259
    enum Year
260
    {
261
        Inv_Year = SHRT_MIN    // should hold in wxDateTime_t
262
    };
263
264
        // flags for GetWeekDayName and GetMonthName
265
    enum NameFlags
266
    {
267
        Name_Full = 0x01,        // return full name
268
        Name_Abbr = 0x02,        // return abbreviated name
269
        Name_Shortest = 0x03     // return shortest name
270
    };
271
272
    // context for GetWeekDayName and GetMonthName
273
    enum NameContext
274
    {
275
        Context_Formatting,      // return name for date formatting context
276
        Context_Standalone       // return name for standalone context
277
    };
278
279
    // flags for GetWeekOfYear and GetWeekOfMonth
280
    enum WeekFlags
281
    {
282
        Default_First,   // Sunday_First for US, Monday_First for the rest
283
        Monday_First,    // week starts with a Monday
284
        Sunday_First     // week starts with a Sunday
285
    };
286
287
    // Currently we assume that DST is always shifted by 1 hour, this seems to
288
    // be always true in practice. If this ever needs to change, search for all
289
    // places using DST_OFFSET and update them.
290
    enum
291
    {
292
        DST_OFFSET = 3600
293
    };
294
295
296
    // helper classes
297
    // ------------------------------------------------------------------------
298
299
        // Describes the form of the month or week-day name.
300
    class NameForm
301
    {
302
    public:
303
        // Ctor is non-explicit for compatibility.
304
0
        NameForm(NameFlags flags = Name_Full) : m_flags(flags) {}
305
306
        // Chainable methods allowing to set various fields.
307
0
        NameForm& Full() { m_flags = Name_Full; return *this; }
308
0
        NameForm& Abbr() { m_flags = Name_Abbr; return *this; }
309
0
        NameForm& Shortest() { m_flags = Name_Shortest; return *this; }
310
0
        NameForm& Formatting() { m_context = Context_Formatting; return *this; }
311
0
        NameForm& Standalone() { m_context = Context_Standalone; return *this; }
312
313
0
        NameFlags GetFlags() const { return m_flags; }
314
0
        NameContext GetContext() const { return m_context; }
315
316
    private:
317
        NameFlags m_flags;
318
        NameContext m_context = Context_Formatting;
319
    };
320
321
        // a class representing a time zone: basically, this is just an offset
322
        // (in seconds) from GMT
323
    class WXDLLIMPEXP_BASE TimeZone
324
    {
325
    public:
326
        TimeZone(TZ tz);
327
328
        // create time zone object with the given offset
329
0
        TimeZone(long offset = 0) { m_offset = offset; }
330
331
        static TimeZone Make(long offset)
332
0
        {
333
0
            TimeZone tz;
334
0
            tz.m_offset = offset;
335
0
            return tz;
336
0
        }
337
338
0
        bool IsLocal() const { return m_offset == -1; }
339
340
        long GetOffset() const;
341
342
    private:
343
        // offset for this timezone from GMT in seconds
344
        long m_offset;
345
    };
346
347
        // standard struct tm is limited to the years from 1900 (because
348
        // tm_year field is the offset from 1900), so we use our own struct
349
        // instead to represent broken down time
350
        //
351
        // NB: this struct should always be kept normalized (i.e. mon should
352
        //     be < 12, 1 <= day <= 31 &c), so use AddMonths(), AddDays()
353
        //     instead of modifying the member fields directly!
354
    struct WXDLLIMPEXP_BASE Tm
355
    {
356
        wxDateTime_t msec, sec, min, hour,
357
                     mday,  // Day of the month in 1..31 range.
358
                     yday;  // Day of the year in 0..365 range.
359
        Month mon;
360
        int year;
361
362
        // default ctor inits the object to an invalid value
363
        Tm();
364
365
        // ctor from struct tm and the timezone
366
        Tm(const struct tm& tm, const TimeZone& tz);
367
368
        // check that the given date/time is valid (in Gregorian calendar)
369
        bool IsValid() const;
370
371
        // get the week day
372
        WeekDay GetWeekDay() // not const because wday may be changed
373
0
        {
374
0
            if ( wday == Inv_WeekDay )
375
0
                ComputeWeekDay();
376
377
0
            return (WeekDay)wday;
378
0
        }
379
380
        // add the given number of months to the date keeping it normalized
381
        void AddMonths(int monDiff);
382
383
        // add the given number of months to the date keeping it normalized
384
        void AddDays(int dayDiff);
385
386
    private:
387
        // compute the weekday from other fields
388
        void ComputeWeekDay();
389
390
        // the timezone we correspond to
391
        TimeZone m_tz;
392
393
        // This value can only be accessed via GetWeekDay() and not directly
394
        // because it's not always computed when creating this object and may
395
        // need to be calculated on demand.
396
        wxDateTime_t wday;
397
    };
398
399
    // static methods
400
    // ------------------------------------------------------------------------
401
402
        // set the current country
403
    static void SetCountry(Country country);
404
        // get the current country
405
    static Country GetCountry();
406
407
        // return true if the country is a West European one (in practice,
408
        // this means that the same DST rules as for EEC apply)
409
    static bool IsWestEuropeanCountry(Country country = Country_Default);
410
411
        // return the current year
412
    static int GetCurrentYear(Calendar cal = Gregorian);
413
414
        // convert the year as returned by wxDateTime::GetYear() to a year
415
        // suitable for BC/AD notation. The difference is that BC year 1
416
        // corresponds to the year 0 (while BC year 0 didn't exist) and AD
417
        // year N is just year N.
418
    static int ConvertYearToBC(int year);
419
420
        // return the current month
421
    static Month GetCurrentMonth(Calendar cal = Gregorian);
422
423
        // returns true if the given year is a leap year in the given calendar
424
    static bool IsLeapYear(int year = Inv_Year, Calendar cal = Gregorian);
425
426
        // acquires the first day of week based on locale and/or OS settings
427
    static bool GetFirstWeekDay(WeekDay *firstDay);
428
429
        // get the century (19 for 1999, 20 for 2000 and -5 for 492 BC)
430
    static int GetCentury(int year);
431
432
        // returns the number of days in this year (356 or 355 for Gregorian
433
        // calendar usually :-)
434
    static wxDateTime_t GetNumberOfDays(int year, Calendar cal = Gregorian);
435
436
        // get the number of the days in the given month (default value for
437
        // the year means the current one)
438
    static wxDateTime_t GetNumberOfDays(Month month,
439
                                        int year = Inv_Year,
440
                                        Calendar cal = Gregorian);
441
442
443
        // get the full (default), abbreviated or shortest month name in the current
444
        // locale, returns empty string on error
445
    static wxString GetMonthName(Month month,
446
                                 const NameForm& form = {});
447
448
        // get the standard English full (default), abbreviated or shortest month name
449
    static wxString GetEnglishMonthName(Month month,
450
                                        const NameForm& form = {});
451
452
        // get the full (default), abbreviated or shortest weekday name in the current
453
        // locale, returns empty string on error
454
    static wxString GetWeekDayName(WeekDay weekday,
455
                                   const NameForm& form = {});
456
457
        // get the standard English full (default), abbreviated or shortest weekday name
458
    static wxString GetEnglishWeekDayName(WeekDay weekday,
459
                                          const NameForm& form = {});
460
461
        // get the AM and PM strings in the current locale (may be empty)
462
    static void GetAmPmStrings(wxString *am, wxString *pm);
463
464
        // return true if the given country uses DST for this year
465
    static bool IsDSTApplicable(int year = Inv_Year,
466
                                Country country = Country_Default);
467
468
        // get the beginning of DST for this year, will return invalid object
469
        // if no DST applicable in this year. The default value of the
470
        // parameter means to take the current year.
471
    static wxDateTime GetBeginDST(int year = Inv_Year,
472
                                  Country country = Country_Default);
473
        // get the end of DST for this year, will return invalid object
474
        // if no DST applicable in this year. The default value of the
475
        // parameter means to take the current year.
476
    static wxDateTime GetEndDST(int year = Inv_Year,
477
                                Country country = Country_Default);
478
479
        // return the wxDateTime object for the current time
480
    static inline wxDateTime Now();
481
482
        // return the wxDateTime object for the current time with millisecond
483
        // precision (if available on this platform)
484
    static wxDateTime UNow();
485
486
        // return the wxDateTime object for today midnight: i.e. as Now() but
487
        // with time set to 0
488
    static inline wxDateTime Today();
489
490
    // constructors: you should test whether the constructor succeeded with
491
    // IsValid() function. The values Inv_Month and Inv_Year for the
492
    // parameters mean take current month and/or year values.
493
    // ------------------------------------------------------------------------
494
495
        // default ctor does not initialize the object, use Set()!
496
51.8k
    wxDateTime() : m_time(wxINT64_MIN) { }
497
498
        // from time_t: seconds since the Epoch 00:00:00 UTC, Jan 1, 1970)
499
    inline wxDateTime(time_t timet);
500
        // from broken down time/date (only for standard Unix range)
501
    inline wxDateTime(const struct tm& tm);
502
        // from broken down time/date (any range)
503
    inline wxDateTime(const Tm& tm);
504
505
        // from JDN (beware of rounding errors)
506
    inline wxDateTime(double jdn);
507
508
        // from separate values for each component, date set to today
509
    inline wxDateTime(wxDateTime_t hour,
510
                      wxDateTime_t minute = 0,
511
                      wxDateTime_t second = 0,
512
                      wxDateTime_t millisec = 0);
513
        // from separate values for each component with explicit date
514
    inline wxDateTime(wxDateTime_t day,             // day of the month
515
                      Month        month,
516
                      int          year = Inv_Year, // 1999, not 99 please!
517
                      wxDateTime_t hour = 0,
518
                      wxDateTime_t minute = 0,
519
                      wxDateTime_t second = 0,
520
                      wxDateTime_t millisec = 0);
521
#ifdef __WINDOWS__
522
    wxDateTime(const struct _SYSTEMTIME& st)
523
    {
524
        SetFromMSWSysTime(st);
525
    }
526
#endif
527
528
        // default copy ctor ok
529
530
        // no dtor
531
532
    // assignment operators and Set() functions: all non const methods return
533
    // the reference to this object. IsValid() should be used to test whether
534
    // the function succeeded.
535
    // ------------------------------------------------------------------------
536
537
        // set to the current time
538
    inline wxDateTime& SetToCurrent();
539
540
        // set to given time_t value
541
    inline wxDateTime& Set(time_t timet);
542
543
        // set to given broken down time/date
544
    wxDateTime& Set(const struct tm& tm);
545
546
        // set to given broken down time/date
547
    inline wxDateTime& Set(const Tm& tm);
548
549
        // set to given JDN (beware of rounding errors)
550
    wxDateTime& Set(double jdn);
551
552
        // set to given time, date = today
553
    wxDateTime& Set(wxDateTime_t hour,
554
                    wxDateTime_t minute = 0,
555
                    wxDateTime_t second = 0,
556
                    wxDateTime_t millisec = 0);
557
558
        // from separate values for each component with explicit date
559
        // (defaults for month and year are the current values)
560
    wxDateTime& Set(wxDateTime_t day,
561
                    Month        month,
562
                    int          year = Inv_Year, // 1999, not 99 please!
563
                    wxDateTime_t hour = 0,
564
                    wxDateTime_t minute = 0,
565
                    wxDateTime_t second = 0,
566
                    wxDateTime_t millisec = 0);
567
568
        // resets time to 00:00:00, doesn't change the date
569
    wxDateTime& ResetTime();
570
571
        // get the date part of this object only, i.e. the object which has the
572
        // same date as this one but time of 00:00:00
573
    wxDateTime GetDateOnly() const;
574
575
        // the following functions don't change the values of the other
576
        // fields, i.e. SetMinute() won't change either hour or seconds value
577
578
        // set the year
579
    wxDateTime& SetYear(int year);
580
        // set the month
581
    wxDateTime& SetMonth(Month month);
582
        // set the day of the month
583
    wxDateTime& SetDay(wxDateTime_t day);
584
        // set hour
585
    wxDateTime& SetHour(wxDateTime_t hour);
586
        // set minute
587
    wxDateTime& SetMinute(wxDateTime_t minute);
588
        // set second
589
    wxDateTime& SetSecond(wxDateTime_t second);
590
        // set millisecond
591
    wxDateTime& SetMillisecond(wxDateTime_t millisecond);
592
593
        // assignment operator from time_t
594
0
    wxDateTime& operator=(time_t timet) { return Set(timet); }
595
596
        // assignment operator from broken down time/date
597
0
    wxDateTime& operator=(const struct tm& tm) { return Set(tm); }
598
599
        // assignment operator from broken down time/date
600
0
    wxDateTime& operator=(const Tm& tm) { return Set(tm); }
601
602
        // default assignment operator is ok
603
604
    // calendar calculations (functions which set the date only leave the time
605
    // unchanged, e.g. don't explicitly zero it): SetXXX() functions modify the
606
    // object itself, GetXXX() ones return a new object.
607
    // ------------------------------------------------------------------------
608
609
        // set to the given week day in the same week as this one
610
    wxDateTime& SetToWeekDayInSameWeek(WeekDay weekday,
611
                                       WeekFlags flags = Monday_First);
612
    inline wxDateTime GetWeekDayInSameWeek(WeekDay weekday,
613
                                           WeekFlags flags = Monday_First) const;
614
615
        // set to the next week day following this one
616
    wxDateTime& SetToNextWeekDay(WeekDay weekday);
617
    inline wxDateTime GetNextWeekDay(WeekDay weekday) const;
618
619
        // set to the previous week day before this one
620
    wxDateTime& SetToPrevWeekDay(WeekDay weekday);
621
    inline wxDateTime GetPrevWeekDay(WeekDay weekday) const;
622
623
        // set to Nth occurrence of given weekday in the given month of the
624
        // given year (time is set to 0), return true on success and false on
625
        // failure. n may be positive (1..5) or negative to count from the end
626
        // of the month (see helper function SetToLastWeekDay())
627
    bool SetToWeekDay(WeekDay weekday,
628
                      int n = 1,
629
                      Month month = Inv_Month,
630
                      int year = Inv_Year);
631
    inline wxDateTime GetWeekDay(WeekDay weekday,
632
                                 int n = 1,
633
                                 Month month = Inv_Month,
634
                                 int year = Inv_Year) const;
635
636
        // sets to the last weekday in the given month, year
637
    inline bool SetToLastWeekDay(WeekDay weekday,
638
                                 Month month = Inv_Month,
639
                                 int year = Inv_Year);
640
    inline wxDateTime GetLastWeekDay(WeekDay weekday,
641
                                     Month month = Inv_Month,
642
                                     int year = Inv_Year);
643
644
        // returns the date corresponding to the given week day of the given
645
        // week (in ISO notation) of the specified year
646
    static wxDateTime SetToWeekOfYear(int year,
647
                                      wxDateTime_t numWeek,
648
                                      WeekDay weekday = Mon);
649
650
        // sets the date to the last day of the given (or current) month or the
651
        // given (or current) year
652
    wxDateTime& SetToLastMonthDay(Month month = Inv_Month,
653
                                  int year = Inv_Year);
654
    inline wxDateTime GetLastMonthDay(Month month = Inv_Month,
655
                                      int year = Inv_Year) const;
656
657
        // sets to the given year day (1..365 or 366)
658
    wxDateTime& SetToYearDay(wxDateTime_t yday);
659
    inline wxDateTime GetYearDay(wxDateTime_t yday) const;
660
661
        // The definitions below were taken verbatim from
662
        //
663
        //      http://www.capecod.net/~pbaum/date/date0.htm
664
        //
665
        // (Peter Baum's home page)
666
        //
667
        // definition: The Julian Day Number, Julian Day, or JD of a
668
        // particular instant of time is the number of days and fractions of a
669
        // day since 12 hours Universal Time (Greenwich mean noon) on January
670
        // 1 of the year -4712, where the year is given in the Julian
671
        // proleptic calendar. The idea of using this reference date was
672
        // originally proposed by Joseph Scalizer in 1582 to count years but
673
        // it was modified by 19th century astronomers to count days. One
674
        // could have equivalently defined the reference time to be noon of
675
        // November 24, -4713 if were understood that Gregorian calendar rules
676
        // were applied. Julian days are Julian Day Numbers and are not to be
677
        // confused with Julian dates.
678
        //
679
        // definition: The Rata Die number is a date specified as the number
680
        // of days relative to a base date of December 31 of the year 0. Thus
681
        // January 1 of the year 1 is Rata Die day 1.
682
683
        // get the Julian Day number (the fractional part specifies the time of
684
        // the day, related to noon - beware of rounding errors!)
685
    double GetJulianDayNumber() const;
686
0
    double GetJDN() const { return GetJulianDayNumber(); }
687
688
        // get the Modified Julian Day number: it is equal to JDN - 2400000.5
689
        // and so integral MJDs correspond to the midnights (and not noons).
690
        // MJD 0 is Nov 17, 1858
691
0
    double GetModifiedJulianDayNumber() const { return GetJDN() - 2400000.5; }
692
0
    double GetMJD() const { return GetModifiedJulianDayNumber(); }
693
694
        // get the Rata Die number
695
    double GetRataDie() const;
696
697
        // TODO algorithms for calculating some important dates, such as
698
        //      religious holidays (Easter...) or moon/solar eclipses? Some
699
        //      algorithms can be found in the calendar FAQ
700
701
702
    // Timezone stuff: a wxDateTime object constructed using given
703
    // day/month/year/hour/min/sec values is interpreted as this moment in
704
    // local time. Using the functions below, it may be converted to another
705
    // time zone (e.g., the Unix epoch is wxDateTime(1, Jan, 1970).ToGMT()).
706
    //
707
    // These functions try to handle DST internally, but there is no magical
708
    // way to know all rules for it in all countries in the world, so if the
709
    // program can handle it itself (or doesn't want to handle it at all for
710
    // whatever reason), the DST handling can be disabled with noDST.
711
    // ------------------------------------------------------------------------
712
713
        // transform to any given timezone
714
    inline wxDateTime ToTimezone(const TimeZone& tz, bool noDST = false) const;
715
    wxDateTime& MakeTimezone(const TimeZone& tz, bool noDST = false);
716
717
        // interpret current value as being in another timezone and transform
718
        // it to local one
719
    inline wxDateTime FromTimezone(const TimeZone& tz, bool noDST = false) const;
720
    wxDateTime& MakeFromTimezone(const TimeZone& tz, bool noDST = false);
721
722
        // transform to/from GMT/UTC
723
0
    wxDateTime ToUTC(bool noDST = false) const { return ToTimezone(UTC, noDST); }
724
0
    wxDateTime& MakeUTC(bool noDST = false) { return MakeTimezone(UTC, noDST); }
725
726
0
    wxDateTime ToGMT(bool noDST = false) const { return ToUTC(noDST); }
727
0
    wxDateTime& MakeGMT(bool noDST = false) { return MakeUTC(noDST); }
728
729
    wxDateTime FromUTC(bool noDST = false) const
730
0
        { return FromTimezone(UTC, noDST); }
731
    wxDateTime& MakeFromUTC(bool noDST = false)
732
0
        { return MakeFromTimezone(UTC, noDST); }
733
734
        // is daylight savings time in effect at this moment according to the
735
        // rules of the specified country?
736
        //
737
        // Return value is > 0 if DST is in effect, 0 if it is not and -1 if
738
        // the information is not available (this is compatible with ANSI C)
739
    int IsDST(Country country = Country_Default) const;
740
741
742
    // accessors: many of them take the timezone parameter which indicates the
743
    // timezone for which to make the calculations and the default value means
744
    // to do it for the current timezone of this machine (even if the function
745
    // only operates with the date it's necessary because a date may wrap as
746
    // result of timezone shift)
747
    // ------------------------------------------------------------------------
748
749
        // is the date valid?
750
30
    inline bool IsValid() const { return m_time != wxLongLong(wxINT64_MIN); }
751
752
        // get the broken down date/time representation in the given timezone
753
        //
754
        // If you wish to get several time components (day, month and year),
755
        // consider getting the whole Tm structure first and retrieving the
756
        // value from it - this is much more efficient
757
    Tm GetTm(const TimeZone& tz = Local) const;
758
759
        // get the number of seconds since the Unix epoch - returns (time_t)-1
760
        // if the value is out of range
761
    inline time_t GetTicks() const;
762
763
        // get the century, same as GetCentury(GetYear())
764
    int GetCentury(const TimeZone& tz = Local) const
765
0
            { return GetCentury(GetYear(tz)); }
766
        // get the year (returns Inv_Year if date is invalid)
767
    int GetYear(const TimeZone& tz = Local) const
768
0
            { return GetTm(tz).year; }
769
        // get the month (Inv_Month if date is invalid)
770
    Month GetMonth(const TimeZone& tz = Local) const
771
0
            { return (Month)GetTm(tz).mon; }
772
        // get the month day (in 1..31 range, 0 if date is invalid)
773
    wxDateTime_t GetDay(const TimeZone& tz = Local) const
774
0
            { return GetTm(tz).mday; }
775
        // get the day of the week (Inv_WeekDay if date is invalid)
776
    WeekDay GetWeekDay(const TimeZone& tz = Local) const
777
0
            { return GetTm(tz).GetWeekDay(); }
778
        // get the hour of the day
779
    wxDateTime_t GetHour(const TimeZone& tz = Local) const
780
0
            { return GetTm(tz).hour; }
781
        // get the minute
782
    wxDateTime_t GetMinute(const TimeZone& tz = Local) const
783
0
            { return GetTm(tz).min; }
784
        // get the second
785
    wxDateTime_t GetSecond(const TimeZone& tz = Local) const
786
0
            { return GetTm(tz).sec; }
787
        // get milliseconds
788
    wxDateTime_t GetMillisecond(const TimeZone& tz = Local) const
789
0
            { return GetTm(tz).msec; }
790
791
        // get the day since the year start (1..366, 0 if date is invalid)
792
    wxDateTime_t GetDayOfYear(const TimeZone& tz = Local) const;
793
        // get the week number since the year start (1..52 or 53, 0 if date is
794
        // invalid)
795
    wxDateTime_t GetWeekOfYear(WeekFlags flags = Monday_First,
796
                               const TimeZone& tz = Local) const;
797
        // get the year to which the number returned from GetWeekOfYear()
798
        // belongs
799
    int GetWeekBasedYear(const TimeZone& tz = Local) const;
800
        // get the week number since the month start (1..5, 0 if date is
801
        // invalid)
802
    wxDateTime_t GetWeekOfMonth(WeekFlags flags = Monday_First,
803
                                const TimeZone& tz = Local) const;
804
805
        // is this date a work day? This depends on a country, of course,
806
        // because the holidays are different in different countries
807
    bool IsWorkDay(Country country = Country_Default) const;
808
809
    // dos date and time format
810
    // ------------------------------------------------------------------------
811
812
        // set from the DOS packed format
813
    wxDateTime& SetFromDOS(unsigned long ddt);
814
815
        // pack the date in DOS format
816
    unsigned long GetAsDOS() const;
817
818
    // SYSTEMTIME format
819
    // ------------------------------------------------------------------------
820
#ifdef __WINDOWS__
821
    // convert SYSTEMTIME to wxDateTime
822
    wxDateTime& SetFromMSWSysTime(const struct _SYSTEMTIME& st);
823
824
    // convert wxDateTime to SYSTEMTIME
825
    void GetAsMSWSysTime(struct _SYSTEMTIME* st) const;
826
827
    // same as above but only take date part into account, time is always zero
828
    wxDateTime& SetFromMSWSysDate(const struct _SYSTEMTIME& st);
829
    void GetAsMSWSysDate(struct _SYSTEMTIME* st) const;
830
#endif // __WINDOWS__
831
832
    // comparison (see also functions below for operator versions)
833
    // ------------------------------------------------------------------------
834
835
        // returns true if the two moments are strictly identical
836
    inline bool IsEqualTo(const wxDateTime& datetime) const;
837
838
        // returns true if the date is strictly earlier than the given one
839
    inline bool IsEarlierThan(const wxDateTime& datetime) const;
840
841
        // returns true if the date is strictly later than the given one
842
    inline bool IsLaterThan(const wxDateTime& datetime) const;
843
844
        // returns true if the date is strictly in the given range
845
    inline bool IsStrictlyBetween(const wxDateTime& t1,
846
                                  const wxDateTime& t2) const;
847
848
        // returns true if the date is in the given range
849
    inline bool IsBetween(const wxDateTime& t1, const wxDateTime& t2) const;
850
851
        // do these two objects refer to the same date?
852
    inline bool IsSameDate(const wxDateTime& dt) const;
853
854
        // do these two objects have the same time?
855
    inline bool IsSameTime(const wxDateTime& dt) const;
856
857
        // are these two objects equal up to given timespan?
858
    inline bool IsEqualUpTo(const wxDateTime& dt, const wxTimeSpan& ts) const;
859
860
    inline bool operator<(const wxDateTime& dt) const
861
0
    {
862
0
        return GetValue() < dt.GetValue();
863
0
    }
864
865
    inline bool operator<=(const wxDateTime& dt) const
866
0
    {
867
0
        return GetValue() <= dt.GetValue();
868
0
    }
869
870
    inline bool operator>(const wxDateTime& dt) const
871
0
    {
872
0
        return GetValue() > dt.GetValue();
873
0
    }
874
875
    inline bool operator>=(const wxDateTime& dt) const
876
0
    {
877
0
        return GetValue() >= dt.GetValue();
878
0
    }
879
880
    inline bool operator==(const wxDateTime& dt) const
881
0
    {
882
        // Intentionally do not call GetValue() here, in order that
883
        // invalid wxDateTimes may be compared for equality
884
0
        return m_time == dt.m_time;
885
0
    }
886
887
    inline bool operator!=(const wxDateTime& dt) const
888
0
    {
889
0
        // As above, don't use GetValue() here.
890
0
        return m_time != dt.m_time;
891
0
    }
892
893
    // arithmetic with dates (see also below for more operators)
894
    // ------------------------------------------------------------------------
895
896
        // return the sum of the date with a time span (positive or negative)
897
    inline wxDateTime Add(const wxTimeSpan& diff) const;
898
        // add a time span (positive or negative)
899
    inline wxDateTime& Add(const wxTimeSpan& diff);
900
        // add a time span (positive or negative)
901
    inline wxDateTime& operator+=(const wxTimeSpan& diff);
902
    inline wxDateTime operator+(const wxTimeSpan& ts) const
903
0
    {
904
0
        wxDateTime dt(*this);
905
0
        dt.Add(ts);
906
0
        return dt;
907
0
    }
908
909
        // return the difference of the date with a time span
910
    inline wxDateTime Subtract(const wxTimeSpan& diff) const;
911
        // subtract a time span (positive or negative)
912
    inline wxDateTime& Subtract(const wxTimeSpan& diff);
913
        // subtract a time span (positive or negative)
914
    inline wxDateTime& operator-=(const wxTimeSpan& diff);
915
    inline wxDateTime operator-(const wxTimeSpan& ts) const
916
0
    {
917
0
        wxDateTime dt(*this);
918
0
        dt.Subtract(ts);
919
0
        return dt;
920
0
    }
921
922
        // return the sum of the date with a date span
923
    inline wxDateTime Add(const wxDateSpan& diff) const;
924
        // add a date span (positive or negative)
925
    wxDateTime& Add(const wxDateSpan& diff);
926
        // add a date span (positive or negative)
927
    inline wxDateTime& operator+=(const wxDateSpan& diff);
928
    inline wxDateTime operator+(const wxDateSpan& ds) const
929
0
    {
930
0
        wxDateTime dt(*this);
931
0
        dt.Add(ds);
932
0
        return dt;
933
0
    }
934
935
        // return the difference of the date with a date span
936
    inline wxDateTime Subtract(const wxDateSpan& diff) const;
937
        // subtract a date span (positive or negative)
938
    inline wxDateTime& Subtract(const wxDateSpan& diff);
939
        // subtract a date span (positive or negative)
940
    inline wxDateTime& operator-=(const wxDateSpan& diff);
941
    inline wxDateTime operator-(const wxDateSpan& ds) const
942
0
    {
943
0
        wxDateTime dt(*this);
944
0
        dt.Subtract(ds);
945
0
        return dt;
946
0
    }
947
948
        // return the difference between two dates
949
    inline wxTimeSpan Subtract(const wxDateTime& dt) const;
950
    inline wxTimeSpan operator-(const wxDateTime& dt2) const;
951
952
    wxDateSpan DiffAsDateSpan(const wxDateTime& dt) const;
953
954
    // conversion to/from text
955
    // ------------------------------------------------------------------------
956
957
    // all conversions functions return true to indicate whether parsing
958
    // succeeded or failed and fill in the provided end iterator, which must
959
    // not be null, with the location of the character where the parsing
960
    // stopped (this will be end() of the passed string if everything was
961
    // parsed)
962
963
        // parse a string in RFC 822 format (found e.g. in mail headers and
964
        // having the form "Wed, 10 Feb 1999 19:07:07 +0100")
965
    bool ParseRfc822Date(const wxString& date,
966
                         wxString::const_iterator *end);
967
968
        // parse a date/time in the given format (see strptime(3)), fill in
969
        // the missing (in the string) fields with the values of dateDef (by
970
        // default, they will not change if they had valid values or will
971
        // default to Today() otherwise)
972
    bool ParseFormat(const wxString& date,
973
                     const wxString& format,
974
                     const wxDateTime& dateDef,
975
                     wxString::const_iterator *end);
976
977
    bool ParseFormat(const wxString& date,
978
                     const wxString& format,
979
                     wxString::const_iterator *end)
980
0
    {
981
0
        return ParseFormat(date, format, wxDefaultDateTime, end);
982
0
    }
983
984
    bool ParseFormat(const wxString& date,
985
                     wxString::const_iterator *end)
986
0
    {
987
0
        return ParseFormat(date, wxASCII_STR(wxDefaultDateTimeFormat), wxDefaultDateTime, end);
988
0
    }
989
990
        // parse a string containing date, time or both in ISO 8601 format
991
        //
992
        // notice that these functions are new in wx 3.0 and so we don't
993
        // provide compatibility overloads for them
994
    bool ParseISODate(const wxString& date)
995
0
    {
996
0
        wxString::const_iterator end;
997
0
        return ParseFormat(date, wxS("%Y-%m-%d"), &end) && end == date.end();
998
0
    }
999
1000
    bool ParseISOTime(const wxString& time)
1001
0
    {
1002
0
        wxString::const_iterator end;
1003
0
        return ParseFormat(time, wxS("%H:%M:%S"), &end) && end == time.end();
1004
0
    }
1005
1006
    bool ParseISOCombined(const wxString& datetime, char sep = 'T')
1007
0
    {
1008
0
        wxString::const_iterator end;
1009
0
        const wxString fmt = wxS("%Y-%m-%d") + wxString(sep) + wxS("%H:%M:%S");
1010
0
        return ParseFormat(datetime, fmt, &end) && end == datetime.end();
1011
0
    }
1012
1013
        // parse a string containing the date/time in "free" format, this
1014
        // function will try to make an educated guess at the string contents
1015
    bool ParseDateTime(const wxString& datetime,
1016
                       wxString::const_iterator *end);
1017
1018
        // parse a string containing the date only in "free" format (less
1019
        // flexible than ParseDateTime)
1020
    bool ParseDate(const wxString& date,
1021
                   wxString::const_iterator *end);
1022
1023
        // parse a string containing the time only in "free" format
1024
    bool ParseTime(const wxString& time,
1025
                   wxString::const_iterator *end);
1026
1027
1028
        // this function accepts strftime()-like format string (default
1029
        // argument corresponds to the preferred date and time representation
1030
        // for the current locale) and returns the string containing the
1031
        // resulting text representation
1032
    wxString Format(const wxString& format = wxASCII_STR(wxDefaultDateTimeFormat),
1033
                    const TimeZone& tz = Local) const;
1034
        // preferred date representation for the current locale
1035
0
    wxString FormatDate() const { return Format(wxS("%x")); }
1036
        // preferred time representation for the current locale
1037
0
    wxString FormatTime() const { return Format(wxS("%X")); }
1038
        // returns the string representing the date in ISO 8601 format
1039
        // (YYYY-MM-DD)
1040
0
    wxString FormatISODate() const { return Format(wxS("%Y-%m-%d")); }
1041
        // returns the string representing the time in ISO 8601 format
1042
        // (HH:MM:SS)
1043
0
    wxString FormatISOTime() const { return Format(wxS("%H:%M:%S")); }
1044
        // return the combined date time representation in ISO 8601 format; the
1045
        // separator character should be 'T' according to the standard but it
1046
        // can also be useful to set it to ' '
1047
    wxString FormatISOCombined(char sep = 'T') const
1048
0
        { return FormatISODate() + sep + FormatISOTime(); }
1049
1050
1051
    // backwards compatible versions of the parsing functions: they return an
1052
    // object representing the next character following the date specification
1053
    // (i.e. the one where the scan had to stop) or a special nullptr-like object
1054
    // on failure
1055
    //
1056
    // they're not deprecated because a lot of existing code uses them and
1057
    // there is no particular harm in keeping them but you should still prefer
1058
    // the versions above in the new code
1059
    wxAnyStrPtr ParseRfc822Date(const wxString& date)
1060
0
    {
1061
0
        wxString::const_iterator end;
1062
0
        return ParseRfc822Date(date, &end) ? wxAnyStrPtr(date, end)
1063
0
                                           : wxAnyStrPtr();
1064
0
    }
1065
1066
    wxAnyStrPtr ParseFormat(const wxString& date,
1067
                            const wxString& format = wxASCII_STR(wxDefaultDateTimeFormat),
1068
                            const wxDateTime& dateDef = wxDefaultDateTime)
1069
0
    {
1070
0
        wxString::const_iterator end;
1071
0
        return ParseFormat(date, format, dateDef, &end) ? wxAnyStrPtr(date, end)
1072
0
                                                        : wxAnyStrPtr();
1073
0
    }
1074
1075
    wxAnyStrPtr ParseDateTime(const wxString& datetime)
1076
0
    {
1077
0
        wxString::const_iterator end;
1078
0
        return ParseDateTime(datetime, &end) ? wxAnyStrPtr(datetime, end)
1079
0
                                             : wxAnyStrPtr();
1080
0
    }
1081
1082
    wxAnyStrPtr ParseDate(const wxString& date)
1083
0
    {
1084
0
        wxString::const_iterator end;
1085
0
        return ParseDate(date, &end) ? wxAnyStrPtr(date, end)
1086
0
                                     : wxAnyStrPtr();
1087
0
    }
1088
1089
    wxAnyStrPtr ParseTime(const wxString& time)
1090
0
    {
1091
0
        wxString::const_iterator end;
1092
0
        return ParseTime(time, &end) ? wxAnyStrPtr(time, end)
1093
0
                                     : wxAnyStrPtr();
1094
0
    }
1095
1096
    // In addition to wxAnyStrPtr versions above we also must provide the
1097
    // overloads for C strings as we must return a pointer into the original
1098
    // string and not inside a temporary wxString which would have been created
1099
    // if the overloads above were used.
1100
    //
1101
    // And then we also have to provide the overloads for wxCStrData, as usual.
1102
    // Unfortunately those can't return anything as we don't have any
1103
    // sufficiently long-lived wxAnyStrPtr to return from them: any temporary
1104
    // strings it would point to would be destroyed when this function returns
1105
    // making it impossible to dereference the return value. So we just don't
1106
    // return anything from here which at least allows to keep compatibility
1107
    // with the code not testing the return value. Other uses of this method
1108
    // need to be converted to use one of the new bool-returning overloads
1109
    // above.
1110
    void ParseRfc822Date(const wxCStrData& date)
1111
0
        { ParseRfc822Date(wxString(date)); }
1112
    const char* ParseRfc822Date(const char* date);
1113
    const wchar_t* ParseRfc822Date(const wchar_t* date);
1114
1115
    void ParseFormat(const wxCStrData& date,
1116
                     const wxString& format = wxASCII_STR(wxDefaultDateTimeFormat),
1117
                     const wxDateTime& dateDef = wxDefaultDateTime)
1118
0
        { ParseFormat(wxString(date), format, dateDef); }
1119
    const char* ParseFormat(const char* date,
1120
                            const wxString& format = wxASCII_STR(wxDefaultDateTimeFormat),
1121
                            const wxDateTime& dateDef = wxDefaultDateTime);
1122
    const wchar_t* ParseFormat(const wchar_t* date,
1123
                               const wxString& format = wxASCII_STR(wxDefaultDateTimeFormat),
1124
                               const wxDateTime& dateDef = wxDefaultDateTime);
1125
1126
    void ParseDateTime(const wxCStrData& datetime)
1127
0
        { ParseDateTime(wxString(datetime)); }
1128
    const char* ParseDateTime(const char* datetime);
1129
    const wchar_t* ParseDateTime(const wchar_t* datetime);
1130
1131
    void ParseDate(const wxCStrData& date)
1132
0
        { ParseDate(wxString(date)); }
1133
    const char* ParseDate(const char* date);
1134
    const wchar_t* ParseDate(const wchar_t* date);
1135
1136
    void ParseTime(const wxCStrData& time)
1137
0
        { ParseTime(wxString(time)); }
1138
    const char* ParseTime(const char* time);
1139
    const wchar_t* ParseTime(const wchar_t* time);
1140
1141
1142
    // implementation
1143
    // ------------------------------------------------------------------------
1144
1145
        // construct from internal representation
1146
6.31k
    wxDateTime(const wxLongLong& time) : m_time(time) { }
1147
1148
        // get the internal representation
1149
    inline wxLongLong GetValue() const;
1150
1151
    // a helper function to get the current time_t
1152
14.5k
    static time_t GetTimeNow() { return time(nullptr); }
1153
1154
    // another one to get the current time broken down
1155
    static struct tm *GetTmNow()
1156
0
    {
1157
0
        static struct tm l_CurrentTime;
1158
0
        return GetTmNow(&l_CurrentTime);
1159
0
    }
1160
1161
    // get current time using thread-safe function
1162
    static struct tm *GetTmNow(struct tm *tmstruct);
1163
1164
private:
1165
    // the current country - as it's the same for all program objects (unless
1166
    // it runs on a _really_ big cluster system :-), this is a static member:
1167
    // see SetCountry() and GetCountry()
1168
    static Country ms_country;
1169
1170
    // this constant is used to transform a time_t value to the internal
1171
    // representation, as time_t is in seconds and we use milliseconds it's
1172
    // fixed to 1000
1173
    static const long TIME_T_FACTOR;
1174
1175
    // returns true if we fall in range in which we can use standard ANSI C
1176
    // functions
1177
    inline bool IsInStdRange() const;
1178
1179
    // assign the preferred first day of a week to flags, if necessary
1180
    void UseEffectiveWeekDayFlags(WeekFlags &flags) const;
1181
1182
    // parse time zone (e.g. "+0100") between [iterator,dateEnd)
1183
    bool ParseRFC822TimeZone(wxString::const_iterator* iterator,
1184
                             const wxString::const_iterator& dateEnd);
1185
1186
    // the internal representation of the time is the amount of milliseconds
1187
    // elapsed since the origin which is set by convention to the UNIX/C epoch
1188
    // value: the midnight of January 1, 1970 (UTC)
1189
    wxLongLong m_time;
1190
};
1191
1192
// ----------------------------------------------------------------------------
1193
// This class contains a difference between 2 wxDateTime values, so it makes
1194
// sense to add it to wxDateTime and it is the result of subtraction of 2
1195
// objects of that class. See also wxDateSpan.
1196
// ----------------------------------------------------------------------------
1197
1198
class WXDLLIMPEXP_BASE wxTimeSpan
1199
{
1200
public:
1201
    // constructors
1202
    // ------------------------------------------------------------------------
1203
1204
        // return the timespan for the given number of milliseconds
1205
0
    static wxTimeSpan Milliseconds(wxLongLong ms) { return wxTimeSpan(0, 0, 0, ms); }
1206
0
    static wxTimeSpan Millisecond() { return Milliseconds(1); }
1207
1208
        // return the timespan for the given number of seconds
1209
0
    static wxTimeSpan Seconds(wxLongLong sec) { return wxTimeSpan(0, 0, sec); }
1210
0
    static wxTimeSpan Second() { return Seconds(1); }
1211
1212
        // return the timespan for the given number of minutes
1213
0
    static wxTimeSpan Minutes(long min) { return wxTimeSpan(0, min, 0 ); }
1214
0
    static wxTimeSpan Minute() { return Minutes(1); }
1215
1216
        // return the timespan for the given number of hours
1217
0
    static wxTimeSpan Hours(long hours) { return wxTimeSpan(hours, 0, 0); }
1218
0
    static wxTimeSpan Hour() { return Hours(1); }
1219
1220
        // return the timespan for the given number of days
1221
0
    static wxTimeSpan Days(long days) { return Hours(24 * days); }
1222
0
    static wxTimeSpan Day() { return Days(1); }
1223
1224
        // return the timespan for the given number of weeks
1225
0
    static wxTimeSpan Weeks(long days) { return Days(7 * days); }
1226
0
    static wxTimeSpan Week() { return Weeks(1); }
1227
1228
        // default ctor constructs the 0 time span
1229
    wxTimeSpan() = default;
1230
1231
        // from separate values for each component, date set to 0 (hours are
1232
        // not restricted to 0..24 range, neither are minutes, seconds or
1233
        // milliseconds)
1234
    inline wxTimeSpan(long hours,
1235
                      long minutes = 0,
1236
                      wxLongLong seconds = 0,
1237
                      wxLongLong milliseconds = 0);
1238
1239
        // default copy ctor is ok
1240
1241
        // no dtor
1242
1243
    // arithmetic with time spans (see also below for more operators)
1244
    // ------------------------------------------------------------------------
1245
1246
        // return the sum of two timespans
1247
    inline wxTimeSpan Add(const wxTimeSpan& diff) const;
1248
        // add two timespans together
1249
    inline wxTimeSpan& Add(const wxTimeSpan& diff);
1250
        // add two timespans together
1251
0
    wxTimeSpan& operator+=(const wxTimeSpan& diff) { return Add(diff); }
1252
    inline wxTimeSpan operator+(const wxTimeSpan& ts) const
1253
0
    {
1254
0
        return wxTimeSpan(GetValue() + ts.GetValue());
1255
0
    }
1256
1257
        // return the difference of two timespans
1258
    inline wxTimeSpan Subtract(const wxTimeSpan& diff) const;
1259
        // subtract another timespan
1260
    inline wxTimeSpan& Subtract(const wxTimeSpan& diff);
1261
        // subtract another timespan
1262
0
    wxTimeSpan& operator-=(const wxTimeSpan& diff) { return Subtract(diff); }
1263
    inline wxTimeSpan operator-(const wxTimeSpan& ts) const
1264
0
    {
1265
0
        return wxTimeSpan(GetValue() - ts.GetValue());
1266
0
    }
1267
1268
        // multiply timespan by a scalar
1269
    inline wxTimeSpan Multiply(int n) const;
1270
        // multiply timespan by a scalar
1271
    inline wxTimeSpan& Multiply(int n);
1272
        // multiply timespan by a scalar
1273
0
    wxTimeSpan& operator*=(int n) { return Multiply(n); }
1274
    inline wxTimeSpan operator*(int n) const
1275
0
    {
1276
0
        return wxTimeSpan(*this).Multiply(n);
1277
0
    }
1278
1279
    friend WXDLLIMPEXP_BASE wxTimeSpan operator*(int n, const wxTimeSpan& ts);
1280
1281
        // return this timespan with opposite sign
1282
0
    wxTimeSpan Negate() const { return wxTimeSpan(-GetValue()); }
1283
        // negate the value of the timespan
1284
0
    wxTimeSpan& Neg() { m_diff = -GetValue(); return *this; }
1285
        // negate the value of the timespan
1286
0
    wxTimeSpan& operator-() { return Neg(); }
1287
1288
        // return the absolute value of the timespan: does _not_ modify the
1289
        // object
1290
    inline wxTimeSpan Abs() const;
1291
1292
        // there is intentionally no division because we don't want to
1293
        // introduce rounding errors in time calculations
1294
1295
    // comparison (see also operator versions below)
1296
    // ------------------------------------------------------------------------
1297
1298
        // is the timespan null?
1299
0
    bool IsNull() const { return m_diff == 0l; }
1300
        // returns true if the timespan is null
1301
0
    bool operator!() const { return !IsNull(); }
1302
1303
        // is the timespan positive?
1304
0
    bool IsPositive() const { return m_diff > 0l; }
1305
1306
        // is the timespan negative?
1307
0
    bool IsNegative() const { return m_diff < 0l; }
1308
1309
        // are two timespans equal?
1310
    inline bool IsEqualTo(const wxTimeSpan& ts) const;
1311
        // compare two timestamps: works with the absolute values, i.e. -2
1312
        // hours is longer than 1 hour. Also, it will return false if the
1313
        // timespans are equal in absolute value.
1314
    inline bool IsLongerThan(const wxTimeSpan& ts) const;
1315
        // compare two timestamps: works with the absolute values, i.e. 1
1316
        // hour is shorter than -2 hours. Also, it will return false if the
1317
        // timespans are equal in absolute value.
1318
    bool IsShorterThan(const wxTimeSpan& t) const;
1319
1320
    inline bool operator<(const wxTimeSpan &ts) const
1321
0
    {
1322
0
        return GetValue() < ts.GetValue();
1323
0
    }
1324
1325
    inline bool operator<=(const wxTimeSpan &ts) const
1326
0
    {
1327
0
        return GetValue() <= ts.GetValue();
1328
0
    }
1329
1330
    inline bool operator>(const wxTimeSpan &ts) const
1331
0
    {
1332
0
        return GetValue() > ts.GetValue();
1333
0
    }
1334
1335
    inline bool operator>=(const wxTimeSpan &ts) const
1336
0
    {
1337
0
        return GetValue() >= ts.GetValue();
1338
0
    }
1339
1340
    inline bool operator==(const wxTimeSpan &ts) const
1341
0
    {
1342
0
        return GetValue() == ts.GetValue();
1343
0
    }
1344
1345
    inline bool operator!=(const wxTimeSpan &ts) const
1346
0
    {
1347
0
        return GetValue() != ts.GetValue();
1348
0
    }
1349
1350
    // breaking into days, hours, minutes and seconds
1351
    // ------------------------------------------------------------------------
1352
1353
        // get the max number of weeks in this timespan
1354
    inline int GetWeeks() const;
1355
        // get the max number of days in this timespan
1356
    inline int GetDays() const;
1357
        // get the max number of hours in this timespan
1358
    inline int GetHours() const;
1359
        // get the max number of minutes in this timespan
1360
    inline int GetMinutes() const;
1361
        // get the max number of seconds in this timespan
1362
    inline wxLongLong GetSeconds() const;
1363
        // get the number of milliseconds in this timespan
1364
0
    wxLongLong GetMilliseconds() const { return m_diff; }
1365
1366
    // conversion to text
1367
    // ------------------------------------------------------------------------
1368
1369
        // this function accepts strftime()-like format string (default
1370
        // argument corresponds to the preferred date and time representation
1371
        // for the current locale) and returns the string containing the
1372
        // resulting text representation. Notice that only some of format
1373
        // specifiers valid for wxDateTime are valid for wxTimeSpan: hours,
1374
        // minutes and seconds make sense, but not "PM/AM" string for example.
1375
    wxString Format(const wxString& format = wxASCII_STR(wxDefaultTimeSpanFormat)) const;
1376
1377
    // implementation
1378
    // ------------------------------------------------------------------------
1379
1380
        // construct from internal representation
1381
0
    wxTimeSpan(const wxLongLong& diff) : m_diff(diff) { }
1382
1383
        // get the internal representation
1384
30
    wxLongLong GetValue() const { return m_diff; }
1385
1386
private:
1387
    // the (signed) time span in milliseconds
1388
    wxLongLong m_diff;
1389
};
1390
1391
// ----------------------------------------------------------------------------
1392
// This class is a "logical time span" and is useful for implementing program
1393
// logic for such things as "add one month to the date" which, in general,
1394
// doesn't mean to add 60*60*24*31 seconds to it, but to take the same date
1395
// the next month (to understand that this is indeed different consider adding
1396
// one month to Feb, 15 - we want to get Mar, 15, of course).
1397
//
1398
// When adding a month to the date, all lesser components (days, hours, ...)
1399
// won't be changed unless the resulting date would be invalid: for example,
1400
// Jan 31 + 1 month will be Feb 28, not (non existing) Feb 31.
1401
//
1402
// Because of this feature, adding and subtracting back again the same
1403
// wxDateSpan will *not*, in general give back the original date: Feb 28 - 1
1404
// month will be Jan 28, not Jan 31!
1405
//
1406
// wxDateSpan can be either positive or negative. They may be
1407
// multiplied by scalars which multiply all deltas by the scalar: i.e. 2*(1
1408
// month and 1 day) is 2 months and 2 days. They can be added together and
1409
// with wxDateTime or wxTimeSpan, but the type of result is different for each
1410
// case.
1411
//
1412
// Beware about weeks: if you specify both weeks and days, the total number of
1413
// days added will be 7*weeks + days! See also GetTotalDays() function.
1414
//
1415
// Equality operators are defined for wxDateSpans. Two datespans are equal if
1416
// they both give the same target date when added to *every* source date.
1417
// Thus wxDateSpan::Months(1) is not equal to wxDateSpan::Days(30), because
1418
// they not give the same date when added to 1 Feb. But wxDateSpan::Days(14) is
1419
// equal to wxDateSpan::Weeks(2)
1420
//
1421
// Finally, notice that for adding hours, minutes &c you don't need this
1422
// class: wxTimeSpan will do the job because there are no subtleties
1423
// associated with those.
1424
// ----------------------------------------------------------------------------
1425
1426
class WXDLLIMPEXP_BASE wxDateSpan
1427
{
1428
public:
1429
    // constructors
1430
    // ------------------------------------------------------------------------
1431
1432
        // this many years/months/weeks/days
1433
    wxDateSpan(int years = 0, int months = 0, int weeks = 0, int days = 0)
1434
0
    {
1435
0
        m_years = years;
1436
0
        m_months = months;
1437
0
        m_weeks = weeks;
1438
0
        m_days = days;
1439
0
    }
1440
1441
        // get an object for the given number of days
1442
0
    static wxDateSpan Days(int days) { return wxDateSpan(0, 0, 0, days); }
1443
0
    static wxDateSpan Day() { return Days(1); }
1444
1445
        // get an object for the given number of weeks
1446
0
    static wxDateSpan Weeks(int weeks) { return wxDateSpan(0, 0, weeks, 0); }
1447
0
    static wxDateSpan Week() { return Weeks(1); }
1448
1449
        // get an object for the given number of months
1450
0
    static wxDateSpan Months(int mon) { return wxDateSpan(0, mon, 0, 0); }
1451
0
    static wxDateSpan Month() { return Months(1); }
1452
1453
        // get an object for the given number of years
1454
0
    static wxDateSpan Years(int years) { return wxDateSpan(years, 0, 0, 0); }
1455
0
    static wxDateSpan Year() { return Years(1); }
1456
1457
        // default copy ctor is ok
1458
1459
        // no dtor
1460
1461
    // accessors (all SetXXX() return the (modified) wxDateSpan object)
1462
    // ------------------------------------------------------------------------
1463
1464
        // set number of years
1465
0
    wxDateSpan& SetYears(int n) { m_years = n; return *this; }
1466
        // set number of months
1467
0
    wxDateSpan& SetMonths(int n) { m_months = n; return *this; }
1468
        // set number of weeks
1469
0
    wxDateSpan& SetWeeks(int n) { m_weeks = n; return *this; }
1470
        // set number of days
1471
0
    wxDateSpan& SetDays(int n) { m_days = n; return *this; }
1472
1473
        // get number of years
1474
0
    int GetYears() const { return m_years; }
1475
        // get number of months
1476
0
    int GetMonths() const { return m_months; }
1477
        // returns 12*GetYears() + GetMonths()
1478
0
    int GetTotalMonths() const { return 12*m_years + m_months; }
1479
        // get number of weeks
1480
0
    int GetWeeks() const { return m_weeks; }
1481
        // get number of days
1482
0
    int GetDays() const { return m_days; }
1483
        // returns 7*GetWeeks() + GetDays()
1484
0
    int GetTotalDays() const { return 7*m_weeks + m_days; }
1485
1486
    // arithmetic with date spans (see also below for more operators)
1487
    // ------------------------------------------------------------------------
1488
1489
        // return sum of two date spans
1490
    inline wxDateSpan Add(const wxDateSpan& other) const;
1491
        // add another wxDateSpan to us
1492
    inline wxDateSpan& Add(const wxDateSpan& other);
1493
        // add another wxDateSpan to us
1494
    inline wxDateSpan& operator+=(const wxDateSpan& other);
1495
    inline wxDateSpan operator+(const wxDateSpan& ds) const
1496
0
    {
1497
0
        return wxDateSpan(GetYears() + ds.GetYears(),
1498
0
                          GetMonths() + ds.GetMonths(),
1499
0
                          GetWeeks() + ds.GetWeeks(),
1500
0
                          GetDays() + ds.GetDays());
1501
0
    }
1502
1503
        // return difference of two date spans
1504
    inline wxDateSpan Subtract(const wxDateSpan& other) const;
1505
        // subtract another wxDateSpan from us
1506
    inline wxDateSpan& Subtract(const wxDateSpan& other);
1507
        // subtract another wxDateSpan from us
1508
    inline wxDateSpan& operator-=(const wxDateSpan& other);
1509
    inline wxDateSpan operator-(const wxDateSpan& ds) const
1510
0
    {
1511
0
        return wxDateSpan(GetYears() - ds.GetYears(),
1512
0
                          GetMonths() - ds.GetMonths(),
1513
0
                          GetWeeks() - ds.GetWeeks(),
1514
0
                          GetDays() - ds.GetDays());
1515
0
    }
1516
1517
        // return a copy of this time span with changed sign
1518
    inline wxDateSpan Negate() const;
1519
        // inverse the sign of this timespan
1520
    inline wxDateSpan& Neg();
1521
        // inverse the sign of this timespan
1522
0
    wxDateSpan& operator-() { return Neg(); }
1523
1524
        // return the date span proportional to this one with given factor
1525
    inline wxDateSpan Multiply(int factor) const;
1526
        // multiply all components by a (signed) number
1527
    inline wxDateSpan& Multiply(int factor);
1528
        // multiply all components by a (signed) number
1529
0
    inline wxDateSpan& operator*=(int factor) { return Multiply(factor); }
1530
    inline wxDateSpan operator*(int n) const
1531
0
    {
1532
0
        return wxDateSpan(*this).Multiply(n);
1533
0
    }
1534
    friend WXDLLIMPEXP_BASE wxDateSpan operator*(int n, const wxDateSpan& ds);
1535
1536
    // ds1 == d2 if and only if for every wxDateTime t t + ds1 == t + ds2
1537
    inline bool operator==(const wxDateSpan& ds) const
1538
0
    {
1539
0
        return GetYears() == ds.GetYears() &&
1540
0
               GetMonths() == ds.GetMonths() &&
1541
0
               GetTotalDays() == ds.GetTotalDays();
1542
0
    }
1543
1544
    inline bool operator!=(const wxDateSpan& ds) const
1545
0
    {
1546
0
        return !(*this == ds);
1547
0
    }
1548
1549
private:
1550
    int m_years,
1551
        m_months,
1552
        m_weeks,
1553
        m_days;
1554
};
1555
1556
// ----------------------------------------------------------------------------
1557
// wxDateTimeArray: array of dates.
1558
// ----------------------------------------------------------------------------
1559
1560
using wxDateTimeArray = wxBaseArray<wxDateTime>;
1561
1562
// ----------------------------------------------------------------------------
1563
// wxDateTimeHolidayAuthority: an object of this class will decide whether a
1564
// given date is a holiday and is used by all functions working with "work
1565
// days".
1566
//
1567
// NB: the base class is an ABC, derived classes must implement the pure
1568
//     virtual methods to work with the holidays they correspond to.
1569
// ----------------------------------------------------------------------------
1570
1571
class WXDLLIMPEXP_FWD_BASE wxDateTimeHolidayAuthority;
1572
WX_DEFINE_USER_EXPORTED_ARRAY_PTR(wxDateTimeHolidayAuthority *,
1573
                              wxHolidayAuthoritiesArray,
1574
                              class WXDLLIMPEXP_BASE);
1575
1576
class wxDateTimeHolidaysModule;
1577
class WXDLLIMPEXP_BASE wxDateTimeHolidayAuthority
1578
{
1579
friend class wxDateTimeHolidaysModule;
1580
public:
1581
    // returns true if the given date is a holiday
1582
    static bool IsHoliday(const wxDateTime& dt);
1583
1584
    // fills the provided array with all holidays in the given range, returns
1585
    // the number of them
1586
    static size_t GetHolidaysInRange(const wxDateTime& dtStart,
1587
                                     const wxDateTime& dtEnd,
1588
                                     wxDateTimeArray& holidays);
1589
1590
    // clear the list of holiday authorities
1591
    static void ClearAllAuthorities();
1592
1593
    // add a new holiday authority (the pointer will be deleted by
1594
    // wxDateTimeHolidayAuthority)
1595
    static void AddAuthority(wxDateTimeHolidayAuthority *auth);
1596
1597
    // the base class must have a virtual dtor
1598
    virtual ~wxDateTimeHolidayAuthority();
1599
1600
protected:
1601
    // this function is called to determine whether a given day is a holiday
1602
    virtual bool DoIsHoliday(const wxDateTime& dt) const = 0;
1603
1604
    // this function should fill the array with all holidays between the two
1605
    // given dates
1606
    virtual size_t DoGetHolidaysInRange(const wxDateTime& dtStart,
1607
                                        const wxDateTime& dtEnd,
1608
                                        wxDateTimeArray& holidays) const = 0;
1609
1610
private:
1611
    // all holiday authorities
1612
    static wxHolidayAuthoritiesArray ms_authorities;
1613
};
1614
1615
// the holidays for this class are all Saturdays and Sundays
1616
class WXDLLIMPEXP_BASE wxDateTimeWorkDays : public wxDateTimeHolidayAuthority
1617
{
1618
protected:
1619
    virtual bool DoIsHoliday(const wxDateTime& dt) const override;
1620
    virtual size_t DoGetHolidaysInRange(const wxDateTime& dtStart,
1621
                                        const wxDateTime& dtEnd,
1622
                                        wxDateTimeArray& holidays) const override;
1623
};
1624
1625
// https://marian.org/mary/feast-days
1626
// https://www.omvusa.org/blog/catholic-holy-days-of-obligation/
1627
class WXDLLIMPEXP_BASE wxDateTimeUSCatholicFeasts : public wxDateTimeHolidayAuthority
1628
{
1629
public:
1630
    // Easter for a given year.
1631
    // Based on https://www.geeksforgeeks.org/how-to-calculate-the-easter-date-for-a-given-year-using-gauss-algorithm/
1632
    // Validated against 1600 to 2099, using data from:
1633
    // https://www.assa.org.au/edm (Astronomical Society of South Australia)
1634
    // https://www.census.gov/data/software/x13as/genhol/easter-dates.html (US Census Bureau)
1635
    static wxDateTime GetEaster(int year);
1636
1637
    // Ascension for a given year.
1638
    // Celebrated on the 40th day of Easter/
1639
    // the sixth Thursday after Easter Sunday.
1640
    static wxDateTime GetThursdayAscension(int year);
1641
1642
    // Ascension for a given year.
1643
    // Same as traditional Ascension, but moved to the following Sunday.
1644
    static wxDateTime GetSundayAscension(int year);
1645
protected:
1646
    bool DoIsHoliday(const wxDateTime& dt) const override;
1647
1648
    size_t DoGetHolidaysInRange(const wxDateTime& dtStart,
1649
                                const wxDateTime& dtEnd,
1650
                                wxDateTimeArray& holidays) const override;
1651
private:
1652
    static std::vector<wxDateTime> m_holyDaysOfObligation;
1653
};
1654
1655
// Christmas and Easter
1656
class WXDLLIMPEXP_BASE wxDateTimeChristianHolidays : public wxDateTimeUSCatholicFeasts
1657
{
1658
protected:
1659
    bool DoIsHoliday(const wxDateTime& dt) const override;
1660
};
1661
1662
// ============================================================================
1663
// inline functions implementation
1664
// ============================================================================
1665
1666
// ----------------------------------------------------------------------------
1667
// private macros
1668
// ----------------------------------------------------------------------------
1669
1670
#define MILLISECONDS_PER_DAY 86400000l
1671
1672
// some broken compilers (HP-UX CC) refuse to compile the "normal" version, but
1673
// using a temp variable always might prevent other compilers from optimising
1674
// it away - hence use of this ugly macro
1675
#ifndef __HPUX__
1676
0
    #define MODIFY_AND_RETURN(op) return wxDateTime(*this).op
1677
#else
1678
    #define MODIFY_AND_RETURN(op) wxDateTime dt(*this); dt.op; return dt
1679
#endif
1680
1681
// ----------------------------------------------------------------------------
1682
// wxDateTime construction
1683
// ----------------------------------------------------------------------------
1684
1685
inline bool wxDateTime::IsInStdRange() const
1686
0
{
1687
    // if sizeof(time_t) is greater than 32 bits, we assume it
1688
    // is safe to return values exceeding wxINT32_MAX
1689
1690
0
    return m_time >= 0l &&
1691
0
        ( (sizeof(time_t) > 4 ) || ( (m_time / TIME_T_FACTOR) < wxINT32_MAX) );
1692
0
}
1693
1694
/* static */
1695
inline wxDateTime wxDateTime::Now()
1696
14.5k
{
1697
14.5k
    struct tm tmstruct;
1698
14.5k
    return wxDateTime(*GetTmNow(&tmstruct));
1699
14.5k
}
1700
1701
/* static */
1702
inline wxDateTime wxDateTime::Today()
1703
0
{
1704
0
    wxDateTime dt(Now());
1705
0
    dt.ResetTime();
1706
1707
0
    return dt;
1708
0
}
1709
1710
inline wxDateTime& wxDateTime::Set(time_t timet)
1711
41.0k
{
1712
41.0k
    if ( timet == (time_t)-1 )
1713
0
    {
1714
0
        m_time = wxInvalidDateTime.m_time;
1715
0
    }
1716
41.0k
    else
1717
41.0k
    {
1718
        // assign first to avoid long multiplication overflow!
1719
41.0k
        m_time = timet - WX_TIME_BASE_OFFSET;
1720
41.0k
        m_time *= TIME_T_FACTOR;
1721
41.0k
    }
1722
1723
41.0k
    return *this;
1724
41.0k
}
1725
1726
inline wxDateTime& wxDateTime::SetToCurrent()
1727
0
{
1728
0
    *this = Now();
1729
0
    return *this;
1730
0
}
1731
1732
inline wxDateTime::wxDateTime(time_t timet)
1733
0
{
1734
0
    Set(timet);
1735
0
}
1736
1737
inline wxDateTime::wxDateTime(const struct tm& tm)
1738
14.5k
{
1739
14.5k
    Set(tm);
1740
14.5k
}
1741
1742
inline wxDateTime::wxDateTime(const Tm& tm)
1743
0
{
1744
0
    Set(tm);
1745
0
}
1746
1747
inline wxDateTime::wxDateTime(double jdn)
1748
{
1749
    Set(jdn);
1750
}
1751
1752
inline wxDateTime& wxDateTime::Set(const Tm& tm)
1753
0
{
1754
0
    wxASSERT_MSG( tm.IsValid(), wxT("invalid broken down date/time") );
1755
1756
0
    return Set(tm.mday, (Month)tm.mon, tm.year,
1757
0
               tm.hour, tm.min, tm.sec, tm.msec);
1758
0
}
1759
1760
inline wxDateTime::wxDateTime(wxDateTime_t hour,
1761
                              wxDateTime_t minute,
1762
                              wxDateTime_t second,
1763
                              wxDateTime_t millisec)
1764
{
1765
    Set(hour, minute, second, millisec);
1766
}
1767
1768
inline wxDateTime::wxDateTime(wxDateTime_t day,
1769
                              Month        month,
1770
                              int          year,
1771
                              wxDateTime_t hour,
1772
                              wxDateTime_t minute,
1773
                              wxDateTime_t second,
1774
                              wxDateTime_t millisec)
1775
30
{
1776
30
    Set(day, month, year, hour, minute, second, millisec);
1777
30
}
1778
1779
// ----------------------------------------------------------------------------
1780
// wxDateTime accessors
1781
// ----------------------------------------------------------------------------
1782
1783
inline wxLongLong wxDateTime::GetValue() const
1784
0
{
1785
0
    wxASSERT_MSG( IsValid(), wxT("invalid wxDateTime"));
1786
1787
0
    return m_time;
1788
0
}
1789
1790
inline time_t wxDateTime::GetTicks() const
1791
0
{
1792
0
    wxASSERT_MSG( IsValid(), wxT("invalid wxDateTime"));
1793
0
    if ( !IsInStdRange() )
1794
0
    {
1795
0
        return (time_t)-1;
1796
0
    }
1797
1798
0
    return (time_t)((m_time / TIME_T_FACTOR).GetValue()) + WX_TIME_BASE_OFFSET;
1799
0
}
1800
1801
inline bool wxDateTime::SetToLastWeekDay(WeekDay weekday,
1802
                                         Month month,
1803
                                         int year)
1804
0
{
1805
0
    return SetToWeekDay(weekday, -1, month, year);
1806
0
}
1807
1808
inline wxDateTime
1809
wxDateTime::GetWeekDayInSameWeek(WeekDay weekday,
1810
                                 WeekFlags WXUNUSED(flags)) const
1811
0
{
1812
0
    MODIFY_AND_RETURN( SetToWeekDayInSameWeek(weekday) );
1813
0
}
1814
1815
inline wxDateTime wxDateTime::GetNextWeekDay(WeekDay weekday) const
1816
0
{
1817
0
    MODIFY_AND_RETURN( SetToNextWeekDay(weekday) );
1818
0
}
1819
1820
inline wxDateTime wxDateTime::GetPrevWeekDay(WeekDay weekday) const
1821
0
{
1822
0
    MODIFY_AND_RETURN( SetToPrevWeekDay(weekday) );
1823
0
}
1824
1825
inline wxDateTime wxDateTime::GetWeekDay(WeekDay weekday,
1826
                                         int n,
1827
                                         Month month,
1828
                                         int year) const
1829
0
{
1830
0
    wxDateTime dt(*this);
1831
0
1832
0
    return dt.SetToWeekDay(weekday, n, month, year) ? dt : wxInvalidDateTime;
1833
0
}
1834
1835
inline wxDateTime wxDateTime::GetLastWeekDay(WeekDay weekday,
1836
                                             Month month,
1837
                                             int year)
1838
0
{
1839
0
    wxDateTime dt(*this);
1840
0
1841
0
    return dt.SetToLastWeekDay(weekday, month, year) ? dt : wxInvalidDateTime;
1842
0
}
1843
1844
inline wxDateTime wxDateTime::GetLastMonthDay(Month month, int year) const
1845
0
{
1846
0
    MODIFY_AND_RETURN( SetToLastMonthDay(month, year) );
1847
0
}
1848
1849
inline wxDateTime wxDateTime::GetYearDay(wxDateTime_t yday) const
1850
0
{
1851
0
    MODIFY_AND_RETURN( SetToYearDay(yday) );
1852
0
}
1853
1854
// ----------------------------------------------------------------------------
1855
// wxDateTime comparison
1856
// ----------------------------------------------------------------------------
1857
1858
inline bool wxDateTime::IsEqualTo(const wxDateTime& datetime) const
1859
0
{
1860
0
    return *this == datetime;
1861
0
}
1862
1863
inline bool wxDateTime::IsEarlierThan(const wxDateTime& datetime) const
1864
0
{
1865
0
    return *this < datetime;
1866
0
}
1867
1868
inline bool wxDateTime::IsLaterThan(const wxDateTime& datetime) const
1869
0
{
1870
0
    return *this > datetime;
1871
0
}
1872
1873
inline bool wxDateTime::IsStrictlyBetween(const wxDateTime& t1,
1874
                                          const wxDateTime& t2) const
1875
0
{
1876
    // no need for assert, will be checked by the functions we call
1877
0
    return IsLaterThan(t1) && IsEarlierThan(t2);
1878
0
}
1879
1880
inline bool wxDateTime::IsBetween(const wxDateTime& t1,
1881
                                  const wxDateTime& t2) const
1882
0
{
1883
    // no need for assert, will be checked by the functions we call
1884
0
    return IsEqualTo(t1) || IsEqualTo(t2) || IsStrictlyBetween(t1, t2);
1885
0
}
1886
1887
inline bool wxDateTime::IsSameDate(const wxDateTime& dt) const
1888
0
{
1889
0
    Tm tm1 = GetTm(),
1890
0
       tm2 = dt.GetTm();
1891
1892
0
    return tm1.year == tm2.year &&
1893
0
           tm1.mon == tm2.mon &&
1894
0
           tm1.mday == tm2.mday;
1895
0
}
1896
1897
inline bool wxDateTime::IsSameTime(const wxDateTime& dt) const
1898
0
{
1899
    // notice that we can't do something like this:
1900
    //
1901
    //    m_time % MILLISECONDS_PER_DAY == dt.m_time % MILLISECONDS_PER_DAY
1902
    //
1903
    // because we have also to deal with (possibly) different DST settings!
1904
0
    Tm tm1 = GetTm(),
1905
0
       tm2 = dt.GetTm();
1906
1907
0
    return tm1.hour == tm2.hour &&
1908
0
           tm1.min == tm2.min &&
1909
0
           tm1.sec == tm2.sec &&
1910
0
           tm1.msec == tm2.msec;
1911
0
}
1912
1913
inline bool wxDateTime::IsEqualUpTo(const wxDateTime& dt,
1914
                                    const wxTimeSpan& ts) const
1915
0
{
1916
0
    return IsBetween(dt.Subtract(ts), dt.Add(ts));
1917
0
}
1918
1919
// ----------------------------------------------------------------------------
1920
// wxDateTime arithmetic
1921
// ----------------------------------------------------------------------------
1922
1923
inline wxDateTime wxDateTime::Add(const wxTimeSpan& diff) const
1924
0
{
1925
0
    wxASSERT_MSG( IsValid(), wxT("invalid wxDateTime"));
1926
0
1927
0
    return wxDateTime(m_time + diff.GetValue());
1928
0
}
1929
1930
inline wxDateTime& wxDateTime::Add(const wxTimeSpan& diff)
1931
30
{
1932
30
    wxASSERT_MSG( IsValid(), wxT("invalid wxDateTime"));
1933
1934
30
    m_time += diff.GetValue();
1935
1936
30
    return *this;
1937
30
}
1938
1939
inline wxDateTime& wxDateTime::operator+=(const wxTimeSpan& diff)
1940
0
{
1941
0
    return Add(diff);
1942
0
}
1943
1944
inline wxDateTime wxDateTime::Subtract(const wxTimeSpan& diff) const
1945
0
{
1946
0
    wxASSERT_MSG( IsValid(), wxT("invalid wxDateTime"));
1947
0
1948
0
    return wxDateTime(m_time - diff.GetValue());
1949
0
}
1950
1951
inline wxDateTime& wxDateTime::Subtract(const wxTimeSpan& diff)
1952
0
{
1953
0
    wxASSERT_MSG( IsValid(), wxT("invalid wxDateTime"));
1954
1955
0
    m_time -= diff.GetValue();
1956
1957
0
    return *this;
1958
0
}
1959
1960
inline wxDateTime& wxDateTime::operator-=(const wxTimeSpan& diff)
1961
0
{
1962
0
    return Subtract(diff);
1963
0
}
1964
1965
inline wxTimeSpan wxDateTime::Subtract(const wxDateTime& datetime) const
1966
0
{
1967
0
    wxASSERT_MSG( IsValid() && datetime.IsValid(), wxT("invalid wxDateTime"));
1968
0
1969
0
    return wxTimeSpan(GetValue() - datetime.GetValue());
1970
0
}
1971
1972
inline wxTimeSpan wxDateTime::operator-(const wxDateTime& dt2) const
1973
0
{
1974
0
    return this->Subtract(dt2);
1975
0
}
1976
1977
inline wxDateTime wxDateTime::Add(const wxDateSpan& diff) const
1978
0
{
1979
0
    return wxDateTime(*this).Add(diff);
1980
0
}
1981
1982
inline wxDateTime& wxDateTime::Subtract(const wxDateSpan& diff)
1983
0
{
1984
0
    return Add(diff.Negate());
1985
0
}
1986
1987
inline wxDateTime wxDateTime::Subtract(const wxDateSpan& diff) const
1988
0
{
1989
0
    return wxDateTime(*this).Subtract(diff);
1990
0
}
1991
1992
inline wxDateTime& wxDateTime::operator-=(const wxDateSpan& diff)
1993
0
{
1994
0
    return Subtract(diff);
1995
0
}
1996
1997
inline wxDateTime& wxDateTime::operator+=(const wxDateSpan& diff)
1998
0
{
1999
0
    return Add(diff);
2000
0
}
2001
2002
// ----------------------------------------------------------------------------
2003
// wxDateTime and timezones
2004
// ----------------------------------------------------------------------------
2005
2006
inline wxDateTime
2007
wxDateTime::ToTimezone(const wxDateTime::TimeZone& tz, bool noDST) const
2008
0
{
2009
0
    MODIFY_AND_RETURN( MakeTimezone(tz, noDST) );
2010
0
}
2011
2012
inline wxDateTime
2013
wxDateTime::FromTimezone(const wxDateTime::TimeZone& tz, bool noDST) const
2014
0
{
2015
0
    MODIFY_AND_RETURN( MakeFromTimezone(tz, noDST) );
2016
0
}
2017
2018
// ----------------------------------------------------------------------------
2019
// wxTimeSpan construction
2020
// ----------------------------------------------------------------------------
2021
2022
inline wxTimeSpan::wxTimeSpan(long hours,
2023
                              long minutes,
2024
                              wxLongLong seconds,
2025
                              wxLongLong milliseconds)
2026
30
{
2027
    // assign first to avoid precision loss
2028
30
    m_diff = hours;
2029
30
    m_diff *= 60l;
2030
30
    m_diff += minutes;
2031
30
    m_diff *= 60l;
2032
30
    m_diff += seconds;
2033
30
    m_diff *= 1000l;
2034
30
    m_diff += milliseconds;
2035
30
}
2036
2037
// ----------------------------------------------------------------------------
2038
// wxTimeSpan accessors
2039
// ----------------------------------------------------------------------------
2040
2041
inline wxLongLong wxTimeSpan::GetSeconds() const
2042
0
{
2043
0
    return m_diff / 1000l;
2044
0
}
2045
2046
inline int wxTimeSpan::GetMinutes() const
2047
0
{
2048
    // For compatibility, this method (and the other accessors) return int,
2049
    // even though GetLo() actually returns unsigned long with greater range.
2050
0
    return static_cast<int>((GetSeconds() / 60l).GetLo());
2051
0
}
2052
2053
inline int wxTimeSpan::GetHours() const
2054
0
{
2055
0
    return GetMinutes() / 60;
2056
0
}
2057
2058
inline int wxTimeSpan::GetDays() const
2059
0
{
2060
0
    return GetHours() / 24;
2061
0
}
2062
2063
inline int wxTimeSpan::GetWeeks() const
2064
0
{
2065
0
    return GetDays() / 7;
2066
0
}
2067
2068
// ----------------------------------------------------------------------------
2069
// wxTimeSpan arithmetic
2070
// ----------------------------------------------------------------------------
2071
2072
inline wxTimeSpan wxTimeSpan::Add(const wxTimeSpan& diff) const
2073
0
{
2074
0
    return wxTimeSpan(m_diff + diff.GetValue());
2075
0
}
2076
2077
inline wxTimeSpan& wxTimeSpan::Add(const wxTimeSpan& diff)
2078
0
{
2079
0
    m_diff += diff.GetValue();
2080
0
2081
0
    return *this;
2082
0
}
2083
2084
inline wxTimeSpan wxTimeSpan::Subtract(const wxTimeSpan& diff) const
2085
0
{
2086
0
    return wxTimeSpan(m_diff - diff.GetValue());
2087
0
}
2088
2089
inline wxTimeSpan& wxTimeSpan::Subtract(const wxTimeSpan& diff)
2090
0
{
2091
0
    m_diff -= diff.GetValue();
2092
0
2093
0
    return *this;
2094
0
}
2095
2096
inline wxTimeSpan& wxTimeSpan::Multiply(int n)
2097
0
{
2098
0
    m_diff *= (long)n;
2099
2100
0
    return *this;
2101
0
}
2102
2103
inline wxTimeSpan wxTimeSpan::Multiply(int n) const
2104
0
{
2105
0
    return wxTimeSpan(m_diff * (long)n);
2106
0
}
2107
2108
inline wxTimeSpan wxTimeSpan::Abs() const
2109
0
{
2110
0
    return wxTimeSpan(GetValue().Abs());
2111
0
}
2112
2113
inline bool wxTimeSpan::IsEqualTo(const wxTimeSpan& ts) const
2114
0
{
2115
0
    return GetValue() == ts.GetValue();
2116
0
}
2117
2118
inline bool wxTimeSpan::IsLongerThan(const wxTimeSpan& ts) const
2119
0
{
2120
0
    return GetValue().Abs() > ts.GetValue().Abs();
2121
0
}
2122
2123
inline bool wxTimeSpan::IsShorterThan(const wxTimeSpan& ts) const
2124
0
{
2125
0
    return GetValue().Abs() < ts.GetValue().Abs();
2126
0
}
2127
2128
// ----------------------------------------------------------------------------
2129
// wxDateSpan
2130
// ----------------------------------------------------------------------------
2131
2132
inline wxDateSpan& wxDateSpan::operator+=(const wxDateSpan& other)
2133
0
{
2134
0
    m_years += other.m_years;
2135
0
    m_months += other.m_months;
2136
0
    m_weeks += other.m_weeks;
2137
0
    m_days += other.m_days;
2138
0
2139
0
    return *this;
2140
0
}
2141
2142
inline wxDateSpan& wxDateSpan::Add(const wxDateSpan& other)
2143
0
{
2144
0
    return *this += other;
2145
0
}
2146
2147
inline wxDateSpan wxDateSpan::Add(const wxDateSpan& other) const
2148
0
{
2149
0
    wxDateSpan ds(*this);
2150
0
    ds.Add(other);
2151
0
    return ds;
2152
0
}
2153
2154
inline wxDateSpan& wxDateSpan::Multiply(int factor)
2155
0
{
2156
0
    m_years *= factor;
2157
0
    m_months *= factor;
2158
0
    m_weeks *= factor;
2159
0
    m_days *= factor;
2160
2161
0
    return *this;
2162
0
}
2163
2164
inline wxDateSpan wxDateSpan::Multiply(int factor) const
2165
0
{
2166
0
    wxDateSpan ds(*this);
2167
0
    ds.Multiply(factor);
2168
0
    return ds;
2169
0
}
2170
2171
inline wxDateSpan wxDateSpan::Negate() const
2172
0
{
2173
0
    return wxDateSpan(-m_years, -m_months, -m_weeks, -m_days);
2174
0
}
2175
2176
inline wxDateSpan& wxDateSpan::Neg()
2177
0
{
2178
0
    m_years = -m_years;
2179
0
    m_months = -m_months;
2180
0
    m_weeks = -m_weeks;
2181
0
    m_days = -m_days;
2182
0
2183
0
    return *this;
2184
0
}
2185
2186
inline wxDateSpan& wxDateSpan::operator-=(const wxDateSpan& other)
2187
0
{
2188
0
    return *this += other.Negate();
2189
0
}
2190
2191
inline wxDateSpan& wxDateSpan::Subtract(const wxDateSpan& other)
2192
0
{
2193
0
    return *this -= other;
2194
0
}
2195
2196
inline wxDateSpan wxDateSpan::Subtract(const wxDateSpan& other) const
2197
0
{
2198
0
    wxDateSpan ds(*this);
2199
0
    ds.Subtract(other);
2200
0
    return ds;
2201
0
}
2202
2203
#undef MILLISECONDS_PER_DAY
2204
2205
#undef MODIFY_AND_RETURN
2206
2207
// ============================================================================
2208
// other helper functions
2209
// ============================================================================
2210
2211
// ----------------------------------------------------------------------------
2212
// iteration helpers: can be used to write a for loop over enum variable like
2213
// this:
2214
//  for ( m = wxDateTime::Jan; m < wxDateTime::Inv_Month; wxNextMonth(m) )
2215
// ----------------------------------------------------------------------------
2216
2217
WXDLLIMPEXP_BASE void wxNextMonth(wxDateTime::Month& m);
2218
WXDLLIMPEXP_BASE void wxPrevMonth(wxDateTime::Month& m);
2219
WXDLLIMPEXP_BASE void wxNextWDay(wxDateTime::WeekDay& wd);
2220
WXDLLIMPEXP_BASE void wxPrevWDay(wxDateTime::WeekDay& wd);
2221
2222
#endif // wxUSE_DATETIME
2223
2224
#endif // _WX_DATETIME_H