1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qplatformdefs.h"
43 #include "private/qdatetime_p.h"
44
45 #include "qdatastream.h"
46 #include "qset.h"
47 #include "qlocale.h"
48 #include "qdatetime.h"
49 #include "qregexp.h"
50 #include "qdebug.h"
51 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
52 #include <qt_windows.h>
53 #endif
54 #ifndef Q_WS_WIN
55 #include <locale.h>
56 #endif
57
58 #include <time.h>
59 #if defined(Q_OS_WINCE)
60 #include "qfunctions_wince.h"
61 #endif
62
63 //#define QDATETIMEPARSER_DEBUG
64 #if defined (QDATETIMEPARSER_DEBUG) && !defined(QT_NO_DEBUG_STREAM)
65 # define QDTPDEBUG qDebug() << QString("%1:%2").arg(__FILE__).arg(__LINE__)
66 # define QDTPDEBUGN qDebug
67 #else
68 # define QDTPDEBUG if (false) qDebug()
69 # define QDTPDEBUGN if (false) qDebug
70 #endif
71
72 #if defined(Q_WS_MAC)
73 #include <private/qcore_mac_p.h>
74 #endif
75
76 #if defined(Q_OS_SYMBIAN)
77 #include <e32std.h>
78 #include <tz.h>
79 #endif
80
81 QT_BEGIN_NAMESPACE
82
83 enum {
84 FIRST_YEAR = -4713,
85 FIRST_MONTH = 1,
86 FIRST_DAY = 2, // ### Qt 5: make FIRST_DAY = 1, by support jd == 0 as valid
87 SECS_PER_DAY = 86400,
88 MSECS_PER_DAY = 86400000,
89 SECS_PER_HOUR = 3600,
90 MSECS_PER_HOUR = 3600000,
91 SECS_PER_MIN = 60,
92 MSECS_PER_MIN = 60000,
93 JULIAN_DAY_FOR_EPOCH = 2440588 // result of julianDayFromGregorianDate(1970, 1, 1)
94 };
95
fixedDate(int y,int m,int d)96 static inline QDate fixedDate(int y, int m, int d)
97 {
98 QDate result(y, m, 1);
99 result.setDate(y, m, qMin(d, result.daysInMonth()));
100 return result;
101 }
102
julianDayFromGregorianDate(int year,int month,int day)103 static inline uint julianDayFromGregorianDate(int year, int month, int day)
104 {
105 // Gregorian calendar starting from October 15, 1582
106 // Algorithm from Henry F. Fliegel and Thomas C. Van Flandern
107 return (1461 * (year + 4800 + (month - 14) / 12)) / 4
108 + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12
109 - (3 * ((year + 4900 + (month - 14) / 12) / 100)) / 4
110 + day - 32075;
111 }
112
julianDayFromDate(int year,int month,int day)113 static uint julianDayFromDate(int year, int month, int day)
114 {
115 if (year < 0)
116 ++year;
117
118 if (year > 1582 || (year == 1582 && (month > 10 || (month == 10 && day >= 15)))) {
119 return julianDayFromGregorianDate(year, month, day);
120 } else if (year < 1582 || (year == 1582 && (month < 10 || (month == 10 && day <= 4)))) {
121 // Julian calendar until October 4, 1582
122 // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
123 int a = (14 - month) / 12;
124 return (153 * (month + (12 * a) - 3) + 2) / 5
125 + (1461 * (year + 4800 - a)) / 4
126 + day - 32083;
127 } else {
128 // the day following October 4, 1582 is October 15, 1582
129 return 0;
130 }
131 }
132
getDateFromJulianDay(uint julianDay,int * year,int * month,int * day)133 static void getDateFromJulianDay(uint julianDay, int *year, int *month, int *day)
134 {
135 int y, m, d;
136
137 if (julianDay >= 2299161) {
138 // Gregorian calendar starting from October 15, 1582
139 // This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern
140 qulonglong ell, n, i, j;
141 ell = qulonglong(julianDay) + 68569;
142 n = (4 * ell) / 146097;
143 ell = ell - (146097 * n + 3) / 4;
144 i = (4000 * (ell + 1)) / 1461001;
145 ell = ell - (1461 * i) / 4 + 31;
146 j = (80 * ell) / 2447;
147 d = ell - (2447 * j) / 80;
148 ell = j / 11;
149 m = j + 2 - (12 * ell);
150 y = 100 * (n - 49) + i + ell;
151 } else {
152 // Julian calendar until October 4, 1582
153 // Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
154 julianDay += 32082;
155 int dd = (4 * julianDay + 3) / 1461;
156 int ee = julianDay - (1461 * dd) / 4;
157 int mm = ((5 * ee) + 2) / 153;
158 d = ee - (153 * mm + 2) / 5 + 1;
159 m = mm + 3 - 12 * (mm / 10);
160 y = dd - 4800 + (mm / 10);
161 if (y <= 0)
162 --y;
163 }
164 if (year)
165 *year = y;
166 if (month)
167 *month = m;
168 if (day)
169 *day = d;
170 }
171
172
173 static const char monthDays[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
174
175 #ifndef QT_NO_TEXTDATE
176 static const char * const qt_shortMonthNames[] = {
177 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
178 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
179 #endif
180 #ifndef QT_NO_DATESTRING
181 static QString fmtDateTime(const QString& f, const QTime* dt = 0, const QDate* dd = 0);
182 #endif
183
184 /*****************************************************************************
185 QDate member functions
186 *****************************************************************************/
187
188 /*!
189 \since 4.5
190
191 \enum QDate::MonthNameType
192
193 This enum describes the types of the string representation used
194 for the month name.
195
196 \value DateFormat This type of name can be used for date-to-string formatting.
197 \value StandaloneFormat This type is used when you need to enumerate months or weekdays.
198 Usually standalone names are represented in singular forms with
199 capitalized first letter.
200 */
201
202 /*!
203 \class QDate
204 \reentrant
205 \brief The QDate class provides date functions.
206
207
208 A QDate object contains a calendar date, i.e. year, month, and day
209 numbers, in the Gregorian calendar. (see \l{QDate G and J} {Use of
210 Gregorian and Julian Calendars} for dates prior to 15 October
211 1582). It can read the current date from the system clock. It
212 provides functions for comparing dates, and for manipulating
213 dates. For example, it is possible to add and subtract days,
214 months, and years to dates.
215
216 A QDate object is typically created either by giving the year,
217 month, and day numbers explicitly. Note that QDate interprets two
218 digit years as is, i.e., years 0 - 99. A QDate can also be
219 constructed with the static function currentDate(), which creates
220 a QDate object containing the system clock's date. An explicit
221 date can also be set using setDate(). The fromString() function
222 returns a QDate given a string and a date format which is used to
223 interpret the date within the string.
224
225 The year(), month(), and day() functions provide access to the
226 year, month, and day numbers. Also, dayOfWeek() and dayOfYear()
227 functions are provided. The same information is provided in
228 textual format by the toString(), shortDayName(), longDayName(),
229 shortMonthName(), and longMonthName() functions.
230
231 QDate provides a full set of operators to compare two QDate
232 objects where smaller means earlier, and larger means later.
233
234 You can increment (or decrement) a date by a given number of days
235 using addDays(). Similarly you can use addMonths() and addYears().
236 The daysTo() function returns the number of days between two
237 dates.
238
239 The daysInMonth() and daysInYear() functions return how many days
240 there are in this date's month and year, respectively. The
241 isLeapYear() function indicates whether a date is in a leap year.
242
243 \section1
244
245 \target QDate G and J
246 \section2 Use of Gregorian and Julian Calendars
247
248 QDate uses the Gregorian calendar in all locales, beginning
249 on the date 15 October 1582. For dates up to and including 4
250 October 1582, the Julian calendar is used. This means there is a
251 10-day gap in the internal calendar between the 4th and the 15th
252 of October 1582. When you use QDateTime for dates in that epoch,
253 the day after 4 October 1582 is 15 October 1582, and the dates in
254 the gap are invalid.
255
256 The Julian to Gregorian changeover date used here is the date when
257 the Gregorian calendar was first introduced, by Pope Gregory
258 XIII. That change was not universally accepted and some localities
259 only executed it at a later date (if at all). QDateTime
260 doesn't take any of these historical facts into account. If an
261 application must support a locale-specific dating system, it must
262 do so on its own, remembering to convert the dates using the
263 Julian day.
264
265 \section2 No Year 0
266
267 There is no year 0. Dates in that year are considered invalid. The
268 year -1 is the year "1 before Christ" or "1 before current era."
269 The day before 0001-01-01 is December 31st, 1 BCE.
270
271 \section2 Range of Valid Dates
272
273 The range of valid dates is from January 2nd, 4713 BCE, to
274 sometime in the year 11 million CE. The Julian Day returned by
275 QDate::toJulianDay() is a number in the contiguous range from 1 to
276 \e{overflow}, even across QDateTime's "date holes". It is suitable
277 for use in applications that must convert a QDateTime to a date in
278 another calendar system, e.g., Hebrew, Islamic or Chinese.
279
280 \sa QTime, QDateTime, QDateEdit, QDateTimeEdit, QCalendarWidget
281 */
282
283 /*!
284 \fn QDate::QDate()
285
286 Constructs a null date. Null dates are invalid.
287
288 \sa isNull(), isValid()
289 */
290
291 /*!
292 Constructs a date with year \a y, month \a m and day \a d.
293
294 If the specified date is invalid, the date is not set and
295 isValid() returns false. A date before 2 January 4713 B.C. is
296 considered invalid.
297
298 \warning Years 0 to 99 are interpreted as is, i.e., years
299 0-99.
300
301 \sa isValid()
302 */
303
QDate(int y,int m,int d)304 QDate::QDate(int y, int m, int d)
305 {
306 setDate(y, m, d);
307 }
308
309
310 /*!
311 \fn bool QDate::isNull() const
312
313 Returns true if the date is null; otherwise returns false. A null
314 date is invalid.
315
316 \note The behavior of this function is equivalent to isValid().
317
318 \sa isValid()
319 */
320
321
322 /*!
323 Returns true if this date is valid; otherwise returns false.
324
325 \sa isNull()
326 */
327
isValid() const328 bool QDate::isValid() const
329 {
330 return !isNull();
331 }
332
333
334 /*!
335 Returns the year of this date. Negative numbers indicate years
336 before 1 A.D. = 1 C.E., such that year -44 is 44 B.C.
337
338 \sa month(), day()
339 */
340
year() const341 int QDate::year() const
342 {
343 int y;
344 getDateFromJulianDay(jd, &y, 0, 0);
345 return y;
346 }
347
348 /*!
349 Returns the number corresponding to the month of this date, using
350 the following convention:
351
352 \list
353 \i 1 = "January"
354 \i 2 = "February"
355 \i 3 = "March"
356 \i 4 = "April"
357 \i 5 = "May"
358 \i 6 = "June"
359 \i 7 = "July"
360 \i 8 = "August"
361 \i 9 = "September"
362 \i 10 = "October"
363 \i 11 = "November"
364 \i 12 = "December"
365 \endlist
366
367 \sa year(), day()
368 */
369
month() const370 int QDate::month() const
371 {
372 int m;
373 getDateFromJulianDay(jd, 0, &m, 0);
374 return m;
375 }
376
377 /*!
378 Returns the day of the month (1 to 31) of this date.
379
380 \sa year(), month(), dayOfWeek()
381 */
382
day() const383 int QDate::day() const
384 {
385 int d;
386 getDateFromJulianDay(jd, 0, 0, &d);
387 return d;
388 }
389
390 /*!
391 Returns the weekday (1 = Monday to 7 = Sunday) for this date.
392
393 \sa day(), dayOfYear(), Qt::DayOfWeek
394 */
395
dayOfWeek() const396 int QDate::dayOfWeek() const
397 {
398 return (jd % 7) + 1;
399 }
400
401 /*!
402 Returns the day of the year (1 to 365 or 366 on leap years) for
403 this date.
404
405 \sa day(), dayOfWeek()
406 */
407
dayOfYear() const408 int QDate::dayOfYear() const
409 {
410 return jd - julianDayFromDate(year(), 1, 1) + 1;
411 }
412
413 /*!
414 Returns the number of days in the month (28 to 31) for this date.
415
416 \sa day(), daysInYear()
417 */
418
daysInMonth() const419 int QDate::daysInMonth() const
420 {
421 int y, m, d;
422 getDateFromJulianDay(jd, &y, &m, &d);
423 if (m == 2 && isLeapYear(y))
424 return 29;
425 else
426 return monthDays[m];
427 }
428
429 /*!
430 Returns the number of days in the year (365 or 366) for this date.
431
432 \sa day(), daysInMonth()
433 */
434
daysInYear() const435 int QDate::daysInYear() const
436 {
437 int y, m, d;
438 getDateFromJulianDay(jd, &y, &m, &d);
439 return isLeapYear(y) ? 366 : 365;
440 }
441
442 /*!
443 Returns the week number (1 to 53), and stores the year in
444 *\a{yearNumber} unless \a yearNumber is null (the default).
445
446 Returns 0 if the date is invalid.
447
448 In accordance with ISO 8601, weeks start on Monday and the first
449 Thursday of a year is always in week 1 of that year. Most years
450 have 52 weeks, but some have 53.
451
452 *\a{yearNumber} is not always the same as year(). For example, 1
453 January 2000 has week number 52 in the year 1999, and 31 December
454 2002 has week number 1 in the year 2003.
455
456 \sa isValid()
457 */
458
weekNumber(int * yearNumber) const459 int QDate::weekNumber(int *yearNumber) const
460 {
461 if (!isValid())
462 return 0;
463
464 int year = QDate::year();
465 int yday = dayOfYear();
466 int wday = dayOfWeek();
467
468 int week = (yday - wday + 10) / 7;
469
470 if (week == 0) {
471 // last week of previous year
472 --year;
473 week = (yday + 365 + (QDate::isLeapYear(year) ? 1 : 0) - wday + 10) / 7;
474 Q_ASSERT(week == 52 || week == 53);
475 } else if (week == 53) {
476 // maybe first week of next year
477 int w = (yday - 365 - (QDate::isLeapYear(year + 1) ? 1 : 0) - wday + 10) / 7;
478 if (w > 0) {
479 ++year;
480 week = w;
481 }
482 Q_ASSERT(week == 53 || week == 1);
483 }
484
485 if (yearNumber != 0)
486 *yearNumber = year;
487 return week;
488 }
489
490 #ifndef QT_NO_TEXTDATE
491 /*!
492 \since 4.5
493
494 Returns the short name of the \a month for the representation specified
495 by \a type.
496
497 The months are enumerated using the following convention:
498
499 \list
500 \i 1 = "Jan"
501 \i 2 = "Feb"
502 \i 3 = "Mar"
503 \i 4 = "Apr"
504 \i 5 = "May"
505 \i 6 = "Jun"
506 \i 7 = "Jul"
507 \i 8 = "Aug"
508 \i 9 = "Sep"
509 \i 10 = "Oct"
510 \i 11 = "Nov"
511 \i 12 = "Dec"
512 \endlist
513
514 The month names will be localized according to the system's default
515 locale settings.
516
517 \sa toString(), longMonthName(), shortDayName(), longDayName()
518 */
519
shortMonthName(int month,QDate::MonthNameType type)520 QString QDate::shortMonthName(int month, QDate::MonthNameType type)
521 {
522 if (month < 1 || month > 12) {
523 month = 1;
524 }
525 switch (type) {
526 case QDate::DateFormat:
527 return QLocale::system().monthName(month, QLocale::ShortFormat);
528 case QDate::StandaloneFormat:
529 return QLocale::system().standaloneMonthName(month, QLocale::ShortFormat);
530 default:
531 break;
532 }
533 return QString();
534 }
535
536 /*!
537 Returns the short version of the name of the \a month. The
538 returned name is in normal type which can be used for date formatting.
539
540 \sa toString(), longMonthName(), shortDayName(), longDayName()
541 */
542
shortMonthName(int month)543 QString QDate::shortMonthName(int month)
544 {
545 return shortMonthName(month, QDate::DateFormat);
546 }
547
548 /*!
549 \since 4.5
550
551 Returns the long name of the \a month for the representation specified
552 by \a type.
553
554 The months are enumerated using the following convention:
555
556 \list
557 \i 1 = "January"
558 \i 2 = "February"
559 \i 3 = "March"
560 \i 4 = "April"
561 \i 5 = "May"
562 \i 6 = "June"
563 \i 7 = "July"
564 \i 8 = "August"
565 \i 9 = "September"
566 \i 10 = "October"
567 \i 11 = "November"
568 \i 12 = "December"
569 \endlist
570
571 The month names will be localized according to the system's default
572 locale settings.
573
574 \sa toString(), shortMonthName(), shortDayName(), longDayName()
575 */
576
longMonthName(int month,MonthNameType type)577 QString QDate::longMonthName(int month, MonthNameType type)
578 {
579 if (month < 1 || month > 12) {
580 month = 1;
581 }
582 switch (type) {
583 case QDate::DateFormat:
584 return QLocale::system().monthName(month, QLocale::LongFormat);
585 case QDate::StandaloneFormat:
586 return QLocale::system().standaloneMonthName(month, QLocale::LongFormat);
587 default:
588 break;
589 }
590 return QString();
591 }
592
593 /*!
594 Returns the long version of the name of the \a month. The
595 returned name is in normal type which can be used for date formatting.
596
597 \sa toString(), shortMonthName(), shortDayName(), longDayName()
598 */
599
longMonthName(int month)600 QString QDate::longMonthName(int month)
601 {
602 if (month < 1 || month > 12) {
603 month = 1;
604 }
605 return QLocale::system().monthName(month, QLocale::LongFormat);
606 }
607
608 /*!
609 \since 4.5
610
611 Returns the short name of the \a weekday for the representation specified
612 by \a type.
613
614 The days are enumerated using the following convention:
615
616 \list
617 \i 1 = "Mon"
618 \i 2 = "Tue"
619 \i 3 = "Wed"
620 \i 4 = "Thu"
621 \i 5 = "Fri"
622 \i 6 = "Sat"
623 \i 7 = "Sun"
624 \endlist
625
626 The day names will be localized according to the system's default
627 locale settings.
628
629 \sa toString(), shortMonthName(), longMonthName(), longDayName()
630 */
631
shortDayName(int weekday,MonthNameType type)632 QString QDate::shortDayName(int weekday, MonthNameType type)
633 {
634 if (weekday < 1 || weekday > 7) {
635 weekday = 1;
636 }
637 switch (type) {
638 case QDate::DateFormat:
639 return QLocale::system().dayName(weekday, QLocale::ShortFormat);
640 case QDate::StandaloneFormat:
641 return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat);
642 default:
643 break;
644 }
645 return QString();
646 }
647
648 /*!
649 Returns the short version of the name of the \a weekday. The
650 returned name is in normal type which can be used for date formatting.
651
652 \sa toString(), longDayName(), shortMonthName(), longMonthName()
653 */
654
shortDayName(int weekday)655 QString QDate::shortDayName(int weekday)
656 {
657 if (weekday < 1 || weekday > 7) {
658 weekday = 1;
659 }
660 return QLocale::system().dayName(weekday, QLocale::ShortFormat);
661 }
662
663 /*!
664 \since 4.5
665
666 Returns the long name of the \a weekday for the representation specified
667 by \a type.
668
669 The days are enumerated using the following convention:
670
671 \list
672 \i 1 = "Monday"
673 \i 2 = "Tuesday"
674 \i 3 = "Wednesday"
675 \i 4 = "Thursday"
676 \i 5 = "Friday"
677 \i 6 = "Saturday"
678 \i 7 = "Sunday"
679 \endlist
680
681 The day names will be localized according to the system's default
682 locale settings.
683
684 \sa toString(), shortDayName(), shortMonthName(), longMonthName()
685 */
686
longDayName(int weekday,MonthNameType type)687 QString QDate::longDayName(int weekday, MonthNameType type)
688 {
689 if (weekday < 1 || weekday > 7) {
690 weekday = 1;
691 }
692 switch (type) {
693 case QDate::DateFormat:
694 return QLocale::system().dayName(weekday, QLocale::LongFormat);
695 case QDate::StandaloneFormat:
696 return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat);
697 default:
698 break;
699 }
700 return QLocale::system().dayName(weekday, QLocale::LongFormat);
701 }
702
703 /*!
704 Returns the long version of the name of the \a weekday. The
705 returned name is in normal type which can be used for date formatting.
706
707 \sa toString(), shortDayName(), shortMonthName(), longMonthName()
708 */
709
longDayName(int weekday)710 QString QDate::longDayName(int weekday)
711 {
712 if (weekday < 1 || weekday > 7) {
713 weekday = 1;
714 }
715 return QLocale::system().dayName(weekday, QLocale::LongFormat);
716 }
717 #endif //QT_NO_TEXTDATE
718
719 #ifndef QT_NO_DATESTRING
720
721 /*!
722 \fn QString QDate::toString(Qt::DateFormat format) const
723
724 \overload
725
726 Returns the date as a string. The \a format parameter determines
727 the format of the string.
728
729 If the \a format is Qt::TextDate, the string is formatted in
730 the default way. QDate::shortDayName() and QDate::shortMonthName()
731 are used to generate the string, so the day and month names will
732 be localized names using the default locale from the system. An
733 example of this formatting is "Sat May 20 1995".
734
735 If the \a format is Qt::ISODate, the string format corresponds
736 to the ISO 8601 extended specification for representations of
737 dates and times, taking the form YYYY-MM-DD, where YYYY is the
738 year, MM is the month of the year (between 01 and 12), and DD is
739 the day of the month between 01 and 31.
740
741 If the \a format is Qt::SystemLocaleShortDate or
742 Qt::SystemLocaleLongDate, the string format depends on the locale
743 settings of the system. Identical to calling
744 QLocale::system().toString(date, QLocale::ShortFormat) or
745 QLocale::system().toString(date, QLocale::LongFormat).
746
747 If the \a format is Qt::DefaultLocaleShortDate or
748 Qt::DefaultLocaleLongDate, the string format depends on the
749 default application locale. This is the locale set with
750 QLocale::setDefault(), or the system locale if no default locale
751 has been set. Identical to calling QLocale().toString(date,
752 QLocale::ShortFormat) or QLocale().toString(date,
753 QLocale::LongFormat).
754
755 If the date is invalid, an empty string will be returned.
756
757 \warning The Qt::ISODate format is only valid for years in the
758 range 0 to 9999. This restriction may apply to locale-aware
759 formats as well, depending on the locale settings.
760
761 \sa shortDayName(), shortMonthName()
762 */
toString(Qt::DateFormat f) const763 QString QDate::toString(Qt::DateFormat f) const
764 {
765 if (!isValid())
766 return QString();
767 int y, m, d;
768 getDateFromJulianDay(jd, &y, &m, &d);
769 switch (f) {
770 case Qt::SystemLocaleDate:
771 case Qt::SystemLocaleShortDate:
772 case Qt::SystemLocaleLongDate:
773 return QLocale::system().toString(*this, f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
774 : QLocale::ShortFormat);
775 case Qt::LocaleDate:
776 case Qt::DefaultLocaleShortDate:
777 case Qt::DefaultLocaleLongDate:
778 return QLocale().toString(*this, f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
779 : QLocale::ShortFormat);
780 default:
781 #ifndef QT_NO_TEXTDATE
782 case Qt::TextDate:
783 {
784 return QString::fromLatin1("%0 %1 %2 %3")
785 .arg(shortDayName(dayOfWeek()))
786 .arg(shortMonthName(m))
787 .arg(d)
788 .arg(y);
789 }
790 #endif
791 case Qt::ISODate:
792 {
793 if (year() < 0 || year() > 9999)
794 return QString();
795 QString month(QString::number(m).rightJustified(2, QLatin1Char('0')));
796 QString day(QString::number(d).rightJustified(2, QLatin1Char('0')));
797 return QString::number(y) + QLatin1Char('-') + month + QLatin1Char('-') + day;
798 }
799 }
800 }
801
802 /*!
803 Returns the date as a string. The \a format parameter determines
804 the format of the result string.
805
806 These expressions may be used:
807
808 \table
809 \header \i Expression \i Output
810 \row \i d \i the day as number without a leading zero (1 to 31)
811 \row \i dd \i the day as number with a leading zero (01 to 31)
812 \row \i ddd
813 \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
814 Uses QDate::shortDayName().
815 \row \i dddd
816 \i the long localized day name (e.g. 'Monday' to 'Sunday').
817 Uses QDate::longDayName().
818 \row \i M \i the month as number without a leading zero (1 to 12)
819 \row \i MM \i the month as number with a leading zero (01 to 12)
820 \row \i MMM
821 \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
822 Uses QDate::shortMonthName().
823 \row \i MMMM
824 \i the long localized month name (e.g. 'January' to 'December').
825 Uses QDate::longMonthName().
826 \row \i yy \i the year as two digit number (00 to 99)
827 \row \i yyyy \i the year as four digit number. If the year is negative,
828 a minus sign is prepended in addition.
829 \endtable
830
831 All other input characters will be ignored. Any sequence of characters that
832 are enclosed in singlequotes will be treated as text and not be used as an
833 expression. Two consecutive singlequotes ("''") are replaced by a singlequote
834 in the output.
835
836 Example format strings (assuming that the QDate is the 20 July
837 1969):
838
839 \table
840 \header \o Format \o Result
841 \row \o dd.MM.yyyy \o 20.07.1969
842 \row \o ddd MMMM d yy \o Sun July 20 69
843 \row \o 'The day is' dddd \o The day is Sunday
844 \endtable
845
846 If the datetime is invalid, an empty string will be returned.
847
848 \warning The Qt::ISODate format is only valid for years in the
849 range 0 to 9999. This restriction may apply to locale-aware
850 formats as well, depending on the locale settings.
851
852 \sa QDateTime::toString() QTime::toString()
853
854 */
toString(const QString & format) const855 QString QDate::toString(const QString& format) const
856 {
857 if (year() > 9999)
858 return QString();
859 return fmtDateTime(format, 0, this);
860 }
861 #endif //QT_NO_DATESTRING
862
863 /*!
864 \obsolete
865
866 Sets the date's year \a y, month \a m, and day \a d.
867
868 If \a y is in the range 0 to 99, it is interpreted as 1900 to
869 1999.
870
871 Use setDate() instead.
872 */
873
setYMD(int y,int m,int d)874 bool QDate::setYMD(int y, int m, int d)
875 {
876 if (uint(y) <= 99)
877 y += 1900;
878 return setDate(y, m, d);
879 }
880
881 /*!
882 \since 4.2
883
884 Sets the date's \a year, \a month, and \a day. Returns true if
885 the date is valid; otherwise returns false.
886
887 If the specified date is invalid, the QDate object is set to be
888 invalid. Any date before 2 January 4713 B.C. is considered
889 invalid.
890
891 \sa isValid()
892 */
setDate(int year,int month,int day)893 bool QDate::setDate(int year, int month, int day)
894 {
895 if (!isValid(year, month, day)) {
896 jd = 0;
897 } else {
898 jd = julianDayFromDate(year, month, day);
899 }
900 return jd != 0;
901 }
902
903 /*!
904 \since 4.5
905
906 Extracts the date's year, month, and day, and assigns them to
907 *\a year, *\a month, and *\a day. The pointers may be null.
908
909 \sa year(), month(), day(), isValid()
910 */
getDate(int * year,int * month,int * day)911 void QDate::getDate(int *year, int *month, int *day)
912 {
913 getDateFromJulianDay(jd, year, month, day);
914 }
915
916 /*!
917 Returns a QDate object containing a date \a ndays later than the
918 date of this object (or earlier if \a ndays is negative).
919
920 \sa addMonths() addYears() daysTo()
921 */
922
addDays(int ndays) const923 QDate QDate::addDays(int ndays) const
924 {
925 QDate d;
926 // this is basically "d.jd = jd + ndays" with checks for integer overflow
927 if (ndays >= 0)
928 d.jd = (jd + ndays >= jd) ? jd + ndays : 0;
929 else
930 d.jd = (jd + ndays < jd) ? jd + ndays : 0;
931 return d;
932 }
933
934 /*!
935 Returns a QDate object containing a date \a nmonths later than the
936 date of this object (or earlier if \a nmonths is negative).
937
938 \note If the ending day/month combination does not exist in the
939 resulting month/year, this function will return a date that is the
940 latest valid date.
941
942 \warning QDate has a date hole around the days introducing the
943 Gregorian calendar (the days 5 to 14 October 1582, inclusive, do
944 not exist). If the calculation ends in one of those days, QDate
945 will return either October 4 or October 15.
946
947 \sa addDays() addYears()
948 */
949
addMonths(int nmonths) const950 QDate QDate::addMonths(int nmonths) const
951 {
952 if (!isValid())
953 return QDate();
954 if (!nmonths)
955 return *this;
956
957 int old_y, y, m, d;
958 getDateFromJulianDay(jd, &y, &m, &d);
959 old_y = y;
960
961 bool increasing = nmonths > 0;
962
963 while (nmonths != 0) {
964 if (nmonths < 0 && nmonths + 12 <= 0) {
965 y--;
966 nmonths+=12;
967 } else if (nmonths < 0) {
968 m+= nmonths;
969 nmonths = 0;
970 if (m <= 0) {
971 --y;
972 m += 12;
973 }
974 } else if (nmonths - 12 >= 0) {
975 y++;
976 nmonths -= 12;
977 } else if (m == 12) {
978 y++;
979 m = 0;
980 } else {
981 m += nmonths;
982 nmonths = 0;
983 if (m > 12) {
984 ++y;
985 m -= 12;
986 }
987 }
988 }
989
990 // was there a sign change?
991 if ((old_y > 0 && y <= 0) ||
992 (old_y < 0 && y >= 0))
993 // yes, adjust the date by +1 or -1 years
994 y += increasing ? +1 : -1;
995
996 // did we end up in the Gregorian/Julian conversion hole?
997 if (y == 1582 && m == 10 && d > 4 && d < 15)
998 d = increasing ? 15 : 4;
999
1000 return fixedDate(y, m, d);
1001 }
1002
1003 /*!
1004 Returns a QDate object containing a date \a nyears later than the
1005 date of this object (or earlier if \a nyears is negative).
1006
1007 \note If the ending day/month combination does not exist in the
1008 resulting year (i.e., if the date was Feb 29 and the final year is
1009 not a leap year), this function will return a date that is the
1010 latest valid date (that is, Feb 28).
1011
1012 \sa addDays(), addMonths()
1013 */
1014
addYears(int nyears) const1015 QDate QDate::addYears(int nyears) const
1016 {
1017 if (!isValid())
1018 return QDate();
1019
1020 int y, m, d;
1021 getDateFromJulianDay(jd, &y, &m, &d);
1022
1023 int old_y = y;
1024 y += nyears;
1025
1026 // was there a sign change?
1027 if ((old_y > 0 && y <= 0) ||
1028 (old_y < 0 && y >= 0))
1029 // yes, adjust the date by +1 or -1 years
1030 y += nyears > 0 ? +1 : -1;
1031
1032 return fixedDate(y, m, d);
1033 }
1034
1035 /*!
1036 Returns the number of days from this date to \a d (which is
1037 negative if \a d is earlier than this date).
1038
1039 Example:
1040 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 0
1041
1042 \sa addDays()
1043 */
1044
daysTo(const QDate & d) const1045 int QDate::daysTo(const QDate &d) const
1046 {
1047 return d.jd - jd;
1048 }
1049
1050
1051 /*!
1052 \fn bool QDate::operator==(const QDate &d) const
1053
1054 Returns true if this date is equal to \a d; otherwise returns
1055 false.
1056
1057 */
1058
1059 /*!
1060 \fn bool QDate::operator!=(const QDate &d) const
1061
1062 Returns true if this date is different from \a d; otherwise
1063 returns false.
1064 */
1065
1066 /*!
1067 \fn bool QDate::operator<(const QDate &d) const
1068
1069 Returns true if this date is earlier than \a d; otherwise returns
1070 false.
1071 */
1072
1073 /*!
1074 \fn bool QDate::operator<=(const QDate &d) const
1075
1076 Returns true if this date is earlier than or equal to \a d;
1077 otherwise returns false.
1078 */
1079
1080 /*!
1081 \fn bool QDate::operator>(const QDate &d) const
1082
1083 Returns true if this date is later than \a d; otherwise returns
1084 false.
1085 */
1086
1087 /*!
1088 \fn bool QDate::operator>=(const QDate &d) const
1089
1090 Returns true if this date is later than or equal to \a d;
1091 otherwise returns false.
1092 */
1093
1094 /*!
1095 \fn QDate::currentDate()
1096 Returns the current date, as reported by the system clock.
1097
1098 \sa QTime::currentTime(), QDateTime::currentDateTime()
1099 */
1100
1101 #ifndef QT_NO_DATESTRING
1102 /*!
1103 \fn QDate QDate::fromString(const QString &string, Qt::DateFormat format)
1104
1105 Returns the QDate represented by the \a string, using the
1106 \a format given, or an invalid date if the string cannot be
1107 parsed.
1108
1109 Note for Qt::TextDate: It is recommended that you use the
1110 English short month names (e.g. "Jan"). Although localized month
1111 names can also be used, they depend on the user's locale settings.
1112 */
fromString(const QString & s,Qt::DateFormat f)1113 QDate QDate::fromString(const QString& s, Qt::DateFormat f)
1114 {
1115 if (s.isEmpty())
1116 return QDate();
1117
1118 switch (f) {
1119 case Qt::ISODate:
1120 {
1121 int year(s.mid(0, 4).toInt());
1122 int month(s.mid(5, 2).toInt());
1123 int day(s.mid(8, 2).toInt());
1124 if (year && month && day)
1125 return QDate(year, month, day);
1126 }
1127 break;
1128 case Qt::SystemLocaleDate:
1129 case Qt::SystemLocaleShortDate:
1130 case Qt::SystemLocaleLongDate:
1131 return fromString(s, QLocale::system().dateFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
1132 : QLocale::ShortFormat));
1133 case Qt::LocaleDate:
1134 case Qt::DefaultLocaleShortDate:
1135 case Qt::DefaultLocaleLongDate:
1136 return fromString(s, QLocale().dateFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
1137 : QLocale::ShortFormat));
1138 default:
1139 #ifndef QT_NO_TEXTDATE
1140 case Qt::TextDate: {
1141 QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
1142
1143 if (parts.count() != 4) {
1144 return QDate();
1145 }
1146
1147 QString monthName = parts.at(1);
1148 int month = -1;
1149 // Assume that English monthnames are the default
1150 for (int i = 0; i < 12; ++i) {
1151 if (monthName == QLatin1String(qt_shortMonthNames[i])) {
1152 month = i + 1;
1153 break;
1154 }
1155 }
1156 // If English names can't be found, search the localized ones
1157 if (month == -1) {
1158 for (int i = 1; i <= 12; ++i) {
1159 if (monthName == QDate::shortMonthName(i)) {
1160 month = i;
1161 break;
1162 }
1163 }
1164 }
1165 if (month < 1 || month > 12) {
1166 return QDate();
1167 }
1168
1169 bool ok;
1170 int day = parts.at(2).toInt(&ok);
1171 if (!ok) {
1172 return QDate();
1173 }
1174
1175 int year = parts.at(3).toInt(&ok);
1176 if (!ok) {
1177 return QDate();
1178 }
1179
1180 return QDate(year, month, day);
1181 }
1182 #else
1183 break;
1184 #endif
1185 }
1186 return QDate();
1187 }
1188
1189 /*!
1190 \fn QDate::fromString(const QString &string, const QString &format)
1191
1192 Returns the QDate represented by the \a string, using the \a
1193 format given, or an invalid date if the string cannot be parsed.
1194
1195 These expressions may be used for the format:
1196
1197 \table
1198 \header \i Expression \i Output
1199 \row \i d \i The day as a number without a leading zero (1 to 31)
1200 \row \i dd \i The day as a number with a leading zero (01 to 31)
1201 \row \i ddd
1202 \i The abbreviated localized day name (e.g. 'Mon' to 'Sun').
1203 Uses QDate::shortDayName().
1204 \row \i dddd
1205 \i The long localized day name (e.g. 'Monday' to 'Sunday').
1206 Uses QDate::longDayName().
1207 \row \i M \i The month as a number without a leading zero (1 to 12)
1208 \row \i MM \i The month as a number with a leading zero (01 to 12)
1209 \row \i MMM
1210 \i The abbreviated localized month name (e.g. 'Jan' to 'Dec').
1211 Uses QDate::shortMonthName().
1212 \row \i MMMM
1213 \i The long localized month name (e.g. 'January' to 'December').
1214 Uses QDate::longMonthName().
1215 \row \i yy \i The year as two digit number (00 to 99)
1216 \row \i yyyy \i The year as four digit number. If the year is negative,
1217 a minus sign is prepended in addition.
1218 \endtable
1219
1220 All other input characters will be treated as text. Any sequence
1221 of characters that are enclosed in single quotes will also be
1222 treated as text and will not be used as an expression. For example:
1223
1224 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 1
1225
1226 If the format is not satisfied, an invalid QDate is returned. The
1227 expressions that don't expect leading zeroes (d, M) will be
1228 greedy. This means that they will use two digits even if this
1229 will put them outside the accepted range of values and leaves too
1230 few digits for other sections. For example, the following format
1231 string could have meant January 30 but the M will grab two
1232 digits, resulting in an invalid date:
1233
1234 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 2
1235
1236 For any field that is not represented in the format the following
1237 defaults are used:
1238
1239 \table
1240 \header \i Field \i Default value
1241 \row \i Year \i 1900
1242 \row \i Month \i 1
1243 \row \i Day \i 1
1244 \endtable
1245
1246 The following examples demonstrate the default values:
1247
1248 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 3
1249
1250 \sa QDateTime::fromString(), QTime::fromString(), QDate::toString(),
1251 QDateTime::toString(), QTime::toString()
1252 */
1253
fromString(const QString & string,const QString & format)1254 QDate QDate::fromString(const QString &string, const QString &format)
1255 {
1256 QDate date;
1257 #ifndef QT_BOOTSTRAPPED
1258 QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString);
1259 if (dt.parseFormat(format))
1260 dt.fromString(string, &date, 0);
1261 #else
1262 Q_UNUSED(string);
1263 Q_UNUSED(format);
1264 #endif
1265 return date;
1266 }
1267 #endif // QT_NO_DATESTRING
1268
1269 /*!
1270 \overload
1271
1272 Returns true if the specified date (\a year, \a month, and \a
1273 day) is valid; otherwise returns false.
1274
1275 Example:
1276 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 4
1277
1278 \sa isNull(), setDate()
1279 */
1280
isValid(int year,int month,int day)1281 bool QDate::isValid(int year, int month, int day)
1282 {
1283 if (year < FIRST_YEAR
1284 || (year == FIRST_YEAR &&
1285 (month < FIRST_MONTH
1286 || (month == FIRST_MONTH && day < FIRST_DAY)))
1287 || year == 0) // there is no year 0 in the Julian calendar
1288 return false;
1289
1290 // passage from Julian to Gregorian calendar
1291 if (year == 1582 && month == 10 && day > 4 && day < 15)
1292 return 0;
1293
1294 return (day > 0 && month > 0 && month <= 12) &&
1295 (day <= monthDays[month] || (day == 29 && month == 2 && isLeapYear(year)));
1296 }
1297
1298 /*!
1299 \fn bool QDate::isLeapYear(int year)
1300
1301 Returns true if the specified \a year is a leap year; otherwise
1302 returns false.
1303 */
1304
isLeapYear(int y)1305 bool QDate::isLeapYear(int y)
1306 {
1307 if (y < 1582) {
1308 if ( y < 1) { // No year 0 in Julian calendar, so -1, -5, -9 etc are leap years
1309 ++y;
1310 }
1311 return y % 4 == 0;
1312 } else {
1313 return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
1314 }
1315 }
1316
1317 /*!
1318 \internal
1319
1320 This function has a confusing name and shouldn't be part of the
1321 API anyway, since we have toJulian() and fromJulian().
1322 ### Qt 5: remove it
1323 */
gregorianToJulian(int y,int m,int d)1324 uint QDate::gregorianToJulian(int y, int m, int d)
1325 {
1326 return julianDayFromDate(y, m, d);
1327 }
1328
1329 /*!
1330 \internal
1331
1332 This function has a confusing name and shouldn't be part of the
1333 API anyway, since we have toJulian() and fromJulian().
1334 ### Qt 5: remove it
1335 */
julianToGregorian(uint jd,int & y,int & m,int & d)1336 void QDate::julianToGregorian(uint jd, int &y, int &m, int &d)
1337 {
1338 getDateFromJulianDay(jd, &y, &m, &d);
1339 }
1340
1341 /*! \fn static QDate QDate::fromJulianDay(int jd)
1342
1343 Converts the Julian day \a jd to a QDate.
1344
1345 \sa toJulianDay()
1346 */
1347
1348 /*! \fn int QDate::toJulianDay() const
1349
1350 Converts the date to a Julian day.
1351
1352 \sa fromJulianDay()
1353 */
1354
1355 /*****************************************************************************
1356 QTime member functions
1357 *****************************************************************************/
1358
1359 /*!
1360 \class QTime
1361 \reentrant
1362
1363 \brief The QTime class provides clock time functions.
1364
1365
1366 A QTime object contains a clock time, i.e. the number of hours,
1367 minutes, seconds, and milliseconds since midnight. It can read the
1368 current time from the system clock and measure a span of elapsed
1369 time. It provides functions for comparing times and for
1370 manipulating a time by adding a number of milliseconds.
1371
1372 QTime uses the 24-hour clock format; it has no concept of AM/PM.
1373 Unlike QDateTime, QTime knows nothing about time zones or
1374 daylight savings time (DST).
1375
1376 A QTime object is typically created either by giving the number
1377 of hours, minutes, seconds, and milliseconds explicitly, or by
1378 using the static function currentTime(), which creates a QTime
1379 object that contains the system's local time. Note that the
1380 accuracy depends on the accuracy of the underlying operating
1381 system; not all systems provide 1-millisecond accuracy.
1382
1383 The hour(), minute(), second(), and msec() functions provide
1384 access to the number of hours, minutes, seconds, and milliseconds
1385 of the time. The same information is provided in textual format by
1386 the toString() function.
1387
1388 QTime provides a full set of operators to compare two QTime
1389 objects. One time is considered smaller than another if it is
1390 earlier than the other.
1391
1392 The time a given number of seconds or milliseconds later than a
1393 given time can be found using the addSecs() or addMSecs()
1394 functions. Correspondingly, the number of seconds or milliseconds
1395 between two times can be found using secsTo() or msecsTo().
1396
1397 QTime can be used to measure a span of elapsed time using the
1398 start(), restart(), and elapsed() functions.
1399
1400 \sa QDate, QDateTime
1401 */
1402
1403 /*!
1404 \fn QTime::QTime()
1405
1406 Constructs a null time object. A null time can be a QTime(0, 0, 0, 0)
1407 (i.e., midnight) object, except that isNull() returns true and isValid()
1408 returns false.
1409
1410 \sa isNull(), isValid()
1411 */
1412
1413 /*!
1414 Constructs a time with hour \a h, minute \a m, seconds \a s and
1415 milliseconds \a ms.
1416
1417 \a h must be in the range 0 to 23, \a m and \a s must be in the
1418 range 0 to 59, and \a ms must be in the range 0 to 999.
1419
1420 \sa isValid()
1421 */
1422
QTime(int h,int m,int s,int ms)1423 QTime::QTime(int h, int m, int s, int ms)
1424 {
1425 setHMS(h, m, s, ms);
1426 }
1427
1428
1429 /*!
1430 \fn bool QTime::isNull() const
1431
1432 Returns true if the time is null (i.e., the QTime object was
1433 constructed using the default constructor); otherwise returns
1434 false. A null time is also an invalid time.
1435
1436 \sa isValid()
1437 */
1438
1439 /*!
1440 Returns true if the time is valid; otherwise returns false. For example,
1441 the time 23:30:55.746 is valid, but 24:12:30 is invalid.
1442
1443 \sa isNull()
1444 */
1445
isValid() const1446 bool QTime::isValid() const
1447 {
1448 return mds > NullTime && mds < MSECS_PER_DAY;
1449 }
1450
1451
1452 /*!
1453 Returns the hour part (0 to 23) of the time.
1454
1455 \sa minute(), second(), msec()
1456 */
1457
hour() const1458 int QTime::hour() const
1459 {
1460 return ds() / MSECS_PER_HOUR;
1461 }
1462
1463 /*!
1464 Returns the minute part (0 to 59) of the time.
1465
1466 \sa hour(), second(), msec()
1467 */
1468
minute() const1469 int QTime::minute() const
1470 {
1471 return (ds() % MSECS_PER_HOUR) / MSECS_PER_MIN;
1472 }
1473
1474 /*!
1475 Returns the second part (0 to 59) of the time.
1476
1477 \sa hour(), minute(), msec()
1478 */
1479
second() const1480 int QTime::second() const
1481 {
1482 return (ds() / 1000)%SECS_PER_MIN;
1483 }
1484
1485 /*!
1486 Returns the millisecond part (0 to 999) of the time.
1487
1488 \sa hour(), minute(), second()
1489 */
1490
msec() const1491 int QTime::msec() const
1492 {
1493 return ds() % 1000;
1494 }
1495
1496 #ifndef QT_NO_DATESTRING
1497 /*!
1498 \overload
1499
1500 Returns the time as a string. Milliseconds are not included. The
1501 \a format parameter determines the format of the string.
1502
1503 If \a format is Qt::TextDate, the string format is HH:mm:ss; e.g. 1
1504 second before midnight would be "23:59:59".
1505
1506 If \a format is Qt::ISODate, the string format corresponds to the
1507 ISO 8601 extended specification for representations of dates,
1508 which is also HH:mm:ss. (However, contrary to ISO 8601, dates
1509 before 15 October 1582 are handled as Julian dates, not Gregorian
1510 dates. See \l{QDate G and J} {Use of Gregorian and Julian
1511 Calendars}. This might change in a future version of Qt.)
1512
1513 If the \a format is Qt::SystemLocaleShortDate or
1514 Qt::SystemLocaleLongDate, the string format depends on the locale
1515 settings of the system. Identical to calling
1516 QLocale::system().toString(time, QLocale::ShortFormat) or
1517 QLocale::system().toString(time, QLocale::LongFormat).
1518
1519 If the \a format is Qt::DefaultLocaleShortDate or
1520 Qt::DefaultLocaleLongDate, the string format depends on the
1521 default application locale. This is the locale set with
1522 QLocale::setDefault(), or the system locale if no default locale
1523 has been set. Identical to calling QLocale().toString(time,
1524 QLocale::ShortFormat) or QLocale().toString(time,
1525 QLocale::LongFormat).
1526
1527 If the time is invalid, an empty string will be returned.
1528 */
1529
toString(Qt::DateFormat format) const1530 QString QTime::toString(Qt::DateFormat format) const
1531 {
1532 if (!isValid())
1533 return QString();
1534
1535 switch (format) {
1536 case Qt::SystemLocaleDate:
1537 case Qt::SystemLocaleShortDate:
1538 case Qt::SystemLocaleLongDate:
1539 return QLocale::system().toString(*this, format == Qt::SystemLocaleLongDate ? QLocale::LongFormat
1540 : QLocale::ShortFormat);
1541 case Qt::LocaleDate:
1542 case Qt::DefaultLocaleShortDate:
1543 case Qt::DefaultLocaleLongDate:
1544 return QLocale().toString(*this, format == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
1545 : QLocale::ShortFormat);
1546
1547 default:
1548 case Qt::ISODate:
1549 case Qt::TextDate:
1550 return QString::fromLatin1("%1:%2:%3")
1551 .arg(hour(), 2, 10, QLatin1Char('0'))
1552 .arg(minute(), 2, 10, QLatin1Char('0'))
1553 .arg(second(), 2, 10, QLatin1Char('0'));
1554 }
1555 }
1556
1557 /*!
1558 Returns the time as a string. The \a format parameter determines
1559 the format of the result string.
1560
1561 These expressions may be used:
1562
1563 \table
1564 \header \i Expression \i Output
1565 \row \i h
1566 \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
1567 \row \i hh
1568 \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
1569 \row \i H
1570 \i the hour without a leading zero (0 to 23, even with AM/PM display)
1571 \row \i HH
1572 \i the hour with a leading zero (00 to 23, even with AM/PM display)
1573 \row \i m \i the minute without a leading zero (0 to 59)
1574 \row \i mm \i the minute with a leading zero (00 to 59)
1575 \row \i s \i the second without a leading zero (0 to 59)
1576 \row \i ss \i the second with a leading zero (00 to 59)
1577 \row \i z \i the milliseconds without leading zeroes (0 to 999)
1578 \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
1579 \row \i AP or A
1580 \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
1581 \row \i ap or a
1582 \i use am/pm display. \e ap will be replaced by either "am" or "pm".
1583 \row \i t \i the timezone (for example "CEST")
1584 \endtable
1585
1586 All other input characters will be ignored. Any sequence of characters that
1587 are enclosed in singlequotes will be treated as text and not be used as an
1588 expression. Two consecutive singlequotes ("''") are replaced by a singlequote
1589 in the output.
1590
1591 Example format strings (assuming that the QTime is 14:13:09.042)
1592
1593 \table
1594 \header \i Format \i Result
1595 \row \i hh:mm:ss.zzz \i 14:13:09.042
1596 \row \i h:m:s ap \i 2:13:9 pm
1597 \row \i H:m:s a \i 14:13:9 pm
1598 \endtable
1599
1600 If the datetime is invalid, an empty string will be returned.
1601 If \a format is empty, the default format "hh:mm:ss" is used.
1602
1603 \sa QDate::toString() QDateTime::toString()
1604 */
toString(const QString & format) const1605 QString QTime::toString(const QString& format) const
1606 {
1607 return fmtDateTime(format, this, 0);
1608 }
1609 #endif //QT_NO_DATESTRING
1610 /*!
1611 Sets the time to hour \a h, minute \a m, seconds \a s and
1612 milliseconds \a ms.
1613
1614 \a h must be in the range 0 to 23, \a m and \a s must be in the
1615 range 0 to 59, and \a ms must be in the range 0 to 999.
1616 Returns true if the set time is valid; otherwise returns false.
1617
1618 \sa isValid()
1619 */
1620
setHMS(int h,int m,int s,int ms)1621 bool QTime::setHMS(int h, int m, int s, int ms)
1622 {
1623 #if defined(Q_OS_WINCE)
1624 startTick = NullTime;
1625 #endif
1626 if (!isValid(h,m,s,ms)) {
1627 mds = NullTime; // make this invalid
1628 return false;
1629 }
1630 mds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms;
1631 return true;
1632 }
1633
1634 /*!
1635 Returns a QTime object containing a time \a s seconds later
1636 than the time of this object (or earlier if \a s is negative).
1637
1638 Note that the time will wrap if it passes midnight.
1639
1640 Example:
1641
1642 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 5
1643
1644 \sa addMSecs(), secsTo(), QDateTime::addSecs()
1645 */
1646
addSecs(int s) const1647 QTime QTime::addSecs(int s) const
1648 {
1649 return addMSecs(s * 1000);
1650 }
1651
1652 /*!
1653 Returns the number of seconds from this time to \a t.
1654 If \a t is earlier than this time, the number of seconds returned
1655 is negative.
1656
1657 Because QTime measures time within a day and there are 86400
1658 seconds in a day, the result is always between -86400 and 86400.
1659
1660 secsTo() does not take into account any milliseconds.
1661
1662 \sa addSecs(), QDateTime::secsTo()
1663 */
1664
secsTo(const QTime & t) const1665 int QTime::secsTo(const QTime &t) const
1666 {
1667 return (t.ds() - ds()) / 1000;
1668 }
1669
1670 /*!
1671 Returns a QTime object containing a time \a ms milliseconds later
1672 than the time of this object (or earlier if \a ms is negative).
1673
1674 Note that the time will wrap if it passes midnight. See addSecs()
1675 for an example.
1676
1677 \sa addSecs(), msecsTo(), QDateTime::addMSecs()
1678 */
1679
addMSecs(int ms) const1680 QTime QTime::addMSecs(int ms) const
1681 {
1682 QTime t;
1683 if (ms < 0) {
1684 // % not well-defined for -ve, but / is.
1685 int negdays = (MSECS_PER_DAY - ms) / MSECS_PER_DAY;
1686 t.mds = (ds() + ms + negdays * MSECS_PER_DAY) % MSECS_PER_DAY;
1687 } else {
1688 t.mds = (ds() + ms) % MSECS_PER_DAY;
1689 }
1690 #if defined(Q_OS_WINCE)
1691 if (startTick > NullTime)
1692 t.startTick = (startTick + ms) % MSECS_PER_DAY;
1693 #endif
1694 return t;
1695 }
1696
1697 /*!
1698 Returns the number of milliseconds from this time to \a t.
1699 If \a t is earlier than this time, the number of milliseconds returned
1700 is negative.
1701
1702 Because QTime measures time within a day and there are 86400
1703 seconds in a day, the result is always between -86400000 and
1704 86400000 ms.
1705
1706 \sa secsTo(), addMSecs(), QDateTime::msecsTo()
1707 */
1708
msecsTo(const QTime & t) const1709 int QTime::msecsTo(const QTime &t) const
1710 {
1711 #if defined(Q_OS_WINCE)
1712 // GetLocalTime() for Windows CE has no milliseconds resolution
1713 if (t.startTick > NullTime && startTick > NullTime)
1714 return t.startTick - startTick;
1715 else
1716 #endif
1717 return t.ds() - ds();
1718 }
1719
1720
1721 /*!
1722 \fn bool QTime::operator==(const QTime &t) const
1723
1724 Returns true if this time is equal to \a t; otherwise returns false.
1725 */
1726
1727 /*!
1728 \fn bool QTime::operator!=(const QTime &t) const
1729
1730 Returns true if this time is different from \a t; otherwise returns false.
1731 */
1732
1733 /*!
1734 \fn bool QTime::operator<(const QTime &t) const
1735
1736 Returns true if this time is earlier than \a t; otherwise returns false.
1737 */
1738
1739 /*!
1740 \fn bool QTime::operator<=(const QTime &t) const
1741
1742 Returns true if this time is earlier than or equal to \a t;
1743 otherwise returns false.
1744 */
1745
1746 /*!
1747 \fn bool QTime::operator>(const QTime &t) const
1748
1749 Returns true if this time is later than \a t; otherwise returns false.
1750 */
1751
1752 /*!
1753 \fn bool QTime::operator>=(const QTime &t) const
1754
1755 Returns true if this time is later than or equal to \a t;
1756 otherwise returns false.
1757 */
1758
1759 /*!
1760 \fn QTime::currentTime()
1761
1762 Returns the current time as reported by the system clock.
1763
1764 Note that the accuracy depends on the accuracy of the underlying
1765 operating system; not all systems provide 1-millisecond accuracy.
1766 */
1767
1768 #ifndef QT_NO_DATESTRING
1769 /*!
1770 \fn QTime QTime::fromString(const QString &string, Qt::DateFormat format)
1771
1772 Returns the time represented in the \a string as a QTime using the
1773 \a format given, or an invalid time if this is not possible.
1774
1775 Note that fromString() uses a "C" locale encoded string to convert
1776 milliseconds to a float value. If the default locale is not "C",
1777 this may result in two conversion attempts (if the conversion
1778 fails for the default locale). This should be considered an
1779 implementation detail.
1780 */
fromString(const QString & s,Qt::DateFormat f)1781 QTime QTime::fromString(const QString& s, Qt::DateFormat f)
1782 {
1783 if (s.isEmpty()) {
1784 QTime t;
1785 t.mds = NullTime;
1786 return t;
1787 }
1788
1789 switch (f) {
1790 case Qt::SystemLocaleDate:
1791 case Qt::SystemLocaleShortDate:
1792 case Qt::SystemLocaleLongDate:
1793 return fromString(s, QLocale::system().timeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
1794 : QLocale::ShortFormat));
1795 case Qt::LocaleDate:
1796 case Qt::DefaultLocaleShortDate:
1797 case Qt::DefaultLocaleLongDate:
1798 return fromString(s, QLocale().timeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
1799 : QLocale::ShortFormat));
1800 default:
1801 {
1802 bool ok = true;
1803 const int hour(s.mid(0, 2).toInt(&ok));
1804 if (!ok)
1805 return QTime();
1806 const int minute(s.mid(3, 2).toInt(&ok));
1807 if (!ok)
1808 return QTime();
1809 const int second(s.mid(6, 2).toInt(&ok));
1810 if (!ok)
1811 return QTime();
1812 const QString msec_s(QLatin1String("0.") + s.mid(9, 4));
1813 const float msec(msec_s.toFloat(&ok));
1814 if (!ok)
1815 return QTime(hour, minute, second, 0);
1816 return QTime(hour, minute, second, qMin(qRound(msec * 1000.0), 999));
1817 }
1818 }
1819 }
1820
1821 /*!
1822 \fn QTime::fromString(const QString &string, const QString &format)
1823
1824 Returns the QTime represented by the \a string, using the \a
1825 format given, or an invalid time if the string cannot be parsed.
1826
1827 These expressions may be used for the format:
1828
1829 \table
1830 \header \i Expression \i Output
1831 \row \i h
1832 \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
1833 \row \i hh
1834 \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
1835 \row \i m \i the minute without a leading zero (0 to 59)
1836 \row \i mm \i the minute with a leading zero (00 to 59)
1837 \row \i s \i the second without a leading zero (0 to 59)
1838 \row \i ss \i the second with a leading zero (00 to 59)
1839 \row \i z \i the milliseconds without leading zeroes (0 to 999)
1840 \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
1841 \row \i AP
1842 \i interpret as an AM/PM time. \e AP must be either "AM" or "PM".
1843 \row \i ap
1844 \i Interpret as an AM/PM time. \e ap must be either "am" or "pm".
1845 \endtable
1846
1847 All other input characters will be treated as text. Any sequence
1848 of characters that are enclosed in single quotes will also be
1849 treated as text and not be used as an expression.
1850
1851 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 6
1852
1853 If the format is not satisfied an invalid QTime is returned.
1854 Expressions that do not expect leading zeroes to be given (h, m, s
1855 and z) are greedy. This means that they will use two digits even if
1856 this puts them outside the range of accepted values and leaves too
1857 few digits for other sections. For example, the following string
1858 could have meant 00:07:10, but the m will grab two digits, resulting
1859 in an invalid time:
1860
1861 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 7
1862
1863 Any field that is not represented in the format will be set to zero.
1864 For example:
1865
1866 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 8
1867
1868 \sa QDateTime::fromString() QDate::fromString() QDate::toString()
1869 QDateTime::toString() QTime::toString()
1870 */
1871
fromString(const QString & string,const QString & format)1872 QTime QTime::fromString(const QString &string, const QString &format)
1873 {
1874 QTime time;
1875 #ifndef QT_BOOTSTRAPPED
1876 QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString);
1877 if (dt.parseFormat(format))
1878 dt.fromString(string, 0, &time);
1879 #else
1880 Q_UNUSED(string);
1881 Q_UNUSED(format);
1882 #endif
1883 return time;
1884 }
1885
1886 #endif // QT_NO_DATESTRING
1887
1888
1889 /*!
1890 \overload
1891
1892 Returns true if the specified time is valid; otherwise returns
1893 false.
1894
1895 The time is valid if \a h is in the range 0 to 23, \a m and
1896 \a s are in the range 0 to 59, and \a ms is in the range 0 to 999.
1897
1898 Example:
1899
1900 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 9
1901 */
1902
isValid(int h,int m,int s,int ms)1903 bool QTime::isValid(int h, int m, int s, int ms)
1904 {
1905 return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
1906 }
1907
1908
1909 /*!
1910 Sets this time to the current time. This is practical for timing:
1911
1912 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 10
1913
1914 \sa restart(), elapsed(), currentTime()
1915 */
1916
start()1917 void QTime::start()
1918 {
1919 *this = currentTime();
1920 }
1921
1922 /*!
1923 Sets this time to the current time and returns the number of
1924 milliseconds that have elapsed since the last time start() or
1925 restart() was called.
1926
1927 This function is guaranteed to be atomic and is thus very handy
1928 for repeated measurements. Call start() to start the first
1929 measurement, and restart() for each later measurement.
1930
1931 Note that the counter wraps to zero 24 hours after the last call
1932 to start() or restart().
1933
1934 \warning If the system's clock setting has been changed since the
1935 last time start() or restart() was called, the result is
1936 undefined. This can happen when daylight savings time is turned on
1937 or off.
1938
1939 \sa start(), elapsed(), currentTime()
1940 */
1941
restart()1942 int QTime::restart()
1943 {
1944 QTime t = currentTime();
1945 int n = msecsTo(t);
1946 if (n < 0) // passed midnight
1947 n += 86400*1000;
1948 *this = t;
1949 return n;
1950 }
1951
1952 /*!
1953 Returns the number of milliseconds that have elapsed since the
1954 last time start() or restart() was called.
1955
1956 Note that the counter wraps to zero 24 hours after the last call
1957 to start() or restart.
1958
1959 Note that the accuracy depends on the accuracy of the underlying
1960 operating system; not all systems provide 1-millisecond accuracy.
1961
1962 \warning If the system's clock setting has been changed since the
1963 last time start() or restart() was called, the result is
1964 undefined. This can happen when daylight savings time is turned on
1965 or off.
1966
1967 \sa start(), restart()
1968 */
1969
elapsed() const1970 int QTime::elapsed() const
1971 {
1972 int n = msecsTo(currentTime());
1973 if (n < 0) // passed midnight
1974 n += 86400 * 1000;
1975 return n;
1976 }
1977
1978
1979 /*****************************************************************************
1980 QDateTime member functions
1981 *****************************************************************************/
1982
1983 /*!
1984 \class QDateTime
1985 \reentrant
1986 \brief The QDateTime class provides date and time functions.
1987
1988
1989 A QDateTime object contains a calendar date and a clock time (a
1990 "datetime"). It is a combination of the QDate and QTime classes.
1991 It can read the current datetime from the system clock. It
1992 provides functions for comparing datetimes and for manipulating a
1993 datetime by adding a number of seconds, days, months, or years.
1994
1995 A QDateTime object is typically created either by giving a date
1996 and time explicitly in the constructor, or by using the static
1997 function currentDateTime() that returns a QDateTime object set
1998 to the system clock's time. The date and time can be changed with
1999 setDate() and setTime(). A datetime can also be set using the
2000 setTime_t() function that takes a POSIX-standard "number of
2001 seconds since 00:00:00 on January 1, 1970" value. The fromString()
2002 function returns a QDateTime, given a string and a date format
2003 used to interpret the date within the string.
2004
2005 The date() and time() functions provide access to the date and
2006 time parts of the datetime. The same information is provided in
2007 textual format by the toString() function.
2008
2009 QDateTime provides a full set of operators to compare two
2010 QDateTime objects where smaller means earlier and larger means
2011 later.
2012
2013 You can increment (or decrement) a datetime by a given number of
2014 milliseconds using addMSecs(), seconds using addSecs(), or days
2015 using addDays(). Similarly you can use addMonths() and addYears().
2016 The daysTo() function returns the number of days between two datetimes,
2017 secsTo() returns the number of seconds between two datetimes, and
2018 msecsTo() returns the number of milliseconds between two datetimes.
2019
2020 QDateTime can store datetimes as \l{Qt::LocalTime}{local time} or
2021 as \l{Qt::UTC}{UTC}. QDateTime::currentDateTime() returns a
2022 QDateTime expressed as local time; use toUTC() to convert it to
2023 UTC. You can also use timeSpec() to find out if a QDateTime
2024 object stores a UTC time or a local time. Operations such as
2025 addSecs() and secsTo() are aware of daylight saving time (DST).
2026
2027 \note QDateTime does not account for leap seconds.
2028
2029 \section1
2030
2031 \target QDateTime G and J
2032 \section2 Use of Gregorian and Julian Calendars
2033
2034 QDate uses the Gregorian calendar in all locales, beginning
2035 on the date 15 October 1582. For dates up to and including 4
2036 October 1582, the Julian calendar is used. This means there is a
2037 10-day gap in the internal calendar between the 4th and the 15th
2038 of October 1582. When you use QDateTime for dates in that epoch,
2039 the day after 4 October 1582 is 15 October 1582, and the dates in
2040 the gap are invalid.
2041
2042 The Julian to Gregorian changeover date used here is the date when
2043 the Gregorian calendar was first introduced, by Pope Gregory
2044 XIII. That change was not universally accepted and some localities
2045 only executed it at a later date (if at all). QDateTime
2046 doesn't take any of these historical facts into account. If an
2047 application must support a locale-specific dating system, it must
2048 do so on its own, remembering to convert the dates using the
2049 Julian day.
2050
2051 \section2 No Year 0
2052
2053 There is no year 0. Dates in that year are considered invalid. The
2054 year -1 is the year "1 before Christ" or "1 before current era."
2055 The day before 0001-01-01 is December 31st, 1 BCE.
2056
2057 \section2 Range of Valid Dates
2058
2059 The range of valid dates is from January 2nd, 4713 BCE, to
2060 sometime in the year 11 million CE. The Julian Day returned by
2061 QDate::toJulianDay() is a number in the contiguous range from 1 to
2062 \e{overflow}, even across QDateTime's "date holes". It is suitable
2063 for use in applications that must convert a QDateTime to a date in
2064 another calendar system, e.g., Hebrew, Islamic or Chinese.
2065
2066 The Gregorian calendar was introduced in different places around
2067 the world on different dates. QDateTime uses QDate to store the
2068 date, so it uses the Gregorian calendar for all locales, beginning
2069 on the date 15 October 1582. For dates up to and including 4
2070 October 1582, QDateTime uses the Julian calendar. This means
2071 there is a 10-day gap in the QDateTime calendar between the 4th
2072 and the 15th of October 1582. When you use QDateTime for dates in
2073 that epoch, the day after 4 October 1582 is 15 October 1582, and
2074 the dates in the gap are invalid.
2075
2076 \section2
2077 Use of System Timezone
2078
2079 QDateTime uses the system's time zone information to determine the
2080 offset of local time from UTC. If the system is not configured
2081 correctly or not up-to-date, QDateTime will give wrong results as
2082 well.
2083
2084 \section2 Daylight Savings Time (DST)
2085
2086 QDateTime takes into account the system's time zone information
2087 when dealing with DST. On modern Unix systems, this means it
2088 applies the correct historical DST data whenever possible. On
2089 Windows and Windows CE, where the system doesn't support
2090 historical DST data, historical accuracy is not maintained with
2091 respect to DST.
2092
2093 The range of valid dates taking DST into account is 1970-01-01 to
2094 the present, and rules are in place for handling DST correctly
2095 until 2037-12-31, but these could change. For dates falling
2096 outside that range, QDateTime makes a \e{best guess} using the
2097 rules for year 1970 or 2037, but we can't guarantee accuracy. This
2098 means QDateTime doesn't take into account changes in a locale's
2099 time zone before 1970, even if the system's time zone database
2100 supports that information.
2101
2102 \sa QDate QTime QDateTimeEdit
2103 */
2104
2105 /*!
2106 Constructs a null datetime (i.e. null date and null time). A null
2107 datetime is invalid, since the date is invalid.
2108
2109 \sa isValid()
2110 */
QDateTime()2111 QDateTime::QDateTime()
2112 : d(new QDateTimePrivate)
2113 {
2114 }
2115
2116
2117 /*!
2118 Constructs a datetime with the given \a date, a valid
2119 time(00:00:00.000), and sets the timeSpec() to Qt::LocalTime.
2120 */
2121
QDateTime(const QDate & date)2122 QDateTime::QDateTime(const QDate &date)
2123 : d(new QDateTimePrivate)
2124 {
2125 d->date = date;
2126 d->time = QTime(0, 0, 0);
2127 }
2128
2129 /*!
2130 Constructs a datetime with the given \a date and \a time, using
2131 the time specification defined by \a spec.
2132
2133 If \a date is valid and \a time is not, the time will be set to midnight.
2134 */
2135
QDateTime(const QDate & date,const QTime & time,Qt::TimeSpec spec)2136 QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec)
2137 : d(new QDateTimePrivate)
2138 {
2139 d->date = date;
2140 d->time = date.isValid() && !time.isValid() ? QTime(0, 0, 0) : time;
2141 d->spec = (spec == Qt::UTC) ? QDateTimePrivate::UTC : QDateTimePrivate::LocalUnknown;
2142 }
2143
2144 /*!
2145 Constructs a copy of the \a other datetime.
2146 */
2147
QDateTime(const QDateTime & other)2148 QDateTime::QDateTime(const QDateTime &other)
2149 : d(other.d)
2150 {
2151 }
2152
2153 /*!
2154 Destroys the datetime.
2155 */
~QDateTime()2156 QDateTime::~QDateTime()
2157 {
2158 }
2159
2160 /*!
2161 Makes a copy of the \a other datetime and returns a reference to the
2162 copy.
2163 */
2164
operator =(const QDateTime & other)2165 QDateTime &QDateTime::operator=(const QDateTime &other)
2166 {
2167 d = other.d;
2168 return *this;
2169 }
2170
2171 /*!
2172 Returns true if both the date and the time are null; otherwise
2173 returns false. A null datetime is invalid.
2174
2175 \sa QDate::isNull(), QTime::isNull(), isValid()
2176 */
2177
isNull() const2178 bool QDateTime::isNull() const
2179 {
2180 return d->date.isNull() && d->time.isNull();
2181 }
2182
2183 /*!
2184 Returns true if both the date and the time are valid; otherwise
2185 returns false.
2186
2187 \sa QDate::isValid(), QTime::isValid()
2188 */
2189
isValid() const2190 bool QDateTime::isValid() const
2191 {
2192 return d->date.isValid() && d->time.isValid();
2193 }
2194
2195 /*!
2196 Returns the date part of the datetime.
2197
2198 \sa setDate(), time(), timeSpec()
2199 */
2200
date() const2201 QDate QDateTime::date() const
2202 {
2203 return d->date;
2204 }
2205
2206 /*!
2207 Returns the time part of the datetime.
2208
2209 \sa setTime(), date(), timeSpec()
2210 */
2211
time() const2212 QTime QDateTime::time() const
2213 {
2214 return d->time;
2215 }
2216
2217 /*!
2218 Returns the time specification of the datetime.
2219
2220 \sa setTimeSpec(), date(), time(), Qt::TimeSpec
2221 */
2222
timeSpec() const2223 Qt::TimeSpec QDateTime::timeSpec() const
2224 {
2225 switch(d->spec)
2226 {
2227 case QDateTimePrivate::UTC:
2228 return Qt::UTC;
2229 case QDateTimePrivate::OffsetFromUTC:
2230 return Qt::OffsetFromUTC;
2231 default:
2232 return Qt::LocalTime;
2233 }
2234 }
2235
2236 /*!
2237 Sets the date part of this datetime to \a date.
2238 If no time is set, it is set to midnight.
2239
2240 \sa date(), setTime(), setTimeSpec()
2241 */
2242
setDate(const QDate & date)2243 void QDateTime::setDate(const QDate &date)
2244 {
2245 detach();
2246 d->date = date;
2247 if (d->spec == QDateTimePrivate::LocalStandard
2248 || d->spec == QDateTimePrivate::LocalDST)
2249 d->spec = QDateTimePrivate::LocalUnknown;
2250 if (date.isValid() && !d->time.isValid())
2251 d->time = QTime(0, 0, 0);
2252 }
2253
2254 /*!
2255 Sets the time part of this datetime to \a time.
2256
2257 \sa time(), setDate(), setTimeSpec()
2258 */
2259
setTime(const QTime & time)2260 void QDateTime::setTime(const QTime &time)
2261 {
2262 detach();
2263 if (d->spec == QDateTimePrivate::LocalStandard
2264 || d->spec == QDateTimePrivate::LocalDST)
2265 d->spec = QDateTimePrivate::LocalUnknown;
2266 d->time = time;
2267 }
2268
2269 /*!
2270 Sets the time specification used in this datetime to \a spec.
2271
2272 \sa timeSpec(), setDate(), setTime(), Qt::TimeSpec
2273 */
2274
setTimeSpec(Qt::TimeSpec spec)2275 void QDateTime::setTimeSpec(Qt::TimeSpec spec)
2276 {
2277 detach();
2278
2279 switch(spec)
2280 {
2281 case Qt::UTC:
2282 d->spec = QDateTimePrivate::UTC;
2283 break;
2284 case Qt::OffsetFromUTC:
2285 d->spec = QDateTimePrivate::OffsetFromUTC;
2286 break;
2287 default:
2288 d->spec = QDateTimePrivate::LocalUnknown;
2289 break;
2290 }
2291 }
2292
toMSecsSinceEpoch_helper(qint64 jd,int msecs)2293 qint64 toMSecsSinceEpoch_helper(qint64 jd, int msecs)
2294 {
2295 qint64 days = jd - JULIAN_DAY_FOR_EPOCH;
2296 qint64 retval = (days * MSECS_PER_DAY) + msecs;
2297 return retval;
2298 }
2299
2300 /*!
2301 \since 4.7
2302
2303 Returns the datetime as the number of milliseconds that have passed
2304 since 1970-01-01T00:00:00.000, Coordinated Universal Time (Qt::UTC).
2305
2306 On systems that do not support time zones, this function will
2307 behave as if local time were Qt::UTC.
2308
2309 The behavior for this function is undefined if the datetime stored in
2310 this object is not valid. However, for all valid dates, this function
2311 returns a unique value.
2312
2313 \sa toTime_t(), setMSecsSinceEpoch()
2314 */
toMSecsSinceEpoch() const2315 qint64 QDateTime::toMSecsSinceEpoch() const
2316 {
2317 QDate utcDate;
2318 QTime utcTime;
2319 d->getUTC(utcDate, utcTime);
2320
2321 return toMSecsSinceEpoch_helper(utcDate.jd, utcTime.ds());
2322 }
2323
2324 /*!
2325 Returns the datetime as the number of seconds that have passed
2326 since 1970-01-01T00:00:00, Coordinated Universal Time (Qt::UTC).
2327
2328 On systems that do not support time zones, this function will
2329 behave as if local time were Qt::UTC.
2330
2331 \note This function returns a 32-bit unsigned integer, so it does not
2332 support dates before 1970, but it does support dates after
2333 2038-01-19T03:14:06, which may not be valid time_t values. Be careful
2334 when passing those time_t values to system functions, which could
2335 interpret them as negative dates.
2336
2337 If the date is outside the range 1970-01-01T00:00:00 to
2338 2106-02-07T06:28:14, this function returns -1 cast to an unsigned integer
2339 (i.e., 0xFFFFFFFF).
2340
2341 To get an extended range, use toMSecsSinceEpoch().
2342
2343 \sa toMSecsSinceEpoch(), setTime_t()
2344 */
2345
toTime_t() const2346 uint QDateTime::toTime_t() const
2347 {
2348 qint64 retval = toMSecsSinceEpoch() / 1000;
2349 if (quint64(retval) >= Q_UINT64_C(0xFFFFFFFF))
2350 return uint(-1);
2351 return uint(retval);
2352 }
2353
2354 /*!
2355 \since 4.7
2356
2357 Sets the date and time given the number of milliseconds,\a msecs, that have
2358 passed since 1970-01-01T00:00:00.000, Coordinated Universal Time
2359 (Qt::UTC). On systems that do not support time zones this function
2360 will behave as if local time were Qt::UTC.
2361
2362 Note that there are possible values for \a msecs that lie outside the
2363 valid range of QDateTime, both negative and positive. The behavior of
2364 this function is undefined for those values.
2365
2366 \sa toMSecsSinceEpoch(), setTime_t()
2367 */
setMSecsSinceEpoch(qint64 msecs)2368 void QDateTime::setMSecsSinceEpoch(qint64 msecs)
2369 {
2370 detach();
2371
2372 QDateTimePrivate::Spec oldSpec = d->spec;
2373
2374 int ddays = msecs / MSECS_PER_DAY;
2375 msecs %= MSECS_PER_DAY;
2376 if (msecs < 0) {
2377 // negative
2378 --ddays;
2379 msecs += MSECS_PER_DAY;
2380 }
2381
2382 d->date = QDate(1970, 1, 1).addDays(ddays);
2383 d->time = QTime().addMSecs(msecs);
2384 d->spec = QDateTimePrivate::UTC;
2385
2386 if (oldSpec != QDateTimePrivate::UTC)
2387 d->spec = d->getLocal(d->date, d->time);
2388 }
2389
2390 /*!
2391 \fn void QDateTime::setTime_t(uint seconds)
2392
2393 Sets the date and time given the number of \a seconds that have
2394 passed since 1970-01-01T00:00:00, Coordinated Universal Time
2395 (Qt::UTC). On systems that do not support time zones this function
2396 will behave as if local time were Qt::UTC.
2397
2398 \sa toTime_t()
2399 */
2400
setTime_t(uint secsSince1Jan1970UTC)2401 void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
2402 {
2403 detach();
2404
2405 QDateTimePrivate::Spec oldSpec = d->spec;
2406
2407 d->date = QDate(1970, 1, 1).addDays(secsSince1Jan1970UTC / SECS_PER_DAY);
2408 d->time = QTime().addSecs(secsSince1Jan1970UTC % SECS_PER_DAY);
2409 d->spec = QDateTimePrivate::UTC;
2410
2411 if (oldSpec != QDateTimePrivate::UTC)
2412 d->spec = d->getLocal(d->date, d->time);
2413 }
2414
2415 #ifndef QT_NO_DATESTRING
2416 /*!
2417 \fn QString QDateTime::toString(Qt::DateFormat format) const
2418
2419 \overload
2420
2421 Returns the datetime as a string in the \a format given.
2422
2423 If the \a format is Qt::TextDate, the string is formatted in
2424 the default way. QDate::shortDayName(), QDate::shortMonthName(),
2425 and QTime::toString() are used to generate the string, so the
2426 day and month names will be localized names. An example of this
2427 formatting is "Wed May 20 03:40:13 1998".
2428
2429 If the \a format is Qt::ISODate, the string format corresponds
2430 to the ISO 8601 extended specification for representations of
2431 dates and times, taking the form YYYY-MM-DDTHH:mm:ss[Z|[+|-]HH:mm],
2432 depending on the timeSpec() of the QDateTime. If the timeSpec()
2433 is Qt::UTC, Z will be appended to the string; if the timeSpec() is
2434 Qt::OffsetFromUTC the offset in hours and minutes from UTC will
2435 be appended to the string.
2436
2437 If the \a format is Qt::SystemLocaleShortDate or
2438 Qt::SystemLocaleLongDate, the string format depends on the locale
2439 settings of the system. Identical to calling
2440 QLocale::system().toString(datetime, QLocale::ShortFormat) or
2441 QLocale::system().toString(datetime, QLocale::LongFormat).
2442
2443 If the \a format is Qt::DefaultLocaleShortDate or
2444 Qt::DefaultLocaleLongDate, the string format depends on the
2445 default application locale. This is the locale set with
2446 QLocale::setDefault(), or the system locale if no default locale
2447 has been set. Identical to calling QLocale().toString(datetime,
2448 QLocale::ShortFormat) or QLocale().toString(datetime,
2449 QLocale::LongFormat).
2450
2451 If the datetime is invalid, an empty string will be returned.
2452
2453 \warning The Qt::ISODate format is only valid for years in the
2454 range 0 to 9999. This restriction may apply to locale-aware
2455 formats as well, depending on the locale settings.
2456
2457 \sa QDate::toString() QTime::toString() Qt::DateFormat
2458 */
2459
toString(Qt::DateFormat f) const2460 QString QDateTime::toString(Qt::DateFormat f) const
2461 {
2462 QString buf;
2463 if (!isValid())
2464 return buf;
2465
2466 if (f == Qt::ISODate) {
2467 buf = d->date.toString(Qt::ISODate);
2468 if (buf.isEmpty())
2469 return QString(); // failed to convert
2470 buf += QLatin1Char('T');
2471 buf += d->time.toString(Qt::ISODate);
2472 switch (d->spec) {
2473 case QDateTimePrivate::UTC:
2474 buf += QLatin1Char('Z');
2475 break;
2476 case QDateTimePrivate::OffsetFromUTC: {
2477 int sign = d->utcOffset >= 0 ? 1: -1;
2478 buf += QString::fromLatin1("%1%2:%3").
2479 arg(sign == 1 ? QLatin1Char('+') : QLatin1Char('-')).
2480 arg(d->utcOffset * sign / SECS_PER_HOUR, 2, 10, QLatin1Char('0')).
2481 arg((d->utcOffset / 60) % 60, 2, 10, QLatin1Char('0'));
2482 break;
2483 }
2484 default:
2485 break;
2486 }
2487 }
2488 #ifndef QT_NO_TEXTDATE
2489 else if (f == Qt::TextDate) {
2490 #ifndef Q_WS_WIN
2491 buf = d->date.shortDayName(d->date.dayOfWeek());
2492 buf += QLatin1Char(' ');
2493 buf += d->date.shortMonthName(d->date.month());
2494 buf += QLatin1Char(' ');
2495 buf += QString::number(d->date.day());
2496 #else
2497 wchar_t out[255];
2498 GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255);
2499 QString winstr = QString::fromWCharArray(out);
2500 switch (winstr.toInt()) {
2501 case 1:
2502 buf = d->date.shortDayName(d->date.dayOfWeek());
2503 buf += QLatin1Char(' ');
2504 buf += QString::number(d->date.day());
2505 buf += QLatin1String(". ");
2506 buf += d->date.shortMonthName(d->date.month());
2507 break;
2508 default:
2509 buf = d->date.shortDayName(d->date.dayOfWeek());
2510 buf += QLatin1Char(' ');
2511 buf += d->date.shortMonthName(d->date.month());
2512 buf += QLatin1Char(' ');
2513 buf += QString::number(d->date.day());
2514 }
2515 #endif
2516 buf += QLatin1Char(' ');
2517 buf += d->time.toString();
2518 buf += QLatin1Char(' ');
2519 buf += QString::number(d->date.year());
2520 }
2521 #endif
2522 else {
2523 buf = d->date.toString(f);
2524 if (buf.isEmpty())
2525 return QString(); // failed to convert
2526 buf += QLatin1Char(' ');
2527 buf += d->time.toString(f);
2528 }
2529
2530 return buf;
2531 }
2532
2533 /*!
2534 Returns the datetime as a string. The \a format parameter
2535 determines the format of the result string.
2536
2537 These expressions may be used for the date:
2538
2539 \table
2540 \header \i Expression \i Output
2541 \row \i d \i the day as number without a leading zero (1 to 31)
2542 \row \i dd \i the day as number with a leading zero (01 to 31)
2543 \row \i ddd
2544 \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
2545 Uses QDate::shortDayName().
2546 \row \i dddd
2547 \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
2548 Uses QDate::longDayName().
2549 \row \i M \i the month as number without a leading zero (1-12)
2550 \row \i MM \i the month as number with a leading zero (01-12)
2551 \row \i MMM
2552 \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
2553 Uses QDate::shortMonthName().
2554 \row \i MMMM
2555 \i the long localized month name (e.g. 'January' to 'December').
2556 Uses QDate::longMonthName().
2557 \row \i yy \i the year as two digit number (00-99)
2558 \row \i yyyy \i the year as four digit number
2559 \endtable
2560
2561 These expressions may be used for the time:
2562
2563 \table
2564 \header \i Expression \i Output
2565 \row \i h
2566 \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
2567 \row \i hh
2568 \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
2569 \row \i m \i the minute without a leading zero (0 to 59)
2570 \row \i mm \i the minute with a leading zero (00 to 59)
2571 \row \i s \i the second without a leading zero (0 to 59)
2572 \row \i ss \i the second with a leading zero (00 to 59)
2573 \row \i z \i the milliseconds without leading zeroes (0 to 999)
2574 \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
2575 \row \i AP
2576 \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
2577 \row \i ap
2578 \i use am/pm display. \e ap will be replaced by either "am" or "pm".
2579 \endtable
2580
2581 All other input characters will be ignored. Any sequence of characters that
2582 are enclosed in singlequotes will be treated as text and not be used as an
2583 expression. Two consecutive singlequotes ("''") are replaced by a singlequote
2584 in the output.
2585
2586 Example format strings (assumed that the QDateTime is 21 May 2001
2587 14:13:09):
2588
2589 \table
2590 \header \i Format \i Result
2591 \row \i dd.MM.yyyy \i 21.05.2001
2592 \row \i ddd MMMM d yy \i Tue May 21 01
2593 \row \i hh:mm:ss.zzz \i 14:13:09.042
2594 \row \i h:m:s ap \i 2:13:9 pm
2595 \endtable
2596
2597 If the datetime is invalid, an empty string will be returned.
2598
2599 \sa QDate::toString() QTime::toString()
2600 */
toString(const QString & format) const2601 QString QDateTime::toString(const QString& format) const
2602 {
2603 return fmtDateTime(format, &d->time, &d->date);
2604 }
2605 #endif //QT_NO_DATESTRING
2606
2607 /*!
2608 Returns a QDateTime object containing a datetime \a ndays days
2609 later than the datetime of this object (or earlier if \a ndays is
2610 negative).
2611
2612 \sa daysTo(), addMonths(), addYears(), addSecs()
2613 */
2614
addDays(int ndays) const2615 QDateTime QDateTime::addDays(int ndays) const
2616 {
2617 return QDateTime(d->date.addDays(ndays), d->time, timeSpec());
2618 }
2619
2620 /*!
2621 Returns a QDateTime object containing a datetime \a nmonths months
2622 later than the datetime of this object (or earlier if \a nmonths
2623 is negative).
2624
2625 \sa daysTo(), addDays(), addYears(), addSecs()
2626 */
2627
addMonths(int nmonths) const2628 QDateTime QDateTime::addMonths(int nmonths) const
2629 {
2630 return QDateTime(d->date.addMonths(nmonths), d->time, timeSpec());
2631 }
2632
2633 /*!
2634 Returns a QDateTime object containing a datetime \a nyears years
2635 later than the datetime of this object (or earlier if \a nyears is
2636 negative).
2637
2638 \sa daysTo(), addDays(), addMonths(), addSecs()
2639 */
2640
addYears(int nyears) const2641 QDateTime QDateTime::addYears(int nyears) const
2642 {
2643 return QDateTime(d->date.addYears(nyears), d->time, timeSpec());
2644 }
2645
addMSecs(const QDateTime & dt,qint64 msecs)2646 QDateTime QDateTimePrivate::addMSecs(const QDateTime &dt, qint64 msecs)
2647 {
2648 QDate utcDate;
2649 QTime utcTime;
2650 dt.d->getUTC(utcDate, utcTime);
2651
2652 addMSecs(utcDate, utcTime, msecs);
2653
2654 return QDateTime(utcDate, utcTime, Qt::UTC).toTimeSpec(dt.timeSpec());
2655 }
2656
2657 /*!
2658 Adds \a msecs to utcDate and \a utcTime as appropriate. It is assumed that
2659 utcDate and utcTime are adjusted to UTC.
2660
2661 \since 4.5
2662 \internal
2663 */
addMSecs(QDate & utcDate,QTime & utcTime,qint64 msecs)2664 void QDateTimePrivate::addMSecs(QDate &utcDate, QTime &utcTime, qint64 msecs)
2665 {
2666 uint dd = utcDate.jd;
2667 int tt = utcTime.ds();
2668 int sign = 1;
2669 if (msecs < 0) {
2670 msecs = -msecs;
2671 sign = -1;
2672 }
2673 if (msecs >= int(MSECS_PER_DAY)) {
2674 dd += sign * (msecs / MSECS_PER_DAY);
2675 msecs %= MSECS_PER_DAY;
2676 }
2677
2678 tt += sign * msecs;
2679 if (tt < 0) {
2680 tt = MSECS_PER_DAY - tt - 1;
2681 dd -= tt / MSECS_PER_DAY;
2682 tt = tt % MSECS_PER_DAY;
2683 tt = MSECS_PER_DAY - tt - 1;
2684 } else if (tt >= int(MSECS_PER_DAY)) {
2685 dd += tt / MSECS_PER_DAY;
2686 tt = tt % MSECS_PER_DAY;
2687 }
2688
2689 utcDate.jd = dd;
2690 utcTime.mds = tt;
2691 }
2692
2693 /*!
2694 Returns a QDateTime object containing a datetime \a s seconds
2695 later than the datetime of this object (or earlier if \a s is
2696 negative).
2697
2698 \sa addMSecs(), secsTo(), addDays(), addMonths(), addYears()
2699 */
2700
addSecs(int s) const2701 QDateTime QDateTime::addSecs(int s) const
2702 {
2703 return d->addMSecs(*this, qint64(s) * 1000);
2704 }
2705
2706 /*!
2707 Returns a QDateTime object containing a datetime \a msecs miliseconds
2708 later than the datetime of this object (or earlier if \a msecs is
2709 negative).
2710
2711 \sa addSecs(), msecsTo(), addDays(), addMonths(), addYears()
2712 */
addMSecs(qint64 msecs) const2713 QDateTime QDateTime::addMSecs(qint64 msecs) const
2714 {
2715 return d->addMSecs(*this, msecs);
2716 }
2717
2718 /*!
2719 Returns the number of days from this datetime to the \a other
2720 datetime. If the \a other datetime is earlier than this datetime,
2721 the value returned is negative.
2722
2723 \sa addDays(), secsTo(), msecsTo()
2724 */
2725
daysTo(const QDateTime & other) const2726 int QDateTime::daysTo(const QDateTime &other) const
2727 {
2728 return d->date.daysTo(other.d->date);
2729 }
2730
2731 /*!
2732 Returns the number of seconds from this datetime to the \a other
2733 datetime. If the \a other datetime is earlier than this datetime,
2734 the value returned is negative.
2735
2736 Before performing the comparison, the two datetimes are converted
2737 to Qt::UTC to ensure that the result is correct if one of the two
2738 datetimes has daylight saving time (DST) and the other doesn't.
2739
2740 Example:
2741 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 11
2742
2743 \sa addSecs(), daysTo(), QTime::secsTo()
2744 */
2745
secsTo(const QDateTime & other) const2746 int QDateTime::secsTo(const QDateTime &other) const
2747 {
2748 QDate date1, date2;
2749 QTime time1, time2;
2750
2751 d->getUTC(date1, time1);
2752 other.d->getUTC(date2, time2);
2753
2754 return (date1.daysTo(date2) * SECS_PER_DAY) + time1.secsTo(time2);
2755 }
2756
2757 /*!
2758 \since 4.7
2759
2760 Returns the number of milliseconds from this datetime to the \a other
2761 datetime. If the \a other datetime is earlier than this datetime,
2762 the value returned is negative.
2763
2764 Before performing the comparison, the two datetimes are converted
2765 to Qt::UTC to ensure that the result is correct if one of the two
2766 datetimes has daylight saving time (DST) and the other doesn't.
2767
2768 \sa addMSecs(), daysTo(), QTime::msecsTo()
2769 */
2770
msecsTo(const QDateTime & other) const2771 qint64 QDateTime::msecsTo(const QDateTime &other) const
2772 {
2773 QDate selfDate;
2774 QDate otherDate;
2775 QTime selfTime;
2776 QTime otherTime;
2777
2778 d->getUTC(selfDate, selfTime);
2779 other.d->getUTC(otherDate, otherTime);
2780
2781 return (static_cast<qint64>(selfDate.daysTo(otherDate)) * static_cast<qint64>(MSECS_PER_DAY))
2782 + static_cast<qint64>(selfTime.msecsTo(otherTime));
2783 }
2784
2785
2786 /*!
2787 \fn QDateTime QDateTime::toTimeSpec(Qt::TimeSpec specification) const
2788
2789 Returns a copy of this datetime configured to use the given time
2790 \a specification.
2791
2792 \sa timeSpec(), toUTC(), toLocalTime()
2793 */
2794
toTimeSpec(Qt::TimeSpec spec) const2795 QDateTime QDateTime::toTimeSpec(Qt::TimeSpec spec) const
2796 {
2797 if ((d->spec == QDateTimePrivate::UTC) == (spec == Qt::UTC))
2798 return *this;
2799
2800 QDateTime ret;
2801 if (spec == Qt::UTC) {
2802 d->getUTC(ret.d->date, ret.d->time);
2803 ret.d->spec = QDateTimePrivate::UTC;
2804 } else {
2805 ret.d->spec = d->getLocal(ret.d->date, ret.d->time);
2806 }
2807 return ret;
2808 }
2809
2810 /*!
2811 Returns true if this datetime is equal to the \a other datetime;
2812 otherwise returns false.
2813
2814 \sa operator!=()
2815 */
2816
operator ==(const QDateTime & other) const2817 bool QDateTime::operator==(const QDateTime &other) const
2818 {
2819 if (d->spec == other.d->spec && d->utcOffset == other.d->utcOffset)
2820 return d->time == other.d->time && d->date == other.d->date;
2821 else {
2822 QDate date1, date2;
2823 QTime time1, time2;
2824
2825 d->getUTC(date1, time1);
2826 other.d->getUTC(date2, time2);
2827 return time1 == time2 && date1 == date2;
2828 }
2829 }
2830
2831 /*!
2832 \fn bool QDateTime::operator!=(const QDateTime &other) const
2833
2834 Returns true if this datetime is different from the \a other
2835 datetime; otherwise returns false.
2836
2837 Two datetimes are different if either the date, the time, or the
2838 time zone components are different.
2839
2840 \sa operator==()
2841 */
2842
2843 /*!
2844 Returns true if this datetime is earlier than the \a other
2845 datetime; otherwise returns false.
2846 */
2847
operator <(const QDateTime & other) const2848 bool QDateTime::operator<(const QDateTime &other) const
2849 {
2850 if (d->spec == other.d->spec && d->spec != QDateTimePrivate::OffsetFromUTC) {
2851 if (d->date != other.d->date)
2852 return d->date < other.d->date;
2853 return d->time < other.d->time;
2854 } else {
2855 QDate date1, date2;
2856 QTime time1, time2;
2857 d->getUTC(date1, time1);
2858 other.d->getUTC(date2, time2);
2859 if (date1 != date2)
2860 return date1 < date2;
2861 return time1 < time2;
2862 }
2863 }
2864
2865 /*!
2866 \fn bool QDateTime::operator<=(const QDateTime &other) const
2867
2868 Returns true if this datetime is earlier than or equal to the
2869 \a other datetime; otherwise returns false.
2870 */
2871
2872 /*!
2873 \fn bool QDateTime::operator>(const QDateTime &other) const
2874
2875 Returns true if this datetime is later than the \a other datetime;
2876 otherwise returns false.
2877 */
2878
2879 /*!
2880 \fn bool QDateTime::operator>=(const QDateTime &other) const
2881
2882 Returns true if this datetime is later than or equal to the
2883 \a other datetime; otherwise returns false.
2884 */
2885
2886 /*!
2887 \fn QDateTime QDateTime::currentDateTime()
2888 Returns the current datetime, as reported by the system clock, in
2889 the local time zone.
2890
2891 \sa currentDateTimeUtc(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
2892 */
2893
2894 /*!
2895 \fn QDateTime QDateTime::currentDateTimeUtc()
2896 \since 4.7
2897 Returns the current datetime, as reported by the system clock, in
2898 UTC.
2899
2900 \sa currentDateTime(), QDate::currentDate(), QTime::currentTime(), toTimeSpec()
2901 */
2902
2903 /*!
2904 \fn qint64 QDateTime::currentMSecsSinceEpoch()
2905 \since 4.7
2906
2907 Returns the number of milliseconds since 1970-01-01T00:00:00 Universal
2908 Coordinated Time. This number is like the POSIX time_t variable, but
2909 expressed in milliseconds instead.
2910
2911 \sa currentDateTime(), currentDateTimeUtc(), toTime_t(), toTimeSpec()
2912 */
2913
msecsFromDecomposed(int hour,int minute,int sec,int msec=0)2914 static inline uint msecsFromDecomposed(int hour, int minute, int sec, int msec = 0)
2915 {
2916 return MSECS_PER_HOUR * hour + MSECS_PER_MIN * minute + 1000 * sec + msec;
2917 }
2918
2919 #if defined(Q_OS_WIN)
currentDate()2920 QDate QDate::currentDate()
2921 {
2922 QDate d;
2923 SYSTEMTIME st;
2924 memset(&st, 0, sizeof(SYSTEMTIME));
2925 GetLocalTime(&st);
2926 d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
2927 return d;
2928 }
2929
currentTime()2930 QTime QTime::currentTime()
2931 {
2932 QTime ct;
2933 SYSTEMTIME st;
2934 memset(&st, 0, sizeof(SYSTEMTIME));
2935 GetLocalTime(&st);
2936 ct.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
2937 #if defined(Q_OS_WINCE)
2938 ct.startTick = GetTickCount() % MSECS_PER_DAY;
2939 #endif
2940 return ct;
2941 }
2942
currentDateTime()2943 QDateTime QDateTime::currentDateTime()
2944 {
2945 QDate d;
2946 QTime t;
2947 SYSTEMTIME st;
2948 memset(&st, 0, sizeof(SYSTEMTIME));
2949 GetLocalTime(&st);
2950 d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
2951 t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
2952 return QDateTime(d, t);
2953 }
2954
currentDateTimeUtc()2955 QDateTime QDateTime::currentDateTimeUtc()
2956 {
2957 QDate d;
2958 QTime t;
2959 SYSTEMTIME st;
2960 memset(&st, 0, sizeof(SYSTEMTIME));
2961 GetSystemTime(&st);
2962 d.jd = julianDayFromDate(st.wYear, st.wMonth, st.wDay);
2963 t.mds = msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
2964 return QDateTime(d, t, Qt::UTC);
2965 }
2966
currentMSecsSinceEpoch()2967 qint64 QDateTime::currentMSecsSinceEpoch()
2968 {
2969 QDate d;
2970 QTime t;
2971 SYSTEMTIME st;
2972 memset(&st, 0, sizeof(SYSTEMTIME));
2973 GetSystemTime(&st);
2974
2975 return msecsFromDecomposed(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds) +
2976 qint64(julianDayFromGregorianDate(st.wYear, st.wMonth, st.wDay)
2977 - julianDayFromGregorianDate(1970, 1, 1)) * Q_INT64_C(86400000);
2978 }
2979
2980 #elif defined(Q_OS_SYMBIAN)
currentDate()2981 QDate QDate::currentDate()
2982 {
2983 QDate d;
2984 TTime localTime;
2985 localTime.HomeTime();
2986 TDateTime localDateTime = localTime.DateTime();
2987 // months and days are zero indexed
2988 d.jd = julianDayFromDate(localDateTime.Year(), localDateTime.Month() + 1, localDateTime.Day() + 1 );
2989 return d;
2990 }
2991
currentTime()2992 QTime QTime::currentTime()
2993 {
2994 QTime ct;
2995 TTime localTime;
2996 localTime.HomeTime();
2997 TDateTime localDateTime = localTime.DateTime();
2998 ct.mds = msecsFromDecomposed(localDateTime.Hour(), localDateTime.Minute(),
2999 localDateTime.Second(), localDateTime.MicroSecond() / 1000);
3000 return ct;
3001 }
3002
currentDateTime()3003 QDateTime QDateTime::currentDateTime()
3004 {
3005 QDate d;
3006 QTime ct;
3007 TTime localTime;
3008 localTime.HomeTime();
3009 TDateTime localDateTime = localTime.DateTime();
3010 // months and days are zero indexed
3011 d.jd = julianDayFromDate(localDateTime.Year(), localDateTime.Month() + 1, localDateTime.Day() + 1);
3012 ct.mds = msecsFromDecomposed(localDateTime.Hour(), localDateTime.Minute(),
3013 localDateTime.Second(), localDateTime.MicroSecond() / 1000);
3014 return QDateTime(d, ct);
3015 }
3016
currentDateTimeUtc()3017 QDateTime QDateTime::currentDateTimeUtc()
3018 {
3019 QDate d;
3020 QTime ct;
3021 TTime gmTime;
3022 gmTime.UniversalTime();
3023 TDateTime gmtDateTime = gmTime.DateTime();
3024 // months and days are zero indexed
3025 d.jd = julianDayFromDate(gmtDateTime.Year(), gmtDateTime.Month() + 1, gmtDateTime.Day() + 1);
3026 ct.mds = msecsFromDecomposed(gmtDateTime.Hour(), gmtDateTime.Minute(),
3027 gmtDateTime.Second(), gmtDateTime.MicroSecond() / 1000);
3028 return QDateTime(d, ct, Qt::UTC);
3029 }
3030
currentMSecsSinceEpoch()3031 qint64 QDateTime::currentMSecsSinceEpoch()
3032 {
3033 QDate d;
3034 QTime ct;
3035 TTime gmTime;
3036 gmTime.UniversalTime();
3037 TDateTime gmtDateTime = gmTime.DateTime();
3038
3039 // according to the documentation, the value is:
3040 // "a date and time as a number of microseconds since midnight, January 1st, 0 AD nominal Gregorian"
3041 qint64 value = gmTime.Int64();
3042
3043 // whereas 1970-01-01T00:00:00 is (in the same representation):
3044 // ((1970 * 365) + (1970 / 4) - (1970 / 100) + (1970 / 400) - 13) * 86400 * 1000000
3045 static const qint64 unixEpoch = Q_INT64_C(0xdcddb30f2f8000);
3046
3047 return (value - unixEpoch) / 1000;
3048 }
3049
3050 #elif defined(Q_OS_UNIX)
currentDate()3051 QDate QDate::currentDate()
3052 {
3053 QDate d;
3054 // posix compliant system
3055 time_t ltime;
3056 time(<ime);
3057 struct tm *t = 0;
3058
3059 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3060 // use the reentrant version of localtime() where available
3061 tzset();
3062 struct tm res;
3063 t = localtime_r(<ime, &res);
3064 #else
3065 t = localtime(<ime);
3066 #endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
3067
3068 d.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
3069 return d;
3070 }
3071
currentTime()3072 QTime QTime::currentTime()
3073 {
3074 QTime ct;
3075 // posix compliant system
3076 struct timeval tv;
3077 gettimeofday(&tv, 0);
3078 time_t ltime = tv.tv_sec;
3079 struct tm *t = 0;
3080
3081 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3082 // use the reentrant version of localtime() where available
3083 tzset();
3084 struct tm res;
3085 t = localtime_r(<ime, &res);
3086 #else
3087 t = localtime(<ime);
3088 #endif
3089 Q_CHECK_PTR(t);
3090
3091 ct.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
3092 return ct;
3093 }
3094
currentDateTime()3095 QDateTime QDateTime::currentDateTime()
3096 {
3097 // posix compliant system
3098 // we have milliseconds
3099 struct timeval tv;
3100 gettimeofday(&tv, 0);
3101 time_t ltime = tv.tv_sec;
3102 struct tm *t = 0;
3103
3104 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3105 // use the reentrant version of localtime() where available
3106 tzset();
3107 struct tm res;
3108 t = localtime_r(<ime, &res);
3109 #else
3110 t = localtime(<ime);
3111 #endif
3112
3113 QDateTime dt;
3114 dt.d->time.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
3115
3116 dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
3117 dt.d->spec = t->tm_isdst > 0 ? QDateTimePrivate::LocalDST :
3118 t->tm_isdst == 0 ? QDateTimePrivate::LocalStandard :
3119 QDateTimePrivate::LocalUnknown;
3120 return dt;
3121 }
3122
currentDateTimeUtc()3123 QDateTime QDateTime::currentDateTimeUtc()
3124 {
3125 // posix compliant system
3126 // we have milliseconds
3127 struct timeval tv;
3128 gettimeofday(&tv, 0);
3129 time_t ltime = tv.tv_sec;
3130 struct tm *t = 0;
3131
3132 #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
3133 // use the reentrant version of localtime() where available
3134 struct tm res;
3135 t = gmtime_r(<ime, &res);
3136 #else
3137 t = gmtime(<ime);
3138 #endif
3139
3140 QDateTime dt;
3141 dt.d->time.mds = msecsFromDecomposed(t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec / 1000);
3142
3143 dt.d->date.jd = julianDayFromDate(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
3144 dt.d->spec = QDateTimePrivate::UTC;
3145 return dt;
3146 }
3147
currentMSecsSinceEpoch()3148 qint64 QDateTime::currentMSecsSinceEpoch()
3149 {
3150 // posix compliant system
3151 // we have milliseconds
3152 struct timeval tv;
3153 gettimeofday(&tv, 0);
3154 return qint64(tv.tv_sec) * Q_INT64_C(1000) + tv.tv_usec / 1000;
3155 }
3156
3157 #else
3158 #error "What system is this?"
3159 #endif
3160
3161 /*!
3162 \since 4.2
3163
3164 Returns a datetime whose date and time are the number of \a seconds
3165 that have passed since 1970-01-01T00:00:00, Coordinated Universal
3166 Time (Qt::UTC). On systems that do not support time zones, the time
3167 will be set as if local time were Qt::UTC.
3168
3169 \sa toTime_t(), setTime_t()
3170 */
fromTime_t(uint seconds)3171 QDateTime QDateTime::fromTime_t(uint seconds)
3172 {
3173 QDateTime d;
3174 d.setTime_t(seconds);
3175 return d;
3176 }
3177
3178 /*!
3179 \since 4.7
3180
3181 Returns a datetime whose date and time are the number of milliseconds, \a msecs,
3182 that have passed since 1970-01-01T00:00:00.000, Coordinated Universal
3183 Time (Qt::UTC). On systems that do not support time zones, the time
3184 will be set as if local time were Qt::UTC.
3185
3186 Note that there are possible values for \a msecs that lie outside the valid
3187 range of QDateTime, both negative and positive. The behavior of this
3188 function is undefined for those values.
3189
3190 \sa toTime_t(), setTime_t()
3191 */
fromMSecsSinceEpoch(qint64 msecs)3192 QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
3193 {
3194 QDateTime d;
3195 d.setMSecsSinceEpoch(msecs);
3196 return d;
3197 }
3198
3199 /*!
3200 \since 4.4
3201 \internal
3202
3203 Sets the offset from UTC to \a seconds, and also sets timeSpec() to
3204 Qt::OffsetFromUTC.
3205
3206 The maximum and minimum offset is 14 positive or negative hours. If
3207 \a seconds is larger or smaller than that, the result is undefined.
3208
3209 0 as offset is identical to UTC. Therefore, if \a seconds is 0, the
3210 timeSpec() will be set to Qt::UTC. Hence the UTC offset always
3211 relates to UTC, and can never relate to local time.
3212
3213 \sa isValid(), utcOffset()
3214 */
setUtcOffset(int seconds)3215 void QDateTime::setUtcOffset(int seconds)
3216 {
3217 detach();
3218
3219 /* The motivation to also setting d->spec is to ensure that the QDateTime
3220 * instance stay in well-defined states all the time, instead of that
3221 * we instruct the user to ensure it. */
3222 if(seconds == 0)
3223 d->spec = QDateTimePrivate::UTC;
3224 else
3225 d->spec = QDateTimePrivate::OffsetFromUTC;
3226
3227 /* Even if seconds is 0 we assign it to utcOffset. */
3228 d->utcOffset = seconds;
3229 }
3230
3231 /*!
3232 \since 4.4
3233 \internal
3234
3235 Returns the UTC offset in seconds. If the timeSpec() isn't
3236 Qt::OffsetFromUTC, 0 is returned. However, since 0 is a valid UTC
3237 offset the return value of this function cannot be used to determine
3238 whether a utcOffset() is used or is valid, timeSpec() must be
3239 checked.
3240
3241 Likewise, if this QDateTime() is invalid or if timeSpec() isn't
3242 Qt::OffsetFromUTC, 0 is returned.
3243
3244 The UTC offset only applies if the timeSpec() is Qt::OffsetFromUTC.
3245
3246 \sa isValid(), setUtcOffset()
3247 */
utcOffset() const3248 int QDateTime::utcOffset() const
3249 {
3250 if(isValid() && d->spec == QDateTimePrivate::OffsetFromUTC)
3251 return d->utcOffset;
3252 else
3253 return 0;
3254 }
3255
3256 #ifndef QT_NO_DATESTRING
3257
fromShortMonthName(const QString & monthName)3258 static int fromShortMonthName(const QString &monthName)
3259 {
3260 // Assume that English monthnames are the default
3261 for (int i = 0; i < 12; ++i) {
3262 if (monthName == QLatin1String(qt_shortMonthNames[i]))
3263 return i + 1;
3264 }
3265 // If English names can't be found, search the localized ones
3266 for (int i = 1; i <= 12; ++i) {
3267 if (monthName == QDate::shortMonthName(i))
3268 return i;
3269 }
3270 return -1;
3271 }
3272
3273 /*!
3274 \fn QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
3275
3276 Returns the QDateTime represented by the \a string, using the
3277 \a format given, or an invalid datetime if this is not possible.
3278
3279 Note for Qt::TextDate: It is recommended that you use the
3280 English short month names (e.g. "Jan"). Although localized month
3281 names can also be used, they depend on the user's locale settings.
3282 */
fromString(const QString & s,Qt::DateFormat f)3283 QDateTime QDateTime::fromString(const QString& s, Qt::DateFormat f)
3284 {
3285 if (s.isEmpty()) {
3286 return QDateTime();
3287 }
3288
3289 switch (f) {
3290 case Qt::ISODate: {
3291 QString tmp = s;
3292 Qt::TimeSpec ts = Qt::LocalTime;
3293 const QDate date = QDate::fromString(tmp.left(10), Qt::ISODate);
3294 if (tmp.size() == 10)
3295 return QDateTime(date);
3296
3297 tmp = tmp.mid(11);
3298
3299 // Recognize UTC specifications
3300 if (tmp.endsWith(QLatin1Char('Z'))) {
3301 ts = Qt::UTC;
3302 tmp.chop(1);
3303 }
3304
3305 // Recognize timezone specifications
3306 QRegExp rx(QLatin1String("[+-]"));
3307 if (tmp.contains(rx)) {
3308 int idx = tmp.indexOf(rx);
3309 QString tmp2 = tmp.mid(idx);
3310 tmp = tmp.left(idx);
3311 bool ok = true;
3312 int ntzhour = 1;
3313 int ntzminute = 3;
3314 if ( tmp2.indexOf(QLatin1Char(':')) == 3 )
3315 ntzminute = 4;
3316 const int tzhour(tmp2.mid(ntzhour, 2).toInt(&ok));
3317 const int tzminute(tmp2.mid(ntzminute, 2).toInt(&ok));
3318 QTime tzt(tzhour, tzminute);
3319 int utcOffset = (tzt.hour() * 60 + tzt.minute()) * 60;
3320 if ( utcOffset != 0 ) {
3321 ts = Qt::OffsetFromUTC;
3322 QDateTime dt(date, QTime::fromString(tmp, Qt::ISODate), ts);
3323 dt.setUtcOffset( utcOffset * (tmp2.startsWith(QLatin1Char('-')) ? -1 : 1) );
3324 return dt;
3325 }
3326 }
3327 return QDateTime(date, QTime::fromString(tmp, Qt::ISODate), ts);
3328 }
3329 case Qt::SystemLocaleDate:
3330 case Qt::SystemLocaleShortDate:
3331 case Qt::SystemLocaleLongDate:
3332 return fromString(s, QLocale::system().dateTimeFormat(f == Qt::SystemLocaleLongDate ? QLocale::LongFormat
3333 : QLocale::ShortFormat));
3334 case Qt::LocaleDate:
3335 case Qt::DefaultLocaleShortDate:
3336 case Qt::DefaultLocaleLongDate:
3337 return fromString(s, QLocale().dateTimeFormat(f == Qt::DefaultLocaleLongDate ? QLocale::LongFormat
3338 : QLocale::ShortFormat));
3339 #if !defined(QT_NO_TEXTDATE)
3340 case Qt::TextDate: {
3341 QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts);
3342
3343 if ((parts.count() < 5) || (parts.count() > 6)) {
3344 return QDateTime();
3345 }
3346
3347 // Accept "Sun Dec 1 13:02:00 1974" and "Sun 1. Dec 13:02:00 1974"
3348 int month = -1, day = -1;
3349 bool ok;
3350
3351 month = fromShortMonthName(parts.at(1));
3352 if (month != -1) {
3353 day = parts.at(2).toInt(&ok);
3354 if (!ok)
3355 day = -1;
3356 }
3357
3358 if (month == -1 || day == -1) {
3359 // first variant failed, lets try the other
3360 month = fromShortMonthName(parts.at(2));
3361 if (month != -1) {
3362 QString dayStr = parts.at(1);
3363 if (dayStr.endsWith(QLatin1Char('.'))) {
3364 dayStr.chop(1);
3365 day = dayStr.toInt(&ok);
3366 if (!ok)
3367 day = -1;
3368 } else {
3369 day = -1;
3370 }
3371 }
3372 }
3373
3374 if (month == -1 || day == -1) {
3375 // both variants failed, give up
3376 return QDateTime();
3377 }
3378
3379 int year;
3380 QStringList timeParts = parts.at(3).split(QLatin1Char(':'));
3381 if ((timeParts.count() == 3) || (timeParts.count() == 2)) {
3382 year = parts.at(4).toInt(&ok);
3383 if (!ok)
3384 return QDateTime();
3385 } else {
3386 timeParts = parts.at(4).split(QLatin1Char(':'));
3387 if ((timeParts.count() != 3) && (timeParts.count() != 2))
3388 return QDateTime();
3389 year = parts.at(3).toInt(&ok);
3390 if (!ok)
3391 return QDateTime();
3392 }
3393
3394 int hour = timeParts.at(0).toInt(&ok);
3395 if (!ok) {
3396 return QDateTime();
3397 }
3398
3399 int minute = timeParts.at(1).toInt(&ok);
3400 if (!ok) {
3401 return QDateTime();
3402 }
3403
3404 int second = (timeParts.count() > 2) ? timeParts.at(2).toInt(&ok) : 0;
3405 if (!ok) {
3406 return QDateTime();
3407 }
3408
3409 QDate date(year, month, day);
3410 QTime time(hour, minute, second);
3411
3412 if (parts.count() == 5)
3413 return QDateTime(date, time, Qt::LocalTime);
3414
3415 QString tz = parts.at(5);
3416 if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
3417 return QDateTime();
3418 QDateTime dt(date, time, Qt::UTC);
3419 if (tz.length() > 3) {
3420 int tzoffset = 0;
3421 QChar sign = tz.at(3);
3422 if ((sign != QLatin1Char('+'))
3423 && (sign != QLatin1Char('-'))) {
3424 return QDateTime();
3425 }
3426 int tzhour = tz.mid(4, 2).toInt(&ok);
3427 if (!ok)
3428 return QDateTime();
3429 int tzminute = tz.mid(6).toInt(&ok);
3430 if (!ok)
3431 return QDateTime();
3432 tzoffset = (tzhour*60 + tzminute) * 60;
3433 if (sign == QLatin1Char('-'))
3434 tzoffset = -tzoffset;
3435 dt.setUtcOffset(tzoffset);
3436 }
3437 return dt.toLocalTime();
3438 }
3439 #endif //QT_NO_TEXTDATE
3440 }
3441
3442 return QDateTime();
3443 }
3444
3445 /*!
3446 \fn QDateTime::fromString(const QString &string, const QString &format)
3447
3448 Returns the QDateTime represented by the \a string, using the \a
3449 format given, or an invalid datetime if the string cannot be parsed.
3450
3451 These expressions may be used for the date part of the format string:
3452
3453 \table
3454 \header \i Expression \i Output
3455 \row \i d \i the day as number without a leading zero (1 to 31)
3456 \row \i dd \i the day as number with a leading zero (01 to 31)
3457 \row \i ddd
3458 \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
3459 Uses QDate::shortDayName().
3460 \row \i dddd
3461 \i the long localized day name (e.g. 'Monday' to 'Sunday').
3462 Uses QDate::longDayName().
3463 \row \i M \i the month as number without a leading zero (1-12)
3464 \row \i MM \i the month as number with a leading zero (01-12)
3465 \row \i MMM
3466 \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
3467 Uses QDate::shortMonthName().
3468 \row \i MMMM
3469 \i the long localized month name (e.g. 'January' to 'December').
3470 Uses QDate::longMonthName().
3471 \row \i yy \i the year as two digit number (00-99)
3472 \row \i yyyy \i the year as four digit number
3473 \endtable
3474
3475 \note Unlike the other version of this function, day and month names must
3476 be given in the user's local language. It is only possible to use the English
3477 names if the user's language is English.
3478
3479 These expressions may be used for the time part of the format string:
3480
3481 \table
3482 \header \i Expression \i Output
3483 \row \i h
3484 \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
3485 \row \i hh
3486 \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
3487 \row \i H
3488 \i the hour without a leading zero (0 to 23, even with AM/PM display)
3489 \row \i HH
3490 \i the hour with a leading zero (00 to 23, even with AM/PM display)
3491 \row \i m \i the minute without a leading zero (0 to 59)
3492 \row \i mm \i the minute with a leading zero (00 to 59)
3493 \row \i s \i the second without a leading zero (0 to 59)
3494 \row \i ss \i the second with a leading zero (00 to 59)
3495 \row \i z \i the milliseconds without leading zeroes (0 to 999)
3496 \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
3497 \row \i AP or A
3498 \i interpret as an AM/PM time. \e AP must be either "AM" or "PM".
3499 \row \i ap or a
3500 \i Interpret as an AM/PM time. \e ap must be either "am" or "pm".
3501 \endtable
3502
3503 All other input characters will be treated as text. Any sequence
3504 of characters that are enclosed in singlequotes will also be
3505 treated as text and not be used as an expression.
3506
3507 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 12
3508
3509 If the format is not satisfied an invalid QDateTime is returned.
3510 The expressions that don't have leading zeroes (d, M, h, m, s, z) will be
3511 greedy. This means that they will use two digits even if this will
3512 put them outside the range and/or leave too few digits for other
3513 sections.
3514
3515 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 13
3516
3517 This could have meant 1 January 00:30.00 but the M will grab
3518 two digits.
3519
3520 For any field that is not represented in the format the following
3521 defaults are used:
3522
3523 \table
3524 \header \i Field \i Default value
3525 \row \i Year \i 1900
3526 \row \i Month \i 1 (January)
3527 \row \i Day \i 1
3528 \row \i Hour \i 0
3529 \row \i Minute \i 0
3530 \row \i Second \i 0
3531 \endtable
3532
3533 For example:
3534
3535 \snippet doc/src/snippets/code/src_corelib_tools_qdatetime.cpp 14
3536
3537 \sa QDate::fromString() QTime::fromString() QDate::toString()
3538 QDateTime::toString() QTime::toString()
3539 */
3540
fromString(const QString & string,const QString & format)3541 QDateTime QDateTime::fromString(const QString &string, const QString &format)
3542 {
3543 #ifndef QT_BOOTSTRAPPED
3544 QTime time;
3545 QDate date;
3546
3547 QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString);
3548 if (dt.parseFormat(format) && dt.fromString(string, &date, &time))
3549 return QDateTime(date, time);
3550 #else
3551 Q_UNUSED(string);
3552 Q_UNUSED(format);
3553 #endif
3554 return QDateTime(QDate(), QTime(-1, -1, -1));
3555 }
3556
3557 #endif // QT_NO_DATESTRING
3558 /*!
3559 \fn QDateTime QDateTime::toLocalTime() const
3560
3561 Returns a datetime containing the date and time information in
3562 this datetime, but specified using the Qt::LocalTime definition.
3563
3564 \sa toTimeSpec()
3565 */
3566
3567 /*!
3568 \fn QDateTime QDateTime::toUTC() const
3569
3570 Returns a datetime containing the date and time information in
3571 this datetime, but specified using the Qt::UTC definition.
3572
3573 \sa toTimeSpec()
3574 */
3575
3576 /*! \internal
3577 */
detach()3578 void QDateTime::detach()
3579 {
3580 d.detach();
3581 }
3582
3583 /*****************************************************************************
3584 Date/time stream functions
3585 *****************************************************************************/
3586
3587 #ifndef QT_NO_DATASTREAM
3588 /*!
3589 \relates QDate
3590
3591 Writes the \a date to stream \a out.
3592
3593 \sa {Serializing Qt Data Types}
3594 */
3595
operator <<(QDataStream & out,const QDate & date)3596 QDataStream &operator<<(QDataStream &out, const QDate &date)
3597 {
3598 return out << (quint32)(date.jd);
3599 }
3600
3601 /*!
3602 \relates QDate
3603
3604 Reads a date from stream \a in into the \a date.
3605
3606 \sa {Serializing Qt Data Types}
3607 */
3608
operator >>(QDataStream & in,QDate & date)3609 QDataStream &operator>>(QDataStream &in, QDate &date)
3610 {
3611 quint32 jd;
3612 in >> jd;
3613 date.jd = jd;
3614 return in;
3615 }
3616
3617 /*!
3618 \relates QTime
3619
3620 Writes \a time to stream \a out.
3621
3622 \sa {Serializing Qt Data Types}
3623 */
3624
operator <<(QDataStream & out,const QTime & time)3625 QDataStream &operator<<(QDataStream &out, const QTime &time)
3626 {
3627 return out << quint32(time.mds);
3628 }
3629
3630 /*!
3631 \relates QTime
3632
3633 Reads a time from stream \a in into the given \a time.
3634
3635 \sa {Serializing Qt Data Types}
3636 */
3637
operator >>(QDataStream & in,QTime & time)3638 QDataStream &operator>>(QDataStream &in, QTime &time)
3639 {
3640 quint32 ds;
3641 in >> ds;
3642 time.mds = int(ds);
3643 return in;
3644 }
3645
3646 /*!
3647 \relates QDateTime
3648
3649 Writes \a dateTime to the \a out stream.
3650
3651 \sa {Serializing Qt Data Types}
3652 */
operator <<(QDataStream & out,const QDateTime & dateTime)3653 QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
3654 {
3655 out << dateTime.d->date << dateTime.d->time;
3656 if (out.version() >= 7)
3657 out << (qint8)dateTime.d->spec;
3658 return out;
3659 }
3660
3661 /*!
3662 \relates QDateTime
3663
3664 Reads a datetime from the stream \a in into \a dateTime.
3665
3666 \sa {Serializing Qt Data Types}
3667 */
3668
operator >>(QDataStream & in,QDateTime & dateTime)3669 QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
3670 {
3671 dateTime.detach();
3672
3673 qint8 ts = (qint8)QDateTimePrivate::LocalUnknown;
3674 in >> dateTime.d->date >> dateTime.d->time;
3675 if (in.version() >= 7)
3676 in >> ts;
3677 dateTime.d->spec = (QDateTimePrivate::Spec)ts;
3678 return in;
3679 }
3680 #endif // QT_NO_DATASTREAM
3681
3682
3683 /*!
3684 \fn QString QDate::monthName(int month)
3685
3686 Use shortMonthName() instead.
3687 */
3688
3689 /*!
3690 \fn QString QDate::dayName(int weekday)
3691
3692 Use shortDayName() instead.
3693 */
3694
3695 /*!
3696 \fn bool QDate::leapYear(int year)
3697
3698 Use isLeapYear() instead.
3699 */
3700
3701 /*!
3702 \fn QDate QDate::currentDate(Qt::TimeSpec spec)
3703
3704 If \a spec is Qt::LocalTime, use the currentDate() overload that
3705 takes no parameters instead; otherwise, use
3706 QDateTime::currentDateTime().
3707
3708 \oldcode
3709 QDate localDate = QDate::currentDate(Qt::LocalTime);
3710 QDate utcDate = QDate::currentDate(Qt::UTC);
3711 \newcode
3712 QDate localDate = QDate::currentDate();
3713 QDate utcDate = QDateTime::currentDateTime().toUTC().date();
3714 \endcode
3715
3716 \sa QDateTime::toUTC()
3717 */
3718
3719 /*!
3720 \fn QTime QTime::currentTime(Qt::TimeSpec specification)
3721
3722 Returns the current time for the given \a specification.
3723
3724 To replace uses of this function where the \a specification is Qt::LocalTime,
3725 use the currentDate() overload that takes no parameters instead; otherwise,
3726 use QDateTime::currentDateTime() and convert the result to a UTC measurement.
3727
3728 \oldcode
3729 QTime localTime = QTime::currentTime(Qt::LocalTime);
3730 QTime utcTime = QTime::currentTime(Qt::UTC);
3731 \newcode
3732 QTime localTime = QTime::currentTime();
3733 QTime utcTime = QTimeTime::currentDateTime().toUTC().time();
3734 \endcode
3735
3736 \sa QDateTime::toUTC()
3737 */
3738
3739 /*!
3740 \fn void QDateTime::setTime_t(uint secsSince1Jan1970UTC, Qt::TimeSpec spec)
3741
3742 Use the single-argument overload of setTime_t() instead.
3743 */
3744
3745 /*!
3746 \fn QDateTime QDateTime::currentDateTime(Qt::TimeSpec spec)
3747
3748 Use the currentDateTime() overload that takes no parameters
3749 instead.
3750 */
3751
3752 // checks if there is an unqoted 'AP' or 'ap' in the string
hasUnquotedAP(const QString & f)3753 static bool hasUnquotedAP(const QString &f)
3754 {
3755 const QLatin1Char quote('\'');
3756 bool inquote = false;
3757 const int max = f.size();
3758 for (int i=0; i<max; ++i) {
3759 if (f.at(i) == quote) {
3760 inquote = !inquote;
3761 } else if (!inquote && f.at(i).toUpper() == QLatin1Char('A')) {
3762 return true;
3763 }
3764 }
3765 return false;
3766 }
3767
3768 #ifndef QT_NO_DATESTRING
3769 /*****************************************************************************
3770 Some static function used by QDate, QTime and QDateTime
3771 *****************************************************************************/
3772
3773 // Replaces tokens by their value. See QDateTime::toString() for a list of valid tokens
getFmtString(const QString & f,const QTime * dt=0,const QDate * dd=0,bool am_pm=false)3774 static QString getFmtString(const QString& f, const QTime* dt = 0, const QDate* dd = 0, bool am_pm = false)
3775 {
3776 if (f.isEmpty())
3777 return QString();
3778
3779 QString buf = f;
3780 int removed = 0;
3781
3782 if (dt) {
3783 if (f.startsWith(QLatin1String("hh")) || f.startsWith(QLatin1String("HH"))) {
3784 const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
3785 if (hour12 && dt->hour() > 12)
3786 buf = QString::number(dt->hour() - 12).rightJustified(2, QLatin1Char('0'), true);
3787 else if (hour12 && dt->hour() == 0)
3788 buf = QLatin1String("12");
3789 else
3790 buf = QString::number(dt->hour()).rightJustified(2, QLatin1Char('0'), true);
3791 removed = 2;
3792 } else if (f.at(0) == QLatin1Char('h') || f.at(0) == QLatin1Char('H')) {
3793 const bool hour12 = f.at(0) == QLatin1Char('h') && am_pm;
3794 if (hour12 && dt->hour() > 12)
3795 buf = QString::number(dt->hour() - 12);
3796 else if (hour12 && dt->hour() == 0)
3797 buf = QLatin1String("12");
3798 else
3799 buf = QString::number(dt->hour());
3800 removed = 1;
3801 } else if (f.startsWith(QLatin1String("mm"))) {
3802 buf = QString::number(dt->minute()).rightJustified(2, QLatin1Char('0'), true);
3803 removed = 2;
3804 } else if (f.at(0) == (QLatin1Char('m'))) {
3805 buf = QString::number(dt->minute());
3806 removed = 1;
3807 } else if (f.startsWith(QLatin1String("ss"))) {
3808 buf = QString::number(dt->second()).rightJustified(2, QLatin1Char('0'), true);
3809 removed = 2;
3810 } else if (f.at(0) == QLatin1Char('s')) {
3811 buf = QString::number(dt->second());
3812 } else if (f.startsWith(QLatin1String("zzz"))) {
3813 buf = QString::number(dt->msec()).rightJustified(3, QLatin1Char('0'), true);
3814 removed = 3;
3815 } else if (f.at(0) == QLatin1Char('z')) {
3816 buf = QString::number(dt->msec());
3817 removed = 1;
3818 } else if (f.at(0).toUpper() == QLatin1Char('A')) {
3819 const bool upper = f.at(0) == QLatin1Char('A');
3820 buf = dt->hour() < 12 ? QLatin1String("am") : QLatin1String("pm");
3821 if (upper)
3822 buf = buf.toUpper();
3823 if (f.size() > 1 && f.at(1).toUpper() == QLatin1Char('P') &&
3824 f.at(0).isUpper() == f.at(1).isUpper()) {
3825 removed = 2;
3826 } else {
3827 removed = 1;
3828 }
3829 }
3830 }
3831
3832 if (dd) {
3833 if (f.startsWith(QLatin1String("dddd"))) {
3834 buf = dd->longDayName(dd->dayOfWeek());
3835 removed = 4;
3836 } else if (f.startsWith(QLatin1String("ddd"))) {
3837 buf = dd->shortDayName(dd->dayOfWeek());
3838 removed = 3;
3839 } else if (f.startsWith(QLatin1String("dd"))) {
3840 buf = QString::number(dd->day()).rightJustified(2, QLatin1Char('0'), true);
3841 removed = 2;
3842 } else if (f.at(0) == QLatin1Char('d')) {
3843 buf = QString::number(dd->day());
3844 removed = 1;
3845 } else if (f.startsWith(QLatin1String("MMMM"))) {
3846 buf = dd->longMonthName(dd->month());
3847 removed = 4;
3848 } else if (f.startsWith(QLatin1String("MMM"))) {
3849 buf = dd->shortMonthName(dd->month());
3850 removed = 3;
3851 } else if (f.startsWith(QLatin1String("MM"))) {
3852 buf = QString::number(dd->month()).rightJustified(2, QLatin1Char('0'), true);
3853 removed = 2;
3854 } else if (f.at(0) == QLatin1Char('M')) {
3855 buf = QString::number(dd->month());
3856 removed = 1;
3857 } else if (f.startsWith(QLatin1String("yyyy"))) {
3858 const int year = dd->year();
3859 buf = QString::number(qAbs(year)).rightJustified(4, QLatin1Char('0'));
3860 if(year > 0)
3861 removed = 4;
3862 else
3863 {
3864 buf.prepend(QLatin1Char('-'));
3865 removed = 5;
3866 }
3867
3868 } else if (f.startsWith(QLatin1String("yy"))) {
3869 buf = QString::number(dd->year()).right(2).rightJustified(2, QLatin1Char('0'));
3870 removed = 2;
3871 }
3872 }
3873 if (removed == 0 || removed >= f.size()) {
3874 return buf;
3875 }
3876
3877 return buf + getFmtString(f.mid(removed), dt, dd, am_pm);
3878 }
3879
3880 // Parses the format string and uses getFmtString to get the values for the tokens. Ret
fmtDateTime(const QString & f,const QTime * dt,const QDate * dd)3881 static QString fmtDateTime(const QString& f, const QTime* dt, const QDate* dd)
3882 {
3883 const QLatin1Char quote('\'');
3884 if (f.isEmpty())
3885 return QString();
3886 if (dt && !dt->isValid())
3887 return QString();
3888 if (dd && !dd->isValid())
3889 return QString();
3890
3891 const bool ap = hasUnquotedAP(f);
3892
3893 QString buf;
3894 QString frm;
3895 QChar status(QLatin1Char('0'));
3896
3897 for (int i = 0; i < (int)f.length(); ++i) {
3898 if (f.at(i) == quote) {
3899 if (status == quote) {
3900 if (i > 0 && f.at(i - 1) == quote)
3901 buf += QLatin1Char('\'');
3902 status = QLatin1Char('0');
3903 } else {
3904 if (!frm.isEmpty()) {
3905 buf += getFmtString(frm, dt, dd, ap);
3906 frm.clear();
3907 }
3908 status = quote;
3909 }
3910 } else if (status == quote) {
3911 buf += f.at(i);
3912 } else if (f.at(i) == status) {
3913 if ((ap) && ((f.at(i) == QLatin1Char('P')) || (f.at(i) == QLatin1Char('p'))))
3914 status = QLatin1Char('0');
3915 frm += f.at(i);
3916 } else {
3917 buf += getFmtString(frm, dt, dd, ap);
3918 frm.clear();
3919 if ((f.at(i) == QLatin1Char('h')) || (f.at(i) == QLatin1Char('m'))
3920 || (f.at(i) == QLatin1Char('H'))
3921 || (f.at(i) == QLatin1Char('s')) || (f.at(i) == QLatin1Char('z'))) {
3922 status = f.at(i);
3923 frm += f.at(i);
3924 } else if ((f.at(i) == QLatin1Char('d')) || (f.at(i) == QLatin1Char('M')) || (f.at(i) == QLatin1Char('y'))) {
3925 status = f.at(i);
3926 frm += f.at(i);
3927 } else if ((ap) && (f.at(i) == QLatin1Char('A'))) {
3928 status = QLatin1Char('P');
3929 frm += f.at(i);
3930 } else if((ap) && (f.at(i) == QLatin1Char('a'))) {
3931 status = QLatin1Char('p');
3932 frm += f.at(i);
3933 } else {
3934 buf += f.at(i);
3935 status = QLatin1Char('0');
3936 }
3937 }
3938 }
3939
3940 buf += getFmtString(frm, dt, dd, ap);
3941
3942 return buf;
3943 }
3944 #endif // QT_NO_DATESTRING
3945
3946 #ifdef Q_OS_WIN
3947 static const int LowerYear = 1980;
3948 #else
3949 static const int LowerYear = 1970;
3950 #endif
3951 static const int UpperYear = 2037;
3952
adjustDate(QDate date)3953 static QDate adjustDate(QDate date)
3954 {
3955 QDate lowerLimit(LowerYear, 1, 2);
3956 QDate upperLimit(UpperYear, 12, 30);
3957
3958 if (date > lowerLimit && date < upperLimit)
3959 return date;
3960
3961 int month = date.month();
3962 int day = date.day();
3963
3964 // neither 1970 nor 2037 are leap years, so make sure date isn't Feb 29
3965 if (month == 2 && day == 29)
3966 --day;
3967
3968 if (date < lowerLimit)
3969 date.setDate(LowerYear, month, day);
3970 else
3971 date.setDate(UpperYear, month, day);
3972
3973 return date;
3974 }
3975
utcToLocal(QDate & date,QTime & time)3976 static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time)
3977 {
3978 QDate fakeDate = adjustDate(date);
3979
3980 // won't overflow because of fakeDate
3981 time_t secsSince1Jan1970UTC = toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime().msecsTo(time)) / 1000;
3982 tm *brokenDown = 0;
3983
3984 #if defined(Q_OS_WINCE)
3985 tm res;
3986 FILETIME utcTime = time_tToFt(secsSince1Jan1970UTC);
3987 FILETIME resultTime;
3988 FileTimeToLocalFileTime(&utcTime , &resultTime);
3989 SYSTEMTIME sysTime;
3990 FileTimeToSystemTime(&resultTime , &sysTime);
3991
3992 res.tm_sec = sysTime.wSecond;
3993 res.tm_min = sysTime.wMinute;
3994 res.tm_hour = sysTime.wHour;
3995 res.tm_mday = sysTime.wDay;
3996 res.tm_mon = sysTime.wMonth - 1;
3997 res.tm_year = sysTime.wYear - 1900;
3998 brokenDown = &res;
3999 #elif defined(Q_OS_SYMBIAN)
4000 // months and days are zero index based
4001 _LIT(KUnixEpoch, "19700000:000000.000000");
4002 TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC);
4003 TTime epochTTime;
4004 TInt err = epochTTime.Set(KUnixEpoch);
4005 tm res;
4006 if(err == KErrNone) {
4007 TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
4008 CTrapCleanup *cleanup = CTrapCleanup::New(); // needed to avoid crashes in apps that previously were able to use this function in static data initialization
4009 TRAP(err,
4010 RTz tz;
4011 User::LeaveIfError(tz.Connect());
4012 CleanupClosePushL(tz);
4013 CTzId *tzId = tz.GetTimeZoneIdL();
4014 CleanupStack::PushL(tzId);
4015 res.tm_isdst = tz.IsDaylightSavingOnL(*tzId,utcTTime);
4016 User::LeaveIfError(tz.ConvertToLocalTime(utcTTime));
4017 CleanupStack::PopAndDestroy(tzId);
4018 CleanupStack::PopAndDestroy(&tz));
4019 delete cleanup;
4020 if (KErrNone == err) {
4021 TDateTime localDateTime = utcTTime.DateTime();
4022 res.tm_sec = localDateTime.Second();
4023 res.tm_min = localDateTime.Minute();
4024 res.tm_hour = localDateTime.Hour();
4025 res.tm_mday = localDateTime.Day() + 1; // non-zero based index for tm struct
4026 res.tm_mon = localDateTime.Month();
4027 res.tm_year = localDateTime.Year() - 1900;
4028 // Symbian's timezone server doesn't know how to handle DST before year 1997
4029 if (res.tm_year < 97)
4030 res.tm_isdst = -1;
4031 brokenDown = &res;
4032 }
4033 }
4034 #elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
4035 // use the reentrant version of localtime() where available
4036 tzset();
4037 tm res;
4038 brokenDown = localtime_r(&secsSince1Jan1970UTC, &res);
4039 #elif defined(_MSC_VER) && _MSC_VER >= 1400
4040 tm res;
4041 if (!_localtime64_s(&res, &secsSince1Jan1970UTC))
4042 brokenDown = &res;
4043 #else
4044 brokenDown = localtime(&secsSince1Jan1970UTC);
4045 #endif
4046 if (!brokenDown) {
4047 date = QDate(1970, 1, 1);
4048 time = QTime();
4049 return QDateTimePrivate::LocalUnknown;
4050 } else {
4051 int deltaDays = fakeDate.daysTo(date);
4052 date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday);
4053 time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec());
4054 date = date.addDays(deltaDays);
4055 if (brokenDown->tm_isdst > 0)
4056 return QDateTimePrivate::LocalDST;
4057 else if (brokenDown->tm_isdst < 0)
4058 return QDateTimePrivate::LocalUnknown;
4059 else
4060 return QDateTimePrivate::LocalStandard;
4061 }
4062 }
4063
localToUtc(QDate & date,QTime & time,int isdst)4064 static void localToUtc(QDate &date, QTime &time, int isdst)
4065 {
4066 if (!date.isValid())
4067 return;
4068
4069 QDate fakeDate = adjustDate(date);
4070
4071 tm localTM;
4072 localTM.tm_sec = time.second();
4073 localTM.tm_min = time.minute();
4074 localTM.tm_hour = time.hour();
4075 localTM.tm_mday = fakeDate.day();
4076 localTM.tm_mon = fakeDate.month() - 1;
4077 localTM.tm_year = fakeDate.year() - 1900;
4078 localTM.tm_isdst = (int)isdst;
4079 #if defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
4080 time_t secsSince1Jan1970UTC = (toMSecsSinceEpoch_helper(fakeDate.toJulianDay(), QTime().msecsTo(time)) / 1000);
4081 #else
4082 #if defined(Q_OS_WIN)
4083 _tzset();
4084 #endif
4085 time_t secsSince1Jan1970UTC = mktime(&localTM);
4086 #ifdef Q_OS_QNX
4087 //mktime sometimes fails on QNX. Following workaround converts the date and time then manually
4088 if (secsSince1Jan1970UTC == (time_t)-1) {
4089 QDateTime tempTime = QDateTime(date, time, Qt::UTC);;
4090 tempTime = tempTime.addMSecs(timezone * 1000);
4091 date = tempTime.date();
4092 time = tempTime.time();
4093 return;
4094 }
4095 #endif
4096 #endif
4097 tm *brokenDown = 0;
4098 #if defined(Q_OS_WINCE)
4099 tm res;
4100 FILETIME localTime = time_tToFt(secsSince1Jan1970UTC);
4101 SYSTEMTIME sysTime;
4102 FileTimeToSystemTime(&localTime, &sysTime);
4103 FILETIME resultTime;
4104 LocalFileTimeToFileTime(&localTime , &resultTime);
4105 FileTimeToSystemTime(&resultTime , &sysTime);
4106 res.tm_sec = sysTime.wSecond;
4107 res.tm_min = sysTime.wMinute;
4108 res.tm_hour = sysTime.wHour;
4109 res.tm_mday = sysTime.wDay;
4110 res.tm_mon = sysTime.wMonth - 1;
4111 res.tm_year = sysTime.wYear - 1900;
4112 res.tm_isdst = (int)isdst;
4113 brokenDown = &res;
4114 #elif defined(Q_OS_SYMBIAN)
4115 // months and days are zero index based
4116 _LIT(KUnixEpoch, "19700000:000000.000000");
4117 TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC);
4118 TTime epochTTime;
4119 TInt err = epochTTime.Set(KUnixEpoch);
4120 tm res;
4121 if(err == KErrNone) {
4122 TTime localTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
4123 RTz tz;
4124 if (KErrNone == tz.Connect()) {
4125 if (KErrNone == tz.ConvertToUniversalTime(localTTime)) {
4126 TDateTime utcDateTime = localTTime.DateTime();
4127 res.tm_sec = utcDateTime.Second();
4128 res.tm_min = utcDateTime.Minute();
4129 res.tm_hour = utcDateTime.Hour();
4130 res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct
4131 res.tm_mon = utcDateTime.Month();
4132 res.tm_year = utcDateTime.Year() - 1900;
4133 res.tm_isdst = (int)isdst;
4134 brokenDown = &res;
4135 }
4136 tz.Close();
4137 }
4138 }
4139 #elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
4140 // use the reentrant version of gmtime() where available
4141 tm res;
4142 brokenDown = gmtime_r(&secsSince1Jan1970UTC, &res);
4143 #elif defined(_MSC_VER) && _MSC_VER >= 1400
4144 tm res;
4145 if (!_gmtime64_s(&res, &secsSince1Jan1970UTC))
4146 brokenDown = &res;
4147 #else
4148 brokenDown = gmtime(&secsSince1Jan1970UTC);
4149 #endif // !QT_NO_THREAD && _POSIX_THREAD_SAFE_FUNCTIONS
4150 if (!brokenDown) {
4151 date = QDate(1970, 1, 1);
4152 time = QTime();
4153 } else {
4154 int deltaDays = fakeDate.daysTo(date);
4155 date = QDate(brokenDown->tm_year + 1900, brokenDown->tm_mon + 1, brokenDown->tm_mday);
4156 time = QTime(brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec, time.msec());
4157 date = date.addDays(deltaDays);
4158 }
4159 }
4160
getLocal(QDate & outDate,QTime & outTime) const4161 QDateTimePrivate::Spec QDateTimePrivate::getLocal(QDate &outDate, QTime &outTime) const
4162 {
4163 outDate = date;
4164 outTime = time;
4165 if (spec == QDateTimePrivate::UTC)
4166 return utcToLocal(outDate, outTime);
4167 return spec;
4168 }
4169
getUTC(QDate & outDate,QTime & outTime) const4170 void QDateTimePrivate::getUTC(QDate &outDate, QTime &outTime) const
4171 {
4172 outDate = date;
4173 outTime = time;
4174 const bool isOffset = spec == QDateTimePrivate::OffsetFromUTC;
4175
4176 if (spec != QDateTimePrivate::UTC && !isOffset)
4177 localToUtc(outDate, outTime, (int)spec);
4178
4179 if (isOffset)
4180 addMSecs(outDate, outTime, -(qint64(utcOffset) * 1000));
4181 }
4182
4183 #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
operator <<(QDebug dbg,const QDate & date)4184 QDebug operator<<(QDebug dbg, const QDate &date)
4185 {
4186 dbg.nospace() << "QDate(" << date.toString() << ')';
4187 return dbg.space();
4188 }
4189
operator <<(QDebug dbg,const QTime & time)4190 QDebug operator<<(QDebug dbg, const QTime &time)
4191 {
4192 dbg.nospace() << "QTime(" << time.toString() << ')';
4193 return dbg.space();
4194 }
4195
operator <<(QDebug dbg,const QDateTime & date)4196 QDebug operator<<(QDebug dbg, const QDateTime &date)
4197 {
4198 dbg.nospace() << "QDateTime(" << date.toString() << ')';
4199 return dbg.space();
4200 }
4201 #endif
4202
4203 #ifndef QT_BOOTSTRAPPED
4204
4205 /*!
4206 \internal
4207 Gets the digit from a datetime. E.g.
4208
4209 QDateTime var(QDate(2004, 02, 02));
4210 int digit = getDigit(var, Year);
4211 // digit = 2004
4212 */
4213
getDigit(const QDateTime & t,int index) const4214 int QDateTimeParser::getDigit(const QDateTime &t, int index) const
4215 {
4216 if (index < 0 || index >= sectionNodes.size()) {
4217 #ifndef QT_NO_DATESTRING
4218 qWarning("QDateTimeParser::getDigit() Internal error (%s %d)",
4219 qPrintable(t.toString()), index);
4220 #else
4221 qWarning("QDateTimeParser::getDigit() Internal error (%d)", index);
4222 #endif
4223 return -1;
4224 }
4225 const SectionNode &node = sectionNodes.at(index);
4226 switch (node.type) {
4227 case Hour24Section: case Hour12Section: return t.time().hour();
4228 case MinuteSection: return t.time().minute();
4229 case SecondSection: return t.time().second();
4230 case MSecSection: return t.time().msec();
4231 case YearSection2Digits:
4232 case YearSection: return t.date().year();
4233 case MonthSection: return t.date().month();
4234 case DaySection: return t.date().day();
4235 case DayOfWeekSection: return t.date().day();
4236 case AmPmSection: return t.time().hour() > 11 ? 1 : 0;
4237
4238 default: break;
4239 }
4240
4241 #ifndef QT_NO_DATESTRING
4242 qWarning("QDateTimeParser::getDigit() Internal error 2 (%s %d)",
4243 qPrintable(t.toString()), index);
4244 #else
4245 qWarning("QDateTimeParser::getDigit() Internal error 2 (%d)", index);
4246 #endif
4247 return -1;
4248 }
4249
4250 /*!
4251 \internal
4252 Sets a digit in a datetime. E.g.
4253
4254 QDateTime var(QDate(2004, 02, 02));
4255 int digit = getDigit(var, Year);
4256 // digit = 2004
4257 setDigit(&var, Year, 2005);
4258 digit = getDigit(var, Year);
4259 // digit = 2005
4260 */
4261
setDigit(QDateTime & v,int index,int newVal) const4262 bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
4263 {
4264 if (index < 0 || index >= sectionNodes.size()) {
4265 #ifndef QT_NO_DATESTRING
4266 qWarning("QDateTimeParser::setDigit() Internal error (%s %d %d)",
4267 qPrintable(v.toString()), index, newVal);
4268 #else
4269 qWarning("QDateTimeParser::setDigit() Internal error (%d %d)", index, newVal);
4270 #endif
4271 return false;
4272 }
4273 const SectionNode &node = sectionNodes.at(index);
4274
4275 int year, month, day, hour, minute, second, msec;
4276 year = v.date().year();
4277 month = v.date().month();
4278 day = v.date().day();
4279 hour = v.time().hour();
4280 minute = v.time().minute();
4281 second = v.time().second();
4282 msec = v.time().msec();
4283
4284 switch (node.type) {
4285 case Hour24Section: case Hour12Section: hour = newVal; break;
4286 case MinuteSection: minute = newVal; break;
4287 case SecondSection: second = newVal; break;
4288 case MSecSection: msec = newVal; break;
4289 case YearSection2Digits:
4290 case YearSection: year = newVal; break;
4291 case MonthSection: month = newVal; break;
4292 case DaySection:
4293 case DayOfWeekSection:
4294 if (newVal > 31) {
4295 // have to keep legacy behavior. setting the
4296 // date to 32 should return false. Setting it
4297 // to 31 for february should return true
4298 return false;
4299 }
4300 day = newVal;
4301 break;
4302 case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
4303 default:
4304 qWarning("QDateTimeParser::setDigit() Internal error (%s)",
4305 qPrintable(sectionName(node.type)));
4306 break;
4307 }
4308
4309 if (!(node.type & (DaySection|DayOfWeekSection))) {
4310 if (day < cachedDay)
4311 day = cachedDay;
4312 const int max = QDate(year, month, 1).daysInMonth();
4313 if (day > max) {
4314 day = max;
4315 }
4316 }
4317 if (QDate::isValid(year, month, day) && QTime::isValid(hour, minute, second, msec)) {
4318 v = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
4319 return true;
4320 }
4321 return false;
4322 }
4323
4324
4325
4326 /*!
4327 \
4328
4329 Returns the absolute maximum for a section
4330 */
4331
absoluteMax(int s,const QDateTime & cur) const4332 int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
4333 {
4334 const SectionNode &sn = sectionNode(s);
4335 switch (sn.type) {
4336 case Hour24Section:
4337 case Hour12Section: return 23; // this is special-cased in
4338 // parseSection. We want it to be
4339 // 23 for the stepBy case.
4340 case MinuteSection:
4341 case SecondSection: return 59;
4342 case MSecSection: return 999;
4343 case YearSection2Digits:
4344 case YearSection: return 9999; // sectionMaxSize will prevent
4345 // people from typing in a larger
4346 // number in count == 2 sections.
4347 // stepBy() will work on real years anyway
4348 case MonthSection: return 12;
4349 case DaySection:
4350 case DayOfWeekSection: return cur.isValid() ? cur.date().daysInMonth() : 31;
4351 case AmPmSection: return 1;
4352 default: break;
4353 }
4354 qWarning("QDateTimeParser::absoluteMax() Internal error (%s)",
4355 qPrintable(sectionName(sn.type)));
4356 return -1;
4357 }
4358
4359 /*!
4360 \internal
4361
4362 Returns the absolute minimum for a section
4363 */
4364
absoluteMin(int s) const4365 int QDateTimeParser::absoluteMin(int s) const
4366 {
4367 const SectionNode &sn = sectionNode(s);
4368 switch (sn.type) {
4369 case Hour24Section:
4370 case Hour12Section:
4371 case MinuteSection:
4372 case SecondSection:
4373 case MSecSection:
4374 case YearSection2Digits:
4375 case YearSection: return 0;
4376 case MonthSection:
4377 case DaySection:
4378 case DayOfWeekSection: return 1;
4379 case AmPmSection: return 0;
4380 default: break;
4381 }
4382 qWarning("QDateTimeParser::absoluteMin() Internal error (%s, %0x)",
4383 qPrintable(sectionName(sn.type)), sn.type);
4384 return -1;
4385 }
4386
4387 /*!
4388 \internal
4389
4390 Returns the sectionNode for the Section \a s.
4391 */
4392
sectionNode(int sectionIndex) const4393 const QDateTimeParser::SectionNode &QDateTimeParser::sectionNode(int sectionIndex) const
4394 {
4395 if (sectionIndex < 0) {
4396 switch (sectionIndex) {
4397 case FirstSectionIndex:
4398 return first;
4399 case LastSectionIndex:
4400 return last;
4401 case NoSectionIndex:
4402 return none;
4403 }
4404 } else if (sectionIndex < sectionNodes.size()) {
4405 return sectionNodes.at(sectionIndex);
4406 }
4407
4408 qWarning("QDateTimeParser::sectionNode() Internal error (%d)",
4409 sectionIndex);
4410 return none;
4411 }
4412
sectionType(int sectionIndex) const4413 QDateTimeParser::Section QDateTimeParser::sectionType(int sectionIndex) const
4414 {
4415 return sectionNode(sectionIndex).type;
4416 }
4417
4418
4419 /*!
4420 \internal
4421
4422 Returns the starting position for section \a s.
4423 */
4424
sectionPos(int sectionIndex) const4425 int QDateTimeParser::sectionPos(int sectionIndex) const
4426 {
4427 return sectionPos(sectionNode(sectionIndex));
4428 }
4429
sectionPos(const SectionNode & sn) const4430 int QDateTimeParser::sectionPos(const SectionNode &sn) const
4431 {
4432 switch (sn.type) {
4433 case FirstSection: return 0;
4434 case LastSection: return displayText().size() - 1;
4435 default: break;
4436 }
4437 if (sn.pos == -1) {
4438 qWarning("QDateTimeParser::sectionPos Internal error (%s)", qPrintable(sectionName(sn.type)));
4439 return -1;
4440 }
4441 return sn.pos;
4442 }
4443
4444
4445 /*!
4446 \internal helper function for parseFormat. removes quotes that are
4447 not escaped and removes the escaping on those that are escaped
4448
4449 */
4450
unquote(const QString & str)4451 static QString unquote(const QString &str)
4452 {
4453 const QChar quote(QLatin1Char('\''));
4454 const QChar slash(QLatin1Char('\\'));
4455 const QChar zero(QLatin1Char('0'));
4456 QString ret;
4457 QChar status(zero);
4458 const int max = str.size();
4459 for (int i=0; i<max; ++i) {
4460 if (str.at(i) == quote) {
4461 if (status != quote) {
4462 status = quote;
4463 } else if (!ret.isEmpty() && str.at(i - 1) == slash) {
4464 ret[ret.size() - 1] = quote;
4465 } else {
4466 status = zero;
4467 }
4468 } else {
4469 ret += str.at(i);
4470 }
4471 }
4472 return ret;
4473 }
4474 /*!
4475 \internal
4476
4477 Parses the format \a newFormat. If successful, returns true and
4478 sets up the format. Else keeps the old format and returns false.
4479
4480 */
4481
countRepeat(const QString & str,int index,int maxCount)4482 static inline int countRepeat(const QString &str, int index, int maxCount)
4483 {
4484 int count = 1;
4485 const QChar ch(str.at(index));
4486 const int max = qMin(index + maxCount, str.size());
4487 while (index + count < max && str.at(index + count) == ch) {
4488 ++count;
4489 }
4490 return count;
4491 }
4492
appendSeparator(QStringList * list,const QString & string,int from,int size,int lastQuote)4493 static inline void appendSeparator(QStringList *list, const QString &string, int from, int size, int lastQuote)
4494 {
4495 QString str(string.mid(from, size));
4496 if (lastQuote >= from)
4497 str = unquote(str);
4498 list->append(str);
4499 }
4500
4501
parseFormat(const QString & newFormat)4502 bool QDateTimeParser::parseFormat(const QString &newFormat)
4503 {
4504 const QLatin1Char quote('\'');
4505 const QLatin1Char slash('\\');
4506 const QLatin1Char zero('0');
4507 if (newFormat == displayFormat && !newFormat.isEmpty()) {
4508 return true;
4509 }
4510
4511 QDTPDEBUGN("parseFormat: %s", newFormat.toLatin1().constData());
4512
4513 QVector<SectionNode> newSectionNodes;
4514 Sections newDisplay = 0;
4515 QStringList newSeparators;
4516 int i, index = 0;
4517 int add = 0;
4518 QChar status(zero);
4519 const int max = newFormat.size();
4520 int lastQuote = -1;
4521 for (i = 0; i<max; ++i) {
4522 if (newFormat.at(i) == quote) {
4523 lastQuote = i;
4524 ++add;
4525 if (status != quote) {
4526 status = quote;
4527 } else if (newFormat.at(i - 1) != slash) {
4528 status = zero;
4529 }
4530 } else if (status != quote) {
4531 const char sect = newFormat.at(i).toLatin1();
4532 switch (sect) {
4533 case 'H':
4534 case 'h':
4535 if (parserType != QVariant::Date) {
4536 const Section hour = (sect == 'h') ? Hour12Section : Hour24Section;
4537 const SectionNode sn = { hour, i - add, countRepeat(newFormat, i, 2) };
4538 newSectionNodes.append(sn);
4539 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4540 i += sn.count - 1;
4541 index = i + 1;
4542 newDisplay |= hour;
4543 }
4544 break;
4545 case 'm':
4546 if (parserType != QVariant::Date) {
4547 const SectionNode sn = { MinuteSection, i - add, countRepeat(newFormat, i, 2) };
4548 newSectionNodes.append(sn);
4549 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4550 i += sn.count - 1;
4551 index = i + 1;
4552 newDisplay |= MinuteSection;
4553 }
4554 break;
4555 case 's':
4556 if (parserType != QVariant::Date) {
4557 const SectionNode sn = { SecondSection, i - add, countRepeat(newFormat, i, 2) };
4558 newSectionNodes.append(sn);
4559 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4560 i += sn.count - 1;
4561 index = i + 1;
4562 newDisplay |= SecondSection;
4563 }
4564 break;
4565
4566 case 'z':
4567 if (parserType != QVariant::Date) {
4568 const SectionNode sn = { MSecSection, i - add, countRepeat(newFormat, i, 3) < 3 ? 1 : 3 };
4569 newSectionNodes.append(sn);
4570 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4571 i += sn.count - 1;
4572 index = i + 1;
4573 newDisplay |= MSecSection;
4574 }
4575 break;
4576 case 'A':
4577 case 'a':
4578 if (parserType != QVariant::Date) {
4579 const bool cap = (sect == 'A');
4580 const SectionNode sn = { AmPmSection, i - add, (cap ? 1 : 0) };
4581 newSectionNodes.append(sn);
4582 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4583 newDisplay |= AmPmSection;
4584 if (i + 1 < newFormat.size()
4585 && newFormat.at(i+1) == (cap ? QLatin1Char('P') : QLatin1Char('p'))) {
4586 ++i;
4587 }
4588 index = i + 1;
4589 }
4590 break;
4591 case 'y':
4592 if (parserType != QVariant::Time) {
4593 const int repeat = countRepeat(newFormat, i, 4);
4594 if (repeat >= 2) {
4595 const SectionNode sn = { repeat == 4 ? YearSection : YearSection2Digits,
4596 i - add, repeat == 4 ? 4 : 2 };
4597 newSectionNodes.append(sn);
4598 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4599 i += sn.count - 1;
4600 index = i + 1;
4601 newDisplay |= sn.type;
4602 }
4603 }
4604 break;
4605 case 'M':
4606 if (parserType != QVariant::Time) {
4607 const SectionNode sn = { MonthSection, i - add, countRepeat(newFormat, i, 4) };
4608 newSectionNodes.append(sn);
4609 newSeparators.append(unquote(newFormat.mid(index, i - index)));
4610 i += sn.count - 1;
4611 index = i + 1;
4612 newDisplay |= MonthSection;
4613 }
4614 break;
4615 case 'd':
4616 if (parserType != QVariant::Time) {
4617 const int repeat = countRepeat(newFormat, i, 4);
4618 const SectionNode sn = { repeat >= 3 ? DayOfWeekSection : DaySection, i - add, repeat };
4619 newSectionNodes.append(sn);
4620 appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
4621 i += sn.count - 1;
4622 index = i + 1;
4623 newDisplay |= sn.type;
4624 }
4625 break;
4626
4627 default:
4628 break;
4629 }
4630 }
4631 }
4632 if (newSectionNodes.isEmpty() && context == DateTimeEdit) {
4633 return false;
4634 }
4635
4636 if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) {
4637 const int max = newSectionNodes.size();
4638 for (int i=0; i<max; ++i) {
4639 SectionNode &node = newSectionNodes[i];
4640 if (node.type == Hour12Section)
4641 node.type = Hour24Section;
4642 }
4643 }
4644
4645 if (index < newFormat.size()) {
4646 appendSeparator(&newSeparators, newFormat, index, index - max, lastQuote);
4647 } else {
4648 newSeparators.append(QString());
4649 }
4650
4651 displayFormat = newFormat;
4652 separators = newSeparators;
4653 sectionNodes = newSectionNodes;
4654 display = newDisplay;
4655 last.pos = -1;
4656
4657 // for (int i=0; i<sectionNodes.size(); ++i) {
4658 // QDTPDEBUG << sectionName(sectionNodes.at(i).type) << sectionNodes.at(i).count;
4659 // }
4660
4661 QDTPDEBUG << newFormat << displayFormat;
4662 QDTPDEBUGN("separators:\n'%s'", separators.join(QLatin1String("\n")).toLatin1().constData());
4663
4664 return true;
4665 }
4666
4667 /*!
4668 \internal
4669
4670 Returns the size of section \a s.
4671 */
4672
sectionSize(int sectionIndex) const4673 int QDateTimeParser::sectionSize(int sectionIndex) const
4674 {
4675 if (sectionIndex < 0)
4676 return 0;
4677
4678 if (sectionIndex >= sectionNodes.size()) {
4679 qWarning("QDateTimeParser::sectionSize Internal error (%d)", sectionIndex);
4680 return -1;
4681 }
4682 if (sectionIndex == sectionNodes.size() - 1) {
4683 return displayText().size() - sectionPos(sectionIndex) - separators.last().size();
4684 } else {
4685 return sectionPos(sectionIndex + 1) - sectionPos(sectionIndex)
4686 - separators.at(sectionIndex + 1).size();
4687 }
4688 }
4689
4690
sectionMaxSize(Section s,int count) const4691 int QDateTimeParser::sectionMaxSize(Section s, int count) const
4692 {
4693 #ifndef QT_NO_TEXTDATE
4694 int mcount = 12;
4695 #endif
4696
4697 switch (s) {
4698 case FirstSection:
4699 case NoSection:
4700 case LastSection: return 0;
4701
4702 case AmPmSection: {
4703 const int lowerMax = qMin(getAmPmText(AmText, LowerCase).size(),
4704 getAmPmText(PmText, LowerCase).size());
4705 const int upperMax = qMin(getAmPmText(AmText, UpperCase).size(),
4706 getAmPmText(PmText, UpperCase).size());
4707 return qMin(4, qMin(lowerMax, upperMax));
4708 }
4709
4710 case Hour24Section:
4711 case Hour12Section:
4712 case MinuteSection:
4713 case SecondSection:
4714 case DaySection: return 2;
4715 case DayOfWeekSection:
4716 #ifdef QT_NO_TEXTDATE
4717 return 2;
4718 #else
4719 mcount = 7;
4720 // fall through
4721 #endif
4722 case MonthSection:
4723 if (count <= 2)
4724 return 2;
4725
4726 #ifdef QT_NO_TEXTDATE
4727 return 2;
4728 #else
4729 {
4730 int ret = 0;
4731 const QLocale l = locale();
4732 for (int i=1; i<=mcount; ++i) {
4733 const QString str = (s == MonthSection
4734 ? l.monthName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat)
4735 : l.dayName(i, count == 4 ? QLocale::LongFormat : QLocale::ShortFormat));
4736 ret = qMax(str.size(), ret);
4737 }
4738 return ret;
4739 }
4740 #endif
4741 case MSecSection: return 3;
4742 case YearSection: return 4;
4743 case YearSection2Digits: return 2;
4744
4745 case CalendarPopupSection:
4746 case Internal:
4747 case TimeSectionMask:
4748 case DateSectionMask:
4749 qWarning("QDateTimeParser::sectionMaxSize: Invalid section %s",
4750 sectionName(s).toLatin1().constData());
4751
4752 case NoSectionIndex:
4753 case FirstSectionIndex:
4754 case LastSectionIndex:
4755 case CalendarPopupIndex:
4756 // these cases can't happen
4757 break;
4758 }
4759 return -1;
4760 }
4761
4762
sectionMaxSize(int index) const4763 int QDateTimeParser::sectionMaxSize(int index) const
4764 {
4765 const SectionNode &sn = sectionNode(index);
4766 return sectionMaxSize(sn.type, sn.count);
4767 }
4768
4769 /*!
4770 \internal
4771
4772 Returns the text of section \a s. This function operates on the
4773 arg text rather than edit->text().
4774 */
4775
4776
sectionText(const QString & text,int sectionIndex,int index) const4777 QString QDateTimeParser::sectionText(const QString &text, int sectionIndex, int index) const
4778 {
4779 const SectionNode &sn = sectionNode(sectionIndex);
4780 switch (sn.type) {
4781 case NoSectionIndex:
4782 case FirstSectionIndex:
4783 case LastSectionIndex:
4784 return QString();
4785 default: break;
4786 }
4787
4788 return text.mid(index, sectionSize(sectionIndex));
4789 }
4790
sectionText(int sectionIndex) const4791 QString QDateTimeParser::sectionText(int sectionIndex) const
4792 {
4793 const SectionNode &sn = sectionNode(sectionIndex);
4794 switch (sn.type) {
4795 case NoSectionIndex:
4796 case FirstSectionIndex:
4797 case LastSectionIndex:
4798 return QString();
4799 default: break;
4800 }
4801
4802 return displayText().mid(sn.pos, sectionSize(sectionIndex));
4803 }
4804
4805
4806 #ifndef QT_NO_TEXTDATE
4807 /*!
4808 \internal:skipToNextSection
4809
4810 Parses the part of \a text that corresponds to \a s and returns
4811 the value of that field. Sets *stateptr to the right state if
4812 stateptr != 0.
4813 */
4814
parseSection(const QDateTime & currentValue,int sectionIndex,QString & text,int & cursorPosition,int index,State & state,int * usedptr) const4815 int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionIndex,
4816 QString &text, int &cursorPosition, int index,
4817 State &state, int *usedptr) const
4818 {
4819 state = Invalid;
4820 int num = 0;
4821 const SectionNode &sn = sectionNode(sectionIndex);
4822 if ((sn.type & Internal) == Internal) {
4823 qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
4824 qPrintable(sectionName(sn.type)), sectionIndex);
4825 return -1;
4826 }
4827
4828 const int sectionmaxsize = sectionMaxSize(sectionIndex);
4829 QString sectiontext = text.mid(index, sectionmaxsize);
4830 int sectiontextSize = sectiontext.size();
4831
4832 QDTPDEBUG << "sectionValue for" << sectionName(sn.type)
4833 << "with text" << text << "and st" << sectiontext
4834 << text.mid(index, sectionmaxsize)
4835 << index;
4836
4837 int used = 0;
4838 switch (sn.type) {
4839 case AmPmSection: {
4840 const int ampm = findAmPm(sectiontext, sectionIndex, &used);
4841 switch (ampm) {
4842 case AM: // sectiontext == AM
4843 case PM: // sectiontext == PM
4844 num = ampm;
4845 state = Acceptable;
4846 break;
4847 case PossibleAM: // sectiontext => AM
4848 case PossiblePM: // sectiontext => PM
4849 num = ampm - 2;
4850 state = Intermediate;
4851 break;
4852 case PossibleBoth: // sectiontext => AM|PM
4853 num = 0;
4854 state = Intermediate;
4855 break;
4856 case Neither:
4857 state = Invalid;
4858 QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1";
4859 break;
4860 default:
4861 QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm);
4862 break;
4863 }
4864 if (state != Invalid) {
4865 QString str = text;
4866 text.replace(index, used, sectiontext.left(used));
4867 }
4868 break; }
4869 case MonthSection:
4870 case DayOfWeekSection:
4871 if (sn.count >= 3) {
4872 if (sn.type == MonthSection) {
4873 int min = 1;
4874 const QDate minDate = getMinimum().date();
4875 if (currentValue.date().year() == minDate.year()) {
4876 min = minDate.month();
4877 }
4878 num = findMonth(sectiontext.toLower(), min, sectionIndex, §iontext, &used);
4879 } else {
4880 num = findDay(sectiontext.toLower(), 1, sectionIndex, §iontext, &used);
4881 }
4882
4883 if (num != -1) {
4884 state = (used == sectiontext.size() ? Acceptable : Intermediate);
4885 QString str = text;
4886 text.replace(index, used, sectiontext.left(used));
4887 } else {
4888 state = Intermediate;
4889 }
4890 break; }
4891 // fall through
4892 case DaySection:
4893 case YearSection:
4894 case YearSection2Digits:
4895 case Hour12Section:
4896 case Hour24Section:
4897 case MinuteSection:
4898 case SecondSection:
4899 case MSecSection: {
4900 if (sectiontextSize == 0) {
4901 num = 0;
4902 used = 0;
4903 state = Intermediate;
4904 } else {
4905 const int absMax = absoluteMax(sectionIndex);
4906 QLocale loc;
4907 bool ok = true;
4908 int last = -1;
4909 used = -1;
4910
4911 QString digitsStr(sectiontext);
4912 for (int i = 0; i < sectiontextSize; ++i) {
4913 if (digitsStr.at(i).isSpace()) {
4914 sectiontextSize = i;
4915 break;
4916 }
4917 }
4918
4919 const int max = qMin(sectionmaxsize, sectiontextSize);
4920 for (int digits = max; digits >= 1; --digits) {
4921 digitsStr.truncate(digits);
4922 int tmp = (int)loc.toUInt(digitsStr, &ok, 10);
4923 if (ok && sn.type == Hour12Section) {
4924 if (tmp > 12) {
4925 tmp = -1;
4926 ok = false;
4927 } else if (tmp == 12) {
4928 tmp = 0;
4929 }
4930 }
4931 if (ok && tmp <= absMax) {
4932 QDTPDEBUG << sectiontext.left(digits) << tmp << digits;
4933 last = tmp;
4934 used = digits;
4935 break;
4936 }
4937 }
4938
4939 if (last == -1) {
4940 QChar first(sectiontext.at(0));
4941 if (separators.at(sectionIndex + 1).startsWith(first)) {
4942 used = 0;
4943 state = Intermediate;
4944 } else {
4945 state = Invalid;
4946 QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok;
4947 }
4948 } else {
4949 num += last;
4950 const FieldInfo fi = fieldInfo(sectionIndex);
4951 const bool done = (used == sectionmaxsize);
4952 if (!done && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002
4953 for (int i=used; i<sectionmaxsize; ++i) {
4954 num *= 10;
4955 }
4956 }
4957 const int absMin = absoluteMin(sectionIndex);
4958 if (num < absMin) {
4959 state = done ? Invalid : Intermediate;
4960 if (done)
4961 QDTPDEBUG << "invalid because" << num << "is less than absoluteMin" << absMin;
4962 } else if (num > absMax) {
4963 state = Intermediate;
4964 } else if (!done && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
4965 if (skipToNextSection(sectionIndex, currentValue, digitsStr)) {
4966 state = Acceptable;
4967 const int missingZeroes = sectionmaxsize - digitsStr.size();
4968 text.insert(index, QString().fill(QLatin1Char('0'), missingZeroes));
4969 used = sectionmaxsize;
4970 cursorPosition += missingZeroes;
4971 } else {
4972 state = Intermediate;;
4973 }
4974 } else {
4975 state = Acceptable;
4976 }
4977 }
4978 }
4979 break; }
4980 default:
4981 qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
4982 qPrintable(sectionName(sn.type)), sectionIndex);
4983 return -1;
4984 }
4985
4986 if (usedptr)
4987 *usedptr = used;
4988
4989 return (state != Invalid ? num : -1);
4990 }
4991 #endif // QT_NO_TEXTDATE
4992
4993 #ifndef QT_NO_DATESTRING
4994 /*!
4995 \internal
4996 */
4997
parse(QString & input,int & cursorPosition,const QDateTime & currentValue,bool fixup) const4998 QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPosition,
4999 const QDateTime ¤tValue, bool fixup) const
5000 {
5001 const QDateTime minimum = getMinimum();
5002 const QDateTime maximum = getMaximum();
5003
5004 State state = Acceptable;
5005
5006 QDateTime newCurrentValue;
5007 int pos = 0;
5008 bool conflicts = false;
5009 const int sectionNodesCount = sectionNodes.size();
5010
5011 QDTPDEBUG << "parse" << input;
5012 {
5013 int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits;
5014 getDateFromJulianDay(currentValue.date().toJulianDay(), &year, &month, &day);
5015 year2digits = year % 100;
5016 hour = currentValue.time().hour();
5017 hour12 = -1;
5018 minute = currentValue.time().minute();
5019 second = currentValue.time().second();
5020 msec = currentValue.time().msec();
5021 dayofweek = currentValue.date().dayOfWeek();
5022
5023 ampm = -1;
5024 Sections isSet = NoSection;
5025 int num;
5026 State tmpstate;
5027
5028 for (int index=0; state != Invalid && index<sectionNodesCount; ++index) {
5029 if (QStringRef(&input, pos, separators.at(index).size()) != separators.at(index)) {
5030 QDTPDEBUG << "invalid because" << input.mid(pos, separators.at(index).size())
5031 << "!=" << separators.at(index)
5032 << index << pos << currentSectionIndex;
5033 state = Invalid;
5034 goto end;
5035 }
5036 pos += separators.at(index).size();
5037 sectionNodes[index].pos = pos;
5038 int *current = 0;
5039 const SectionNode sn = sectionNodes.at(index);
5040 int used;
5041
5042 num = parseSection(currentValue, index, input, cursorPosition, pos, tmpstate, &used);
5043 QDTPDEBUG << "sectionValue" << sectionName(sectionType(index)) << input
5044 << "pos" << pos << "used" << used << stateName(tmpstate);
5045 if (fixup && tmpstate == Intermediate && used < sn.count) {
5046 const FieldInfo fi = fieldInfo(index);
5047 if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
5048 const QString newText = QString::fromLatin1("%1").arg(num, sn.count, 10, QLatin1Char('0'));
5049 input.replace(pos, used, newText);
5050 used = sn.count;
5051 }
5052 }
5053 pos += qMax(0, used);
5054
5055 state = qMin<State>(state, tmpstate);
5056 if (state == Intermediate && context == FromString) {
5057 state = Invalid;
5058 break;
5059 }
5060
5061 QDTPDEBUG << index << sectionName(sectionType(index)) << "is set to"
5062 << pos << "state is" << stateName(state);
5063
5064
5065 if (state != Invalid) {
5066 switch (sn.type) {
5067 case Hour24Section: current = &hour; break;
5068 case Hour12Section: current = &hour12; break;
5069 case MinuteSection: current = &minute; break;
5070 case SecondSection: current = &second; break;
5071 case MSecSection: current = &msec; break;
5072 case YearSection: current = &year; break;
5073 case YearSection2Digits: current = &year2digits; break;
5074 case MonthSection: current = &month; break;
5075 case DayOfWeekSection: current = &dayofweek; break;
5076 case DaySection: current = &day; num = qMax<int>(1, num); break;
5077 case AmPmSection: current = &m; break;
5078 default:
5079 qWarning("QDateTimeParser::parse Internal error (%s)",
5080 qPrintable(sectionName(sn.type)));
5081 break;
5082 }
5083 if (!current) {
5084 qWarning("QDateTimeParser::parse Internal error 2");
5085 return StateNode();
5086 }
5087 if (isSet & sn.type && *current != num) {
5088 QDTPDEBUG << "CONFLICT " << sectionName(sn.type) << *current << num;
5089 conflicts = true;
5090 if (index != currentSectionIndex || num == -1) {
5091 continue;
5092 }
5093 }
5094 if (num != -1)
5095 *current = num;
5096 isSet |= sn.type;
5097 }
5098 }
5099
5100 if (state != Invalid && QStringRef(&input, pos, input.size() - pos) != separators.last()) {
5101 QDTPDEBUG << "invalid because" << input.mid(pos)
5102 << "!=" << separators.last() << pos;
5103 state = Invalid;
5104 }
5105
5106 if (state != Invalid) {
5107 if (parserType != QVariant::Time) {
5108 if (year % 100 != year2digits) {
5109 switch (isSet & (YearSection2Digits|YearSection)) {
5110 case YearSection2Digits:
5111 year = (year / 100) * 100;
5112 year += year2digits;
5113 break;
5114 case ((uint)YearSection2Digits|(uint)YearSection): {
5115 conflicts = true;
5116 const SectionNode &sn = sectionNode(currentSectionIndex);
5117 if (sn.type == YearSection2Digits) {
5118 year = (year / 100) * 100;
5119 year += year2digits;
5120 }
5121 break; }
5122 default:
5123 break;
5124 }
5125 }
5126
5127 const QDate date(year, month, day);
5128 const int diff = dayofweek - date.dayOfWeek();
5129 if (diff != 0 && state == Acceptable && isSet & DayOfWeekSection) {
5130 conflicts = isSet & DaySection;
5131 const SectionNode &sn = sectionNode(currentSectionIndex);
5132 if (sn.type == DayOfWeekSection || currentSectionIndex == -1) {
5133 // dayofweek should be preferred
5134 day += diff;
5135 if (day <= 0) {
5136 day += 7;
5137 } else if (day > date.daysInMonth()) {
5138 day -= 7;
5139 }
5140 QDTPDEBUG << year << month << day << dayofweek
5141 << diff << QDate(year, month, day).dayOfWeek();
5142 }
5143 }
5144 bool needfixday = false;
5145 if (sectionType(currentSectionIndex) & (DaySection|DayOfWeekSection)) {
5146 cachedDay = day;
5147 } else if (cachedDay > day) {
5148 day = cachedDay;
5149 needfixday = true;
5150 }
5151
5152 if (!QDate::isValid(year, month, day)) {
5153 if (day < 32) {
5154 cachedDay = day;
5155 }
5156 if (day > 28 && QDate::isValid(year, month, 1)) {
5157 needfixday = true;
5158 }
5159 }
5160 if (needfixday) {
5161 if (context == FromString) {
5162 state = Invalid;
5163 goto end;
5164 }
5165 if (state == Acceptable && fixday) {
5166 day = qMin<int>(day, QDate(year, month, 1).daysInMonth());
5167
5168 const QLocale loc = locale();
5169 for (int i=0; i<sectionNodesCount; ++i) {
5170 if (sectionType(i) & (DaySection|DayOfWeekSection)) {
5171 input.replace(sectionPos(i), sectionSize(i), loc.toString(day));
5172 }
5173 }
5174 } else {
5175 state = qMin(Intermediate, state);
5176 }
5177 }
5178 }
5179
5180 if (parserType != QVariant::Date) {
5181 if (isSet & Hour12Section) {
5182 const bool hasHour = isSet & Hour24Section;
5183 if (ampm == -1) {
5184 if (hasHour) {
5185 ampm = (hour < 12 ? 0 : 1);
5186 } else {
5187 ampm = 0; // no way to tell if this is am or pm so I assume am
5188 }
5189 }
5190 hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12);
5191 if (!hasHour) {
5192 hour = hour12;
5193 } else if (hour != hour12) {
5194 conflicts = true;
5195 }
5196 } else if (ampm != -1) {
5197 if (!(isSet & (Hour24Section))) {
5198 hour = (12 * ampm); // special case. Only ap section
5199 } else if ((ampm == 0) != (hour < 12)) {
5200 conflicts = true;
5201 }
5202 }
5203
5204 }
5205
5206 newCurrentValue = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
5207 QDTPDEBUG << year << month << day << hour << minute << second << msec;
5208 }
5209 QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
5210 newCurrentValue.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(),
5211 stateName(state).toLatin1().constData());
5212 }
5213 end:
5214 if (newCurrentValue.isValid()) {
5215 if (context != FromString && state != Invalid && newCurrentValue < minimum) {
5216 const QLatin1Char space(' ');
5217 if (newCurrentValue >= minimum)
5218 qWarning("QDateTimeParser::parse Internal error 3 (%s %s)",
5219 qPrintable(newCurrentValue.toString()), qPrintable(minimum.toString()));
5220
5221 bool done = false;
5222 state = Invalid;
5223 for (int i=0; i<sectionNodesCount && !done; ++i) {
5224 const SectionNode &sn = sectionNodes.at(i);
5225 QString t = sectionText(input, i, sn.pos).toLower();
5226 if ((t.size() < sectionMaxSize(i) && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric))
5227 || t.contains(space)) {
5228 switch (sn.type) {
5229 case AmPmSection:
5230 switch (findAmPm(t, i)) {
5231 case AM:
5232 case PM:
5233 state = Acceptable;
5234 done = true;
5235 break;
5236 case Neither:
5237 state = Invalid;
5238 done = true;
5239 break;
5240 case PossibleAM:
5241 case PossiblePM:
5242 case PossibleBoth: {
5243 const QDateTime copy(newCurrentValue.addSecs(12 * 60 * 60));
5244 if (copy >= minimum && copy <= maximum) {
5245 state = Intermediate;
5246 done = true;
5247 }
5248 break; }
5249 }
5250 case MonthSection:
5251 if (sn.count >= 3) {
5252 int tmp = newCurrentValue.date().month();
5253 // I know the first possible month makes the date too early
5254 while ((tmp = findMonth(t, tmp + 1, i)) != -1) {
5255 const QDateTime copy(newCurrentValue.addMonths(tmp - newCurrentValue.date().month()));
5256 if (copy >= minimum && copy <= maximum)
5257 break; // break out of while
5258 }
5259 if (tmp == -1) {
5260 break;
5261 }
5262 state = Intermediate;
5263 done = true;
5264 break;
5265 }
5266 // fallthrough
5267 default: {
5268 int toMin;
5269 int toMax;
5270
5271 if (sn.type & TimeSectionMask) {
5272 if (newCurrentValue.daysTo(minimum) != 0) {
5273 break;
5274 }
5275 toMin = newCurrentValue.time().msecsTo(minimum.time());
5276 if (newCurrentValue.daysTo(maximum) > 0) {
5277 toMax = -1; // can't get to max
5278 } else {
5279 toMax = newCurrentValue.time().msecsTo(maximum.time());
5280 }
5281 } else {
5282 toMin = newCurrentValue.daysTo(minimum);
5283 toMax = newCurrentValue.daysTo(maximum);
5284 }
5285 const int maxChange = QDateTimeParser::maxChange(i);
5286 if (toMin > maxChange) {
5287 QDTPDEBUG << "invalid because toMin > maxChange" << toMin
5288 << maxChange << t << newCurrentValue << minimum;
5289 state = Invalid;
5290 done = true;
5291 break;
5292 } else if (toMax > maxChange) {
5293 toMax = -1; // can't get to max
5294 }
5295
5296 const int min = getDigit(minimum, i);
5297 if (min == -1) {
5298 qWarning("QDateTimeParser::parse Internal error 4 (%s)",
5299 qPrintable(sectionName(sn.type)));
5300 state = Invalid;
5301 done = true;
5302 break;
5303 }
5304
5305 int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, newCurrentValue);
5306 int pos = cursorPosition - sn.pos;
5307 if (pos < 0 || pos >= t.size())
5308 pos = -1;
5309 if (!potentialValue(t.simplified(), min, max, i, newCurrentValue, pos)) {
5310 QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max
5311 << sectionName(sn.type) << "returned" << toMax << toMin << pos;
5312 state = Invalid;
5313 done = true;
5314 break;
5315 }
5316 state = Intermediate;
5317 done = true;
5318 break; }
5319 }
5320 }
5321 }
5322 } else {
5323 if (context == FromString) {
5324 // optimization
5325 Q_ASSERT(getMaximum().date().toJulianDay() == 4642999);
5326 if (newCurrentValue.date().toJulianDay() > 4642999)
5327 state = Invalid;
5328 } else {
5329 if (newCurrentValue > getMaximum())
5330 state = Invalid;
5331 }
5332
5333 QDTPDEBUG << "not checking intermediate because newCurrentValue is" << newCurrentValue << getMinimum() << getMaximum();
5334 }
5335 }
5336 StateNode node;
5337 node.input = input;
5338 node.state = state;
5339 node.conflicts = conflicts;
5340 node.value = newCurrentValue.toTimeSpec(spec);
5341 text = input;
5342 return node;
5343 }
5344 #endif // QT_NO_DATESTRING
5345
5346 #ifndef QT_NO_TEXTDATE
5347 /*!
5348 \internal finds the first possible monthname that \a str1 can
5349 match. Starting from \a index; str should already by lowered
5350 */
5351
findMonth(const QString & str1,int startMonth,int sectionIndex,QString * usedMonth,int * used) const5352 int QDateTimeParser::findMonth(const QString &str1, int startMonth, int sectionIndex,
5353 QString *usedMonth, int *used) const
5354 {
5355 int bestMatch = -1;
5356 int bestCount = 0;
5357 if (!str1.isEmpty()) {
5358 const SectionNode &sn = sectionNode(sectionIndex);
5359 if (sn.type != MonthSection) {
5360 qWarning("QDateTimeParser::findMonth Internal error");
5361 return -1;
5362 }
5363
5364 QLocale::FormatType type = sn.count == 3 ? QLocale::ShortFormat : QLocale::LongFormat;
5365 QLocale l = locale();
5366
5367 for (int month=startMonth; month<=12; ++month) {
5368 QString str2 = l.monthName(month, type).toLower();
5369
5370 if (str1.startsWith(str2)) {
5371 if (used) {
5372 QDTPDEBUG << "used is set to" << str2.size();
5373 *used = str2.size();
5374 }
5375 if (usedMonth)
5376 *usedMonth = l.monthName(month, type);
5377
5378 return month;
5379 }
5380 if (context == FromString)
5381 continue;
5382
5383 const int limit = qMin(str1.size(), str2.size());
5384
5385 QDTPDEBUG << "limit is" << limit << str1 << str2;
5386 bool equal = true;
5387 for (int i=0; i<limit; ++i) {
5388 if (str1.at(i) != str2.at(i)) {
5389 equal = false;
5390 if (i > bestCount) {
5391 bestCount = i;
5392 bestMatch = month;
5393 }
5394 break;
5395 }
5396 }
5397 if (equal) {
5398 if (used)
5399 *used = limit;
5400 if (usedMonth)
5401 *usedMonth = l.monthName(month, type);
5402 return month;
5403 }
5404 }
5405 if (usedMonth && bestMatch != -1)
5406 *usedMonth = l.monthName(bestMatch, type);
5407 }
5408 if (used) {
5409 QDTPDEBUG << "used is set to" << bestCount;
5410 *used = bestCount;
5411 }
5412 return bestMatch;
5413 }
5414
findDay(const QString & str1,int startDay,int sectionIndex,QString * usedDay,int * used) const5415 int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex, QString *usedDay, int *used) const
5416 {
5417 int bestMatch = -1;
5418 int bestCount = 0;
5419 if (!str1.isEmpty()) {
5420 const SectionNode &sn = sectionNode(sectionIndex);
5421 if (!(sn.type & (DaySection|DayOfWeekSection))) {
5422 qWarning("QDateTimeParser::findDay Internal error");
5423 return -1;
5424 }
5425 const QLocale l = locale();
5426 for (int day=startDay; day<=7; ++day) {
5427 const QString str2 = l.dayName(day, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
5428
5429 if (str1.startsWith(str2.toLower())) {
5430 if (used)
5431 *used = str2.size();
5432 if (usedDay) {
5433 *usedDay = str2;
5434 }
5435 return day;
5436 }
5437 if (context == FromString)
5438 continue;
5439
5440 const int limit = qMin(str1.size(), str2.size());
5441 bool found = true;
5442 for (int i=0; i<limit; ++i) {
5443 if (str1.at(i) != str2.at(i) && !str1.at(i).isSpace()) {
5444 if (i > bestCount) {
5445 bestCount = i;
5446 bestMatch = day;
5447 }
5448 found = false;
5449 break;
5450 }
5451
5452 }
5453 if (found) {
5454 if (used)
5455 *used = limit;
5456 if (usedDay)
5457 *usedDay = str2;
5458
5459 return day;
5460 }
5461 }
5462 if (usedDay && bestMatch != -1) {
5463 *usedDay = l.dayName(bestMatch, sn.count == 4 ? QLocale::LongFormat : QLocale::ShortFormat);
5464 }
5465 }
5466 if (used)
5467 *used = bestCount;
5468
5469 return bestMatch;
5470 }
5471 #endif // QT_NO_TEXTDATE
5472
5473 /*!
5474 \internal
5475
5476 returns
5477 0 if str == QDateTimeEdit::tr("AM")
5478 1 if str == QDateTimeEdit::tr("PM")
5479 2 if str can become QDateTimeEdit::tr("AM")
5480 3 if str can become QDateTimeEdit::tr("PM")
5481 4 if str can become QDateTimeEdit::tr("PM") and can become QDateTimeEdit::tr("AM")
5482 -1 can't become anything sensible
5483
5484 */
5485
findAmPm(QString & str,int index,int * used) const5486 int QDateTimeParser::findAmPm(QString &str, int index, int *used) const
5487 {
5488 const SectionNode &s = sectionNode(index);
5489 if (s.type != AmPmSection) {
5490 qWarning("QDateTimeParser::findAmPm Internal error");
5491 return -1;
5492 }
5493 if (used)
5494 *used = str.size();
5495 if (str.trimmed().isEmpty()) {
5496 return PossibleBoth;
5497 }
5498 const QLatin1Char space(' ');
5499 int size = sectionMaxSize(index);
5500
5501 enum {
5502 amindex = 0,
5503 pmindex = 1
5504 };
5505 QString ampm[2];
5506 ampm[amindex] = getAmPmText(AmText, s.count == 1 ? UpperCase : LowerCase);
5507 ampm[pmindex] = getAmPmText(PmText, s.count == 1 ? UpperCase : LowerCase);
5508 for (int i=0; i<2; ++i)
5509 ampm[i].truncate(size);
5510
5511 QDTPDEBUG << "findAmPm" << str << ampm[0] << ampm[1];
5512
5513 if (str.indexOf(ampm[amindex], 0, Qt::CaseInsensitive) == 0) {
5514 str = ampm[amindex];
5515 return AM;
5516 } else if (str.indexOf(ampm[pmindex], 0, Qt::CaseInsensitive) == 0) {
5517 str = ampm[pmindex];
5518 return PM;
5519 } else if (context == FromString || (str.count(space) == 0 && str.size() >= size)) {
5520 return Neither;
5521 }
5522 size = qMin(size, str.size());
5523
5524 bool broken[2] = {false, false};
5525 for (int i=0; i<size; ++i) {
5526 if (str.at(i) != space) {
5527 for (int j=0; j<2; ++j) {
5528 if (!broken[j]) {
5529 int index = ampm[j].indexOf(str.at(i));
5530 QDTPDEBUG << "looking for" << str.at(i)
5531 << "in" << ampm[j] << "and got" << index;
5532 if (index == -1) {
5533 if (str.at(i).category() == QChar::Letter_Uppercase) {
5534 index = ampm[j].indexOf(str.at(i).toLower());
5535 QDTPDEBUG << "trying with" << str.at(i).toLower()
5536 << "in" << ampm[j] << "and got" << index;
5537 } else if (str.at(i).category() == QChar::Letter_Lowercase) {
5538 index = ampm[j].indexOf(str.at(i).toUpper());
5539 QDTPDEBUG << "trying with" << str.at(i).toUpper()
5540 << "in" << ampm[j] << "and got" << index;
5541 }
5542 if (index == -1) {
5543 broken[j] = true;
5544 if (broken[amindex] && broken[pmindex]) {
5545 QDTPDEBUG << str << "didn't make it";
5546 return Neither;
5547 }
5548 continue;
5549 } else {
5550 str[i] = ampm[j].at(index); // fix case
5551 }
5552 }
5553 ampm[j].remove(index, 1);
5554 }
5555 }
5556 }
5557 }
5558 if (!broken[pmindex] && !broken[amindex])
5559 return PossibleBoth;
5560 return (!broken[amindex] ? PossibleAM : PossiblePM);
5561 }
5562
5563 /*!
5564 \internal
5565 Max number of units that can be changed by this section.
5566 */
5567
maxChange(int index) const5568 int QDateTimeParser::maxChange(int index) const
5569 {
5570 const SectionNode &sn = sectionNode(index);
5571 switch (sn.type) {
5572 // Time. unit is msec
5573 case MSecSection: return 999;
5574 case SecondSection: return 59 * 1000;
5575 case MinuteSection: return 59 * 60 * 1000;
5576 case Hour24Section: case Hour12Section: return 59 * 60 * 60 * 1000;
5577
5578 // Date. unit is day
5579 case DayOfWeekSection: return 7;
5580 case DaySection: return 30;
5581 case MonthSection: return 365 - 31;
5582 case YearSection: return 9999 * 365;
5583 case YearSection2Digits: return 100 * 365;
5584 default:
5585 qWarning("QDateTimeParser::maxChange() Internal error (%s)",
5586 qPrintable(sectionName(sectionType(index))));
5587 }
5588
5589 return -1;
5590 }
5591
fieldInfo(int index) const5592 QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const
5593 {
5594 FieldInfo ret = 0;
5595 const SectionNode &sn = sectionNode(index);
5596 const Section s = sn.type;
5597 switch (s) {
5598 case MSecSection:
5599 ret |= Fraction;
5600 // fallthrough
5601 case SecondSection:
5602 case MinuteSection:
5603 case Hour24Section:
5604 case Hour12Section:
5605 case YearSection:
5606 case YearSection2Digits:
5607 ret |= Numeric;
5608 if (s != YearSection) {
5609 ret |= AllowPartial;
5610 }
5611 if (sn.count != 1) {
5612 ret |= FixedWidth;
5613 }
5614 break;
5615 case MonthSection:
5616 case DaySection:
5617 switch (sn.count) {
5618 case 2:
5619 ret |= FixedWidth;
5620 // fallthrough
5621 case 1:
5622 ret |= (Numeric|AllowPartial);
5623 break;
5624 }
5625 break;
5626 case DayOfWeekSection:
5627 if (sn.count == 3)
5628 ret |= FixedWidth;
5629 break;
5630 case AmPmSection:
5631 ret |= FixedWidth;
5632 break;
5633 default:
5634 qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %s %d)",
5635 index, qPrintable(sectionName(sn.type)), sn.count);
5636 break;
5637 }
5638 return ret;
5639 }
5640
5641 /*!
5642 \internal Get a number that str can become which is between min
5643 and max or -1 if this is not possible.
5644 */
5645
5646
sectionFormat(int index) const5647 QString QDateTimeParser::sectionFormat(int index) const
5648 {
5649 const SectionNode &sn = sectionNode(index);
5650 return sectionFormat(sn.type, sn.count);
5651 }
5652
sectionFormat(Section s,int count) const5653 QString QDateTimeParser::sectionFormat(Section s, int count) const
5654 {
5655 QChar fillChar;
5656 switch (s) {
5657 case AmPmSection: return count == 1 ? QLatin1String("AP") : QLatin1String("ap");
5658 case MSecSection: fillChar = QLatin1Char('z'); break;
5659 case SecondSection: fillChar = QLatin1Char('s'); break;
5660 case MinuteSection: fillChar = QLatin1Char('m'); break;
5661 case Hour24Section: fillChar = QLatin1Char('H'); break;
5662 case Hour12Section: fillChar = QLatin1Char('h'); break;
5663 case DayOfWeekSection:
5664 case DaySection: fillChar = QLatin1Char('d'); break;
5665 case MonthSection: fillChar = QLatin1Char('M'); break;
5666 case YearSection2Digits:
5667 case YearSection: fillChar = QLatin1Char('y'); break;
5668 default:
5669 qWarning("QDateTimeParser::sectionFormat Internal error (%s)",
5670 qPrintable(sectionName(s)));
5671 return QString();
5672 }
5673 if (fillChar.isNull()) {
5674 qWarning("QDateTimeParser::sectionFormat Internal error 2");
5675 return QString();
5676 }
5677
5678 QString str;
5679 str.fill(fillChar, count);
5680 return str;
5681 }
5682
5683
5684 /*! \internal Returns true if str can be modified to represent a
5685 number that is within min and max.
5686 */
5687
potentialValue(const QString & str,int min,int max,int index,const QDateTime & currentValue,int insert) const5688 bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index,
5689 const QDateTime ¤tValue, int insert) const
5690 {
5691 if (str.isEmpty()) {
5692 return true;
5693 }
5694 const int size = sectionMaxSize(index);
5695 int val = (int)locale().toUInt(str);
5696 const SectionNode &sn = sectionNode(index);
5697 if (sn.type == YearSection2Digits) {
5698 val += currentValue.date().year() - (currentValue.date().year() % 100);
5699 }
5700 if (val >= min && val <= max && str.size() == size) {
5701 return true;
5702 } else if (val > max) {
5703 return false;
5704 } else if (str.size() == size && val < min) {
5705 return false;
5706 }
5707
5708 const int len = size - str.size();
5709 for (int i=0; i<len; ++i) {
5710 for (int j=0; j<10; ++j) {
5711 if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) {
5712 return true;
5713 } else if (insert >= 0) {
5714 QString tmp = str;
5715 tmp.insert(insert, QLatin1Char('0' + j));
5716 if (potentialValue(tmp, min, max, index, currentValue, insert))
5717 return true;
5718 }
5719 }
5720 }
5721
5722 return false;
5723 }
5724
skipToNextSection(int index,const QDateTime & current,const QString & text) const5725 bool QDateTimeParser::skipToNextSection(int index, const QDateTime ¤t, const QString &text) const
5726 {
5727 Q_ASSERT(current >= getMinimum() && current <= getMaximum());
5728
5729 const SectionNode &node = sectionNode(index);
5730 Q_ASSERT(text.size() < sectionMaxSize(index));
5731
5732 const QDateTime maximum = getMaximum();
5733 const QDateTime minimum = getMinimum();
5734 QDateTime tmp = current;
5735 int min = absoluteMin(index);
5736 setDigit(tmp, index, min);
5737 if (tmp < minimum) {
5738 min = getDigit(minimum, index);
5739 }
5740
5741 int max = absoluteMax(index, current);
5742 setDigit(tmp, index, max);
5743 if (tmp > maximum) {
5744 max = getDigit(maximum, index);
5745 }
5746 int pos = cursorPosition() - node.pos;
5747 if (pos < 0 || pos >= text.size())
5748 pos = -1;
5749
5750 const bool potential = potentialValue(text, min, max, index, current, pos);
5751 return !potential;
5752
5753 /* If the value potentially can become another valid entry we
5754 * don't want to skip to the next. E.g. In a M field (month
5755 * without leading 0 if you type 1 we don't want to autoskip but
5756 * if you type 3 we do
5757 */
5758 }
5759
5760 /*!
5761 \internal
5762 For debugging. Returns the name of the section \a s.
5763 */
5764
sectionName(int s) const5765 QString QDateTimeParser::sectionName(int s) const
5766 {
5767 switch (s) {
5768 case QDateTimeParser::AmPmSection: return QLatin1String("AmPmSection");
5769 case QDateTimeParser::DaySection: return QLatin1String("DaySection");
5770 case QDateTimeParser::DayOfWeekSection: return QLatin1String("DayOfWeekSection");
5771 case QDateTimeParser::Hour24Section: return QLatin1String("Hour24Section");
5772 case QDateTimeParser::Hour12Section: return QLatin1String("Hour12Section");
5773 case QDateTimeParser::MSecSection: return QLatin1String("MSecSection");
5774 case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection");
5775 case QDateTimeParser::MonthSection: return QLatin1String("MonthSection");
5776 case QDateTimeParser::SecondSection: return QLatin1String("SecondSection");
5777 case QDateTimeParser::YearSection: return QLatin1String("YearSection");
5778 case QDateTimeParser::YearSection2Digits: return QLatin1String("YearSection2Digits");
5779 case QDateTimeParser::NoSection: return QLatin1String("NoSection");
5780 case QDateTimeParser::FirstSection: return QLatin1String("FirstSection");
5781 case QDateTimeParser::LastSection: return QLatin1String("LastSection");
5782 default: return QLatin1String("Unknown section ") + QString::number(s);
5783 }
5784 }
5785
5786 /*!
5787 \internal
5788 For debugging. Returns the name of the state \a s.
5789 */
5790
stateName(int s) const5791 QString QDateTimeParser::stateName(int s) const
5792 {
5793 switch (s) {
5794 case Invalid: return QLatin1String("Invalid");
5795 case Intermediate: return QLatin1String("Intermediate");
5796 case Acceptable: return QLatin1String("Acceptable");
5797 default: return QLatin1String("Unknown state ") + QString::number(s);
5798 }
5799 }
5800
5801 #ifndef QT_NO_DATESTRING
fromString(const QString & t,QDate * date,QTime * time) const5802 bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const
5803 {
5804 QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN);
5805 QString text = t;
5806 int copy = -1;
5807 const StateNode tmp = parse(text, copy, val, false);
5808 if (tmp.state != Acceptable || tmp.conflicts) {
5809 return false;
5810 }
5811 if (time) {
5812 const QTime t = tmp.value.time();
5813 if (!t.isValid()) {
5814 return false;
5815 }
5816 *time = t;
5817 }
5818
5819 if (date) {
5820 const QDate d = tmp.value.date();
5821 if (!d.isValid()) {
5822 return false;
5823 }
5824 *date = d;
5825 }
5826 return true;
5827 }
5828 #endif // QT_NO_DATESTRING
5829
getMinimum() const5830 QDateTime QDateTimeParser::getMinimum() const
5831 {
5832 return QDateTime(QDATETIMEEDIT_DATE_MIN, QDATETIMEEDIT_TIME_MIN, spec);
5833 }
5834
getMaximum() const5835 QDateTime QDateTimeParser::getMaximum() const
5836 {
5837 return QDateTime(QDATETIMEEDIT_DATE_MAX, QDATETIMEEDIT_TIME_MAX, spec);
5838 }
5839
getAmPmText(AmPm ap,Case cs) const5840 QString QDateTimeParser::getAmPmText(AmPm ap, Case cs) const
5841 {
5842 if (ap == AmText) {
5843 return (cs == UpperCase ? QLatin1String("AM") : QLatin1String("am"));
5844 } else {
5845 return (cs == UpperCase ? QLatin1String("PM") : QLatin1String("pm"));
5846 }
5847 }
5848
5849 /*
5850 \internal
5851
5852 I give arg2 preference because arg1 is always a QDateTime.
5853 */
5854
operator ==(const QDateTimeParser::SectionNode & s1,const QDateTimeParser::SectionNode & s2)5855 bool operator==(const QDateTimeParser::SectionNode &s1, const QDateTimeParser::SectionNode &s2)
5856 {
5857 return (s1.type == s2.type) && (s1.pos == s2.pos) && (s1.count == s2.count);
5858 }
5859
5860 #ifdef Q_OS_SYMBIAN
5861 const static TTime UnixEpochOffset(I64LIT(0xdcddb30f2f8000));
5862 const static TInt64 MinimumMillisecondTime(KMinTInt64 / 1000);
5863 const static TInt64 MaximumMillisecondTime(KMaxTInt64 / 1000);
qt_symbian_TTime_To_QDateTime(const TTime & time)5864 QDateTime qt_symbian_TTime_To_QDateTime(const TTime& time)
5865 {
5866 TTimeIntervalMicroSeconds absolute = time.MicroSecondsFrom(UnixEpochOffset);
5867
5868 return QDateTime::fromMSecsSinceEpoch(absolute.Int64() / 1000);
5869 }
5870
qt_symbian_QDateTime_To_TTime(const QDateTime & datetime)5871 TTime qt_symbian_QDateTime_To_TTime(const QDateTime& datetime)
5872 {
5873 qint64 absolute = datetime.toMSecsSinceEpoch();
5874 if(absolute > MaximumMillisecondTime)
5875 return TTime(KMaxTInt64);
5876 if(absolute < MinimumMillisecondTime)
5877 return TTime(KMinTInt64);
5878 return TTime(absolute * 1000);
5879 }
5880
qt_symbian_TTime_To_time_t(const TTime & time)5881 time_t qt_symbian_TTime_To_time_t(const TTime& time)
5882 {
5883 TTimeIntervalSeconds interval;
5884 TInt err = time.SecondsFrom(UnixEpochOffset, interval);
5885 if (err || interval.Int() < 0)
5886 return (time_t) 0;
5887 return (time_t) interval.Int();
5888 }
5889
qt_symbian_time_t_To_TTime(time_t time)5890 TTime qt_symbian_time_t_To_TTime(time_t time)
5891 {
5892 return UnixEpochOffset + TTimeIntervalSeconds(time);
5893 }
5894 #endif //Q_OS_SYMBIAN
5895
5896 #endif // QT_BOOTSTRAPPED
5897
5898 QT_END_NAMESPACE
5899