source: trunk/src/corelib/tools/qdatetime.cpp@ 265

Last change on this file since 265 was 79, checked in by Dmitry A. Kuminov, 16 years ago

Adopted QDateTime to OS/2 (posix).

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