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