00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "qplatformdefs.h"
00039
00040 #include "qdatetime.h"
00041 #include "qdatastream.h"
00042 #include "qregexp.h"
00043
00044 #include <stdio.h>
00045 #ifndef Q_OS_TEMP
00046 #include <time.h>
00047 #endif
00048
00049 #if defined(Q_OS_WIN32)
00050 #include <windows.h>
00051 #endif
00052
00053 static const uint FIRST_DAY = 2361222;
00054 static const int FIRST_YEAR = 1752;
00055 static const uint SECS_PER_DAY = 86400;
00056 static const uint MSECS_PER_DAY = 86400000;
00057 static const uint SECS_PER_HOUR = 3600;
00058 static const uint MSECS_PER_HOUR= 3600000;
00059 static const uint SECS_PER_MIN = 60;
00060 static const uint MSECS_PER_MIN = 60000;
00061
00062 static const short monthDays[] = {
00063 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
00064
00065 static const char * const qt_shortMonthNames[] = {
00066 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00067 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
00068
00069 #ifndef QT_NO_DATESTRING
00070
00071
00072
00073
00074
00075 static QString getFmtString( const QString& f, const QTime* dt = 0, const QDate* dd = 0, bool am_pm = FALSE )
00076 {
00077 if ( f.isEmpty() )
00078 return QString::null;
00079
00080 QString buf = f;
00081
00082 if ( dt ) {
00083 if ( f == "h" ) {
00084 if ( ( am_pm ) && ( dt->hour() > 12 ) )
00085 buf = QString::number( dt->hour() - 12 );
00086 else if ( ( am_pm ) && ( dt->hour() == 0 ) )
00087 buf = "12";
00088 else
00089 buf = QString::number( dt->hour() );
00090 } else if ( f == "hh" ) {
00091 if ( ( am_pm ) && ( dt->hour() > 12 ) )
00092 buf = QString::number( dt->hour() - 12 ).rightJustify( 2, '0', TRUE );
00093 else if ( ( am_pm ) && ( dt->hour() == 0 ) )
00094 buf = "12";
00095 else
00096 buf = QString::number( dt->hour() ).rightJustify( 2, '0', TRUE );
00097 } else if ( f == "m" ) {
00098 buf = QString::number( dt->minute() );
00099 } else if ( f == "mm" ) {
00100 buf = QString::number( dt->minute() ).rightJustify( 2, '0', TRUE );
00101 } else if ( f == "s" ) {
00102 buf = QString::number( dt->second() );
00103 } else if ( f == "ss" ) {
00104 buf = QString::number( dt->second() ).rightJustify( 2, '0', TRUE );
00105 } else if ( f == "z" ) {
00106 buf = QString::number( dt->msec() );
00107 } else if ( f == "zzz" ) {
00108 buf = QString::number( dt->msec() ).rightJustify( 3, '0', TRUE );
00109 } else if ( f == "ap" ) {
00110 buf = dt->hour() < 12 ? "am" : "pm";
00111 } else if ( f == "AP" ) {
00112 buf = dt->hour() < 12 ? "AM" : "PM";
00113 }
00114 }
00115
00116 if ( dd ) {
00117 if ( f == "d" ) {
00118 buf = QString::number( dd->day() );
00119 } else if ( f == "dd" ) {
00120 buf = QString::number( dd->day() ).rightJustify( 2, '0', TRUE );
00121 } else if ( f == "M" ) {
00122 buf = QString::number( dd->month() );
00123 } else if ( f == "MM" ) {
00124 buf = QString::number( dd->month() ).rightJustify( 2, '0', TRUE );
00125 #ifndef QT_NO_TEXTDATE
00126 } else if ( f == "ddd" ) {
00127 buf = dd->shortDayName( dd->dayOfWeek() );
00128 } else if ( f == "dddd" ) {
00129 buf = dd->longDayName( dd->dayOfWeek() );
00130 } else if ( f == "MMM" ) {
00131 buf = dd->shortMonthName( dd->month() );
00132 } else if ( f == "MMMM" ) {
00133 buf = dd->longMonthName( dd->month() );
00134 #endif
00135 } else if ( f == "yy" ) {
00136 buf = QString::number( dd->year() ).right( 2 );
00137 } else if ( f == "yyyy" ) {
00138 buf = QString::number( dd->year() );
00139 }
00140 }
00141
00142 return buf;
00143 }
00144
00145
00146 static QString fmtDateTime( const QString& f, const QTime* dt = 0, const QDate* dd = 0 )
00147 {
00148 if ( f.isEmpty() ) {
00149 return QString::null;
00150 }
00151
00152 bool ap = ( f.contains( "AP" ) || f.contains( "ap" ) );
00153
00154 QString buf;
00155 QString frm;
00156 QChar status = '0';
00157
00158 for ( int i = 0; i < (int)f.length(); ++i ) {
00159
00160 if ( f[ i ] == status ) {
00161 if ( ( ap ) && ( ( f[ i ] == 'P' ) || ( f[ i ] == 'p' ) ) )
00162 status = '0';
00163 frm += f[ i ];
00164 } else {
00165 buf += getFmtString( frm, dt, dd, ap );
00166 frm = QString::null;
00167 if ( ( f[ i ] == 'h' ) || ( f[ i ] == 'm' ) || ( f[ i ] == 's' ) || ( f[ i ] == 'z' ) ) {
00168 status = f[ i ];
00169 frm += f[ i ];
00170 } else if ( ( f[ i ] == 'd' ) || ( f[ i ] == 'M' ) || ( f[ i ] == 'y' ) ) {
00171 status = f[ i ];
00172 frm += f[ i ];
00173 } else if ( ( ap ) && ( f[ i ] == 'A' ) ) {
00174 status = 'P';
00175 frm += f[ i ];
00176 } else if( ( ap ) && ( f[ i ] == 'a' ) ) {
00177 status = 'p';
00178 frm += f[ i ];
00179 } else {
00180 buf += f[ i ];
00181 status = '0';
00182 }
00183 }
00184 }
00185
00186 buf += getFmtString( frm, dt, dd, ap );
00187
00188 return buf;
00189 }
00190 #endif // QT_NO_DATESTRING
00191
00192
00193
00194
00195
00285 QDate::QDate( int y, int m, int d )
00286 {
00287 jd = 0;
00288 setYMD( y, m, d );
00289 }
00290
00291
00308 bool QDate::isValid() const
00309 {
00310 return jd >= FIRST_DAY;
00311 }
00312
00313
00320 int QDate::year() const
00321 {
00322 int y, m, d;
00323 julianToGregorian( jd, y, m, d );
00324 return y;
00325 }
00326
00333 int QDate::month() const
00334 {
00335 int y, m, d;
00336 julianToGregorian( jd, y, m, d );
00337 return m;
00338 }
00339
00346 int QDate::day() const
00347 {
00348 int y, m, d;
00349 julianToGregorian( jd, y, m, d );
00350 return d;
00351 }
00352
00359 int QDate::dayOfWeek() const
00360 {
00361 return ( jd % 7 ) + 1;
00362 }
00363
00370 int QDate::dayOfYear() const
00371 {
00372 return jd - gregorianToJulian(year(), 1, 1) + 1;
00373 }
00374
00381 int QDate::daysInMonth() const
00382 {
00383 int y, m, d;
00384 julianToGregorian( jd, y, m, d );
00385 if ( m == 2 && leapYear(y) )
00386 return 29;
00387 else
00388 return monthDays[m];
00389 }
00390
00397 int QDate::daysInYear() const
00398 {
00399 int y, m, d;
00400 julianToGregorian( jd, y, m, d );
00401 return leapYear( y ) ? 366 : 365;
00402 }
00403
00421 int QDate::weekNumber( int *yearNumber ) const
00422 {
00423 if ( !isValid() )
00424 return 0;
00425
00426 int dow = dayOfWeek();
00427 int doy = dayOfYear();
00428 int currYear = year();
00429 int jan1WeekDay = QDate( currYear, 1, 1 ).dayOfWeek();
00430 int yearNum;
00431 int weekNum;
00432
00433 if ( doy <= (8 - jan1WeekDay) && jan1WeekDay > 4 ) {
00434 yearNum = currYear - 1;
00435 weekNum = 52;
00436 if ( jan1WeekDay == 5 ||
00437 (jan1WeekDay == 6 && QDate::leapYear(yearNum)) )
00438 weekNum++;
00439 } else {
00440 int totalDays = 365;
00441 if ( QDate::leapYear(currYear) )
00442 totalDays++;
00443
00444 if ( (totalDays - doy < 4 - dow)
00445 || (jan1WeekDay == 7 && totalDays - doy < 3) ) {
00446 yearNum = currYear + 1;
00447 weekNum = 1;
00448 } else {
00449 int j = doy + ( 7 - dow ) + ( jan1WeekDay - 1 );
00450 yearNum = currYear;
00451 weekNum = j / 7;
00452 if ( jan1WeekDay > 4 )
00453 weekNum--;
00454 }
00455 }
00456 if ( yearNumber )
00457 *yearNumber = yearNum;
00458 return weekNum;
00459 }
00460
00467 #ifndef QT_NO_TEXTDATE
00468
00479 QString QDate::shortMonthName( int month )
00480 {
00481 #if defined(QT_CHECK_RANGE)
00482 if ( month < 1 || month > 12 ) {
00483 qWarning( "QDate::shortMonthName: Parameter out ouf range." );
00484 month = 1;
00485 }
00486 #endif
00487 #ifndef Q_WS_WIN
00488 char buffer[255];
00489 tm tt;
00490 memset( &tt, 0, sizeof( tm ) );
00491 tt.tm_mon = month - 1;
00492 if ( strftime( buffer, sizeof( buffer ), "%b", &tt ) )
00493 return QString::fromLocal8Bit( buffer );
00494 #else
00495 SYSTEMTIME st;
00496 memset( &st, 0, sizeof(SYSTEMTIME) );
00497 st.wYear = 2000;
00498 st.wMonth = month;
00499 st.wDay = 1;
00500 const wchar_t mmm_t[] = L"MMM";
00501 QT_WA( {
00502 TCHAR buf[255];
00503 if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, mmm_t, buf, 255 ) )
00504 return QString::fromUcs2( (ushort*)buf );
00505 } , {
00506 char buf[255];
00507 if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, "MMM", (char*)&buf, 255 ) )
00508 return QString::fromLocal8Bit( buf );
00509 } );
00510 #endif
00511 return QString::null;
00512 }
00513
00525 QString QDate::longMonthName( int month )
00526 {
00527 #if defined(QT_CHECK_RANGE)
00528 if ( month < 1 || month > 12 ) {
00529 qWarning( "QDate::longMonthName: Parameter out ouf range." );
00530 month = 1;
00531 }
00532 #endif
00533 #ifndef Q_WS_WIN
00534 char buffer[255];
00535 tm tt;
00536 memset( &tt, 0, sizeof( tm ) );
00537 tt.tm_mon = month - 1;
00538 if ( strftime( buffer, sizeof( buffer ), "%B", &tt ) )
00539 return QString::fromLocal8Bit( buffer );
00540 #else
00541 SYSTEMTIME st;
00542 memset( &st, 0, sizeof(SYSTEMTIME) );
00543 st.wYear = 2000;
00544 st.wMonth = month;
00545 st.wDay = 1 ;
00546 const wchar_t mmmm_t[] = L"MMMM";
00547 QT_WA( {
00548 TCHAR buf[255];
00549 if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, mmmm_t, buf, 255 ) )
00550 return QString::fromUcs2( (ushort*)buf );
00551 } , {
00552 char buf[255];
00553 if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, "MMMM", (char*)&buf, 255 ) )
00554 return QString::fromLocal8Bit( buf );
00555 } )
00556 #endif
00557
00558 return QString::null;
00559 }
00560
00579 QString QDate::shortDayName( int weekday )
00580 {
00581 #if defined(QT_CHECK_RANGE)
00582 if ( weekday < 1 || weekday > 7 ) {
00583 qWarning( "QDate::shortDayName: Parameter out of range." );
00584 weekday = 1;
00585 }
00586 #endif
00587 #ifndef Q_WS_WIN
00588 char buffer[255];
00589 tm tt;
00590 memset( &tt, 0, sizeof( tm ) );
00591 tt.tm_wday = ( weekday == 7 ) ? 0 : weekday;
00592 if ( strftime( buffer, sizeof( buffer ), "%a", &tt ) )
00593 return QString::fromLocal8Bit( buffer );
00594 #else
00595 SYSTEMTIME st;
00596 memset( &st, 0, sizeof(SYSTEMTIME) );
00597 st.wYear = 2001;
00598 st.wMonth = 10;
00599 st.wDayOfWeek = ( weekday == 7 ) ? 0 : weekday;
00600 st.wDay = 21 + st.wDayOfWeek;
00601 const wchar_t ddd_t[] = L"ddd";
00602 QT_WA( {
00603 TCHAR buf[255];
00604 if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, ddd_t, buf, 255 ) )
00605 return QString::fromUcs2( (ushort*)buf );
00606 } , {
00607 char buf[255];
00608 if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, "ddd", (char*)&buf, 255 ) )
00609 return QString::fromLocal8Bit( buf );
00610 } );
00611 #endif
00612
00613 return QString::null;
00614 }
00615
00627 QString QDate::longDayName( int weekday )
00628 {
00629 #if defined(QT_CHECK_RANGE)
00630 if ( weekday < 1 || weekday > 7 ) {
00631 qWarning( "QDate::longDayName: Parameter out of range." );
00632 weekday = 1;
00633 }
00634 #endif
00635 #ifndef Q_WS_WIN
00636 char buffer[255];
00637 tm tt;
00638 memset( &tt, 0, sizeof( tm ) );
00639 tt.tm_wday = ( weekday == 7 ) ? 0 : weekday;
00640 if ( strftime( buffer, sizeof( buffer ), "%A", &tt ) )
00641 return QString::fromLocal8Bit( buffer );
00642 #else
00643 SYSTEMTIME st;
00644 memset( &st, 0, sizeof(SYSTEMTIME) );
00645 st.wYear = 2001;
00646 st.wMonth = 10;
00647 st.wDayOfWeek = ( weekday == 7 ) ? 0 : weekday;
00648 st.wDay = 21 + st.wDayOfWeek;
00649 const wchar_t dddd_t[] = L"dddd";
00650 QT_WA( {
00651 TCHAR buf[255];
00652 if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, dddd_t, buf, 255 ) )
00653 return QString::fromUcs2( (ushort*)buf );
00654 } , {
00655 char buf[255];
00656 if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, "dddd", (char*)&buf, 255 ) )
00657 return QString::fromLocal8Bit( buf );
00658 } );
00659 #endif
00660
00661 return QString::null;
00662 }
00663 #endif //QT_NO_TEXTDATE
00664
00665 #ifndef QT_NO_DATESTRING
00666
00667 #if !defined(QT_NO_SPRINTF)
00668
00690 QString QDate::toString( Qt::DateFormat f ) const
00691 {
00692 int y, m, d;
00693 julianToGregorian( jd, y, m, d );
00694 switch ( f ) {
00695 case Qt::LocalDate:
00696 {
00697 #ifndef Q_WS_WIN
00698 tm tt;
00699 memset( &tt, 0, sizeof( tm ) );
00700 char buf[255];
00701 tt.tm_mday = day();
00702 tt.tm_mon = month() - 1;
00703 tt.tm_year = year() - 1900;
00704
00705 static const char * avoidEgcsWarning = "%x";
00706 if ( strftime( buf, sizeof(buf), avoidEgcsWarning, &tt ) )
00707 return QString::fromLocal8Bit( buf );
00708 #else
00709 SYSTEMTIME st;
00710 memset( &st, 0, sizeof(SYSTEMTIME) );
00711 st.wYear = year();
00712 st.wMonth = month();
00713 st.wDay = day();
00714 QT_WA( {
00715 TCHAR buf[255];
00716 if ( GetDateFormat( LOCALE_USER_DEFAULT, 0, &st, 0, buf, 255 ) )
00717 return QString::fromUcs2( (ushort*)buf );
00718 } , {
00719 char buf[255];
00720 if ( GetDateFormatA( LOCALE_USER_DEFAULT, 0, &st, 0, (char*)&buf, 255 ) )
00721 return QString::fromLocal8Bit( buf );
00722 } );
00723 #endif
00724 return QString::null;
00725 }
00726 default:
00727 #ifndef QT_NO_TEXTDATE
00728 case Qt::TextDate:
00729 {
00730 QString buf = shortDayName( dayOfWeek() );
00731 buf += ' ';
00732 buf += shortMonthName( m );
00733 QString t;
00734 t.sprintf( " %d %d", d, y );
00735 buf += t;
00736 return buf;
00737 }
00738 #endif
00739 case Qt::ISODate:
00740 {
00741 QString month( QString::number( m ).rightJustify( 2, '0' ) );
00742 QString day( QString::number( d ).rightJustify( 2, '0' ) );
00743 return QString::number( y ) + "-" + month + "-" + day;
00744 }
00745 }
00746 }
00747 #endif //QT_NO_SPRINTF
00748
00790 QString QDate::toString( const QString& format ) const
00791 {
00792 return fmtDateTime( format, 0, this );
00793 }
00794 #endif //QT_NO_DATESTRING
00795
00808 bool QDate::setYMD( int y, int m, int d )
00809 {
00810 if ( year() == y && month() == m && day() == d )
00811 return isValid();
00812 if ( !isValid(y,m,d) ) {
00813 #if defined(QT_CHECK_RANGE)
00814 qWarning( "QDate::setYMD: Invalid date %04d-%02d-%02d", y, m, d );
00815 #endif
00816 return FALSE;
00817 }
00818 jd = gregorianToJulian( y, m, d );
00819 return TRUE;
00820 }
00821
00829 QDate QDate::addDays( int ndays ) const
00830 {
00831 QDate d;
00832 d.jd = jd + ndays;
00833 return d;
00834 }
00835
00843 QDate QDate::addMonths( int nmonths ) const
00844 {
00845 int y, m, d;
00846 julianToGregorian( jd, y, m, d );
00847
00848 while ( nmonths != 0 ) {
00849 if ( nmonths < 0 && nmonths + 12 <= 0 ) {
00850 y--;
00851 nmonths+=12;
00852 } else if ( nmonths < 0 ) {
00853 m+= nmonths;
00854 nmonths = 0;
00855 if ( m <= 0 ) {
00856 --y;
00857 m+=12;
00858 }
00859 } else if ( nmonths - 12 >= 0 ) {
00860 y++;
00861 nmonths-=12;
00862 } else if ( m == 12 ) {
00863 y++;
00864 m = 0;
00865 } else {
00866 m+= nmonths;
00867 nmonths = 0;
00868 if ( m > 12 ) {
00869 ++y;
00870 m -= 12;
00871 }
00872 }
00873 }
00874
00875 QDate tmp(y,m,1);
00876
00877 if( d > tmp.daysInMonth() )
00878 d = tmp.daysInMonth();
00879
00880 QDate date(y, m, d);
00881 return date;
00882
00883 }
00884
00892 QDate QDate::addYears( int nyears ) const
00893 {
00894 int y, m, d;
00895 julianToGregorian( jd, y, m, d );
00896 y += nyears;
00897
00898 QDate tmp(y,m,1);
00899
00900 if( d > tmp.daysInMonth() )
00901 d = tmp.daysInMonth();
00902
00903 QDate date(y, m, d);
00904 return date;
00905 }
00906
00907
00908
00924 int QDate::daysTo( const QDate &d ) const
00925 {
00926 return d.jd - jd;
00927 }
00928
00929
00975 QDate QDate::currentDate()
00976 {
00977 return currentDate( Qt::LocalTime );
00978 }
00979
00986 QDate QDate::currentDate( Qt::TimeSpec ts )
00987 {
00988 QDate d;
00989 #if defined(Q_OS_WIN32)
00990 SYSTEMTIME t;
00991 memset( &t, 0, sizeof(SYSTEMTIME) );
00992 if ( ts == Qt::LocalTime )
00993 GetLocalTime( &t );
00994 else
00995 GetSystemTime( &t );
00996 d.jd = gregorianToJulian( t.wYear, t.wMonth, t.wDay );
00997 #else
00998
00999 time_t ltime;
01000 time( <ime );
01001 tm *t;
01002
01003 # if defined(QT_THREAD_SUPPORT) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
01004
01005 tm res;
01006 if ( ts == Qt::LocalTime )
01007 t = localtime_r( <ime, &res );
01008 else
01009 t = gmtime_r( <ime, &res );
01010 # else
01011 if ( ts == Qt::LocalTime )
01012 t = localtime( <ime );
01013 else
01014 t = gmtime( <ime );
01015 # endif // QT_THREAD_SUPPORT && _POSIX_THREAD_SAFE_FUNCTIONS
01016
01017 d.jd = gregorianToJulian( t->tm_year + 1900, t->tm_mon + 1, t->tm_mday );
01018 #endif
01019 return d;
01020 }
01021
01022 #ifndef QT_NO_DATESTRING
01023
01033 QDate QDate::fromString( const QString& s, Qt::DateFormat f )
01034 {
01035 if ( ( s.isEmpty() ) || ( f == Qt::LocalDate ) ) {
01036 #if defined(QT_CHECK_RANGE)
01037 qWarning( "QDate::fromString: Parameter out of range." );
01038 #endif
01039 return QDate();
01040 }
01041 switch ( f ) {
01042 case Qt::ISODate:
01043 {
01044 int year( s.mid( 0, 4 ).toInt() );
01045 int month( s.mid( 5, 2 ).toInt() );
01046 int day( s.mid( 8, 2 ).toInt() );
01047 if ( year && month && day )
01048 return QDate( year, month, day );
01049 }
01050 break;
01051 default:
01052 #ifndef QT_NO_TEXTDATE
01053 case Qt::TextDate:
01054 {
01055
01056
01057
01058
01059 int monthPos = s.find( ' ' ) + 1;
01060 int dayPos = s.find( ' ', monthPos ) + 1;
01061
01062 QString monthName( s.mid(monthPos, dayPos - monthPos - 1) );
01063 int month = -1;
01064
01065
01066 for ( int i = 0; i < 12; i++ ) {
01067 if ( monthName == qt_shortMonthNames[i] ) {
01068 month = i + 1;
01069 break;
01070 }
01071 }
01072
01073
01074 if ( month == -1 ) {
01075 for ( int i = 0; i < 12; i++ ) {
01076 if ( monthName == shortMonthName( i + 1 ) ) {
01077 month = i + 1;
01078 break;
01079 }
01080 }
01081 }
01082 #if defined(QT_CHECK_RANGE)
01083 if ( month < 1 || month > 12 ) {
01084 qWarning( "QDate::fromString: Parameter out of range." );
01085 month = 1;
01086 }
01087 #endif
01088 int day = s.mid( dayPos, 2 ).stripWhiteSpace().toInt();
01089 int year = s.right( 4 ).toInt();
01090 return QDate( year, month, day );
01091 }
01092 #else
01093 break;
01094 #endif
01095 }
01096 return QDate();
01097 }
01098 #endif //QT_NO_DATESTRING
01099
01120 bool QDate::isValid( int y, int m, int d )
01121 {
01122 if ( y >= 0 && y <= 99 )
01123 y += 1900;
01124 else if ( y < FIRST_YEAR || (y == FIRST_YEAR && (m < 9 ||
01125 (m == 9 && d < 14))) )
01126 return FALSE;
01127 return (d > 0 && m > 0 && m <= 12) &&
01128 (d <= monthDays[m] || (d == 29 && m == 2 && leapYear(y)));
01129 }
01130
01136 bool QDate::leapYear( int y )
01137 {
01138 return y % 4 == 0 && y % 100 != 0 || y % 400 == 0;
01139 }
01140
01148 uint QDate::gregorianToJulian( int y, int m, int d )
01149 {
01150 uint c, ya;
01151 if ( y <= 99 )
01152 y += 1900;
01153 if ( m > 2 ) {
01154 m -= 3;
01155 } else {
01156 m += 9;
01157 y--;
01158 }
01159 c = y;
01160 c /= 100;
01161 ya = y - 100*c;
01162 return 1721119 + d + (146097*c)/4 + (1461*ya)/4 + (153*m+2)/5;
01163 }
01164
01172 void QDate::julianToGregorian( uint jd, int &y, int &m, int &d )
01173 {
01174 uint x;
01175 uint j = jd - 1721119;
01176 y = (j*4 - 1)/146097;
01177 j = j*4 - 146097*y - 1;
01178 x = j/4;
01179 j = (x*4 + 3) / 1461;
01180 y = 100*y + j;
01181 x = (x*4) + 3 - 1461*j;
01182 x = (x + 4)/4;
01183 m = (5*x - 3)/153;
01184 x = 5*x - 3 - 153*m;
01185 d = (x + 5)/5;
01186 if ( m < 10 ) {
01187 m += 3;
01188 } else {
01189 m -= 9;
01190 y++;
01191 }
01192 }
01193
01194
01195
01196
01197
01198
01264 QTime::QTime( int h, int m, int s, int ms )
01265 {
01266 setHMS( h, m, s, ms );
01267 }
01268
01269
01286 bool QTime::isValid() const
01287 {
01288 return ds < MSECS_PER_DAY;
01289 }
01290
01291
01296 int QTime::hour() const
01297 {
01298 return ds / MSECS_PER_HOUR;
01299 }
01300
01305 int QTime::minute() const
01306 {
01307 return (ds % MSECS_PER_HOUR)/MSECS_PER_MIN;
01308 }
01309
01314 int QTime::second() const
01315 {
01316 return (ds / 1000)%SECS_PER_MIN;
01317 }
01318
01323 int QTime::msec() const
01324 {
01325 return ds % 1000;
01326 }
01327
01328 #ifndef QT_NO_DATESTRING
01329 #ifndef QT_NO_SPRINTF
01330
01347 QString QTime::toString( Qt::DateFormat f ) const
01348 {
01349 switch ( f ) {
01350 case Qt::LocalDate:
01351 {
01352 #ifndef Q_WS_WIN
01353 tm tt;
01354 memset( &tt, 0, sizeof( tm ) );
01355 char buf[255];
01356 tt.tm_sec = second();
01357 tt.tm_min = minute();
01358 tt.tm_hour = hour();
01359 if ( strftime( buf, sizeof(buf), "%X", &tt ) )
01360 return QString::fromLocal8Bit( buf );
01361 #else
01362 SYSTEMTIME st;
01363 memset( &st, 0, sizeof(SYSTEMTIME) );
01364 st.wHour = hour();
01365 st.wMinute = minute();
01366 st.wSecond = second();
01367 st.wMilliseconds = 0;
01368 QT_WA( {
01369 TCHAR buf[255];
01370 if ( GetTimeFormat( LOCALE_USER_DEFAULT, 0, &st, 0, buf, 255 ) )
01371 return QString::fromUcs2( (ushort*)buf );
01372 } , {
01373 char buf[255];
01374 if ( GetTimeFormatA( LOCALE_USER_DEFAULT, 0, &st, 0, (char*)&buf, 255 ) )
01375 return QString::fromLocal8Bit( buf );
01376 } );
01377 #endif
01378 return QString::null;
01379 }
01380 default:
01381 case Qt::ISODate:
01382 case Qt::TextDate:
01383 QString buf;
01384 buf.sprintf( "%.2d:%.2d:%.2d", hour(), minute(), second() );
01385 return buf;
01386 }
01387 }
01388 #endif
01389
01426 QString QTime::toString( const QString& format ) const
01427 {
01428 return fmtDateTime( format, this, 0 );
01429 }
01430 #endif //QT_NO_DATESTRING
01431
01442 bool QTime::setHMS( int h, int m, int s, int ms )
01443 {
01444 if ( !isValid(h,m,s,ms) ) {
01445 #if defined(QT_CHECK_RANGE)
01446 qWarning( "QTime::setHMS Invalid time %02d:%02d:%02d.%03d", h, m, s,
01447 ms );
01448 #endif
01449 ds = MSECS_PER_DAY;
01450 return FALSE;
01451 }
01452 ds = (h*SECS_PER_HOUR + m*SECS_PER_MIN + s)*1000 + ms;
01453 return TRUE;
01454 }
01455
01475 QTime QTime::addSecs( int nsecs ) const
01476 {
01477 return addMSecs( nsecs * 1000 );
01478 }
01479
01490 int QTime::secsTo( const QTime &t ) const
01491 {
01492 return ((int)t.ds - (int)ds)/1000;
01493 }
01494
01505 QTime QTime::addMSecs( int ms ) const
01506 {
01507 QTime t;
01508 if ( ms < 0 ) {
01509
01510 int negdays = (MSECS_PER_DAY-ms) / MSECS_PER_DAY;
01511 t.ds = ((int)ds + ms + negdays*MSECS_PER_DAY)
01512 % MSECS_PER_DAY;
01513 } else {
01514 t.ds = ((int)ds + ms) % MSECS_PER_DAY;
01515 }
01516 return t;
01517 }
01518
01529 int QTime::msecsTo( const QTime &t ) const
01530 {
01531 return (int)t.ds - (int)ds;
01532 }
01533
01534
01584 QTime QTime::currentTime()
01585 {
01586 return currentTime( Qt::LocalTime );
01587 }
01588
01598 QTime QTime::currentTime( Qt::TimeSpec ts )
01599 {
01600 QTime t;
01601 currentTime( &t, ts );
01602 return t;
01603 }
01604
01605 #ifndef QT_NO_DATESTRING
01606
01612 QTime QTime::fromString( const QString& s, Qt::DateFormat f )
01613 {
01614 if ( ( s.isEmpty() ) || ( f == Qt::LocalDate ) ) {
01615 #if defined(QT_CHECK_RANGE)
01616 qWarning( "QTime::fromString: Parameter out of range." );
01617 #endif
01618 return QTime();
01619 }
01620
01621 int hour( s.mid( 0, 2 ).toInt() );
01622 int minute( s.mid( 3, 2 ).toInt() );
01623 int second( s.mid( 6, 2 ).toInt() );
01624 int msec( s.mid( 9, 3 ).toInt() );
01625 return QTime( hour, minute, second, msec );
01626 }
01627 #endif
01628
01638 bool QTime::currentTime( QTime *ct )
01639 {
01640 return currentTime( ct, Qt::LocalTime );
01641 }
01642
01643
01654 bool QTime::currentTime( QTime *ct, Qt::TimeSpec ts )
01655 {
01656 if ( !ct ) {
01657 #if defined(QT_CHECK_NULL)
01658 qWarning( "QTime::currentTime(QTime *): Null pointer not allowed" );
01659 #endif
01660 return FALSE;
01661 }
01662
01663 #if defined(Q_OS_WIN32)
01664 SYSTEMTIME t;
01665 if ( ts == Qt::LocalTime ) {
01666 GetLocalTime( &t );
01667 } else {
01668 GetSystemTime( &t );
01669 }
01670 ct->ds = (uint)( MSECS_PER_HOUR*t.wHour + MSECS_PER_MIN*t.wMinute +
01671 1000*t.wSecond + t.wMilliseconds );
01672 #elif defined(Q_OS_UNIX)
01673
01674 struct timeval tv;
01675 gettimeofday( &tv, 0 );
01676 time_t ltime = tv.tv_sec;
01677 tm *t;
01678
01679 # if defined(QT_THREAD_SUPPORT) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
01680
01681 tm res;
01682 if ( ts == Qt::LocalTime )
01683 t = localtime_r( <ime, &res );
01684 else
01685 t = gmtime_r( <ime, &res );
01686 # else
01687 if ( ts == Qt::LocalTime )
01688 t = localtime( <ime );
01689 else
01690 t = gmtime( <ime );
01691 # endif // QT_THREAD_SUPPORT && _POSIX_THREAD_SAFE_FUNCTIONS
01692
01693 ct->ds = (uint)( MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min +
01694 1000 * t->tm_sec + tv.tv_usec / 1000 );
01695 #else
01696 time_t ltime;
01697 ::time( <ime );
01698 tm *t;
01699 if ( ts == Qt::LocalTime )
01700 localtime( <ime );
01701 else
01702 gmtime( <ime );
01703 ct->ds = (uint) ( MSECS_PER_HOUR * t->tm_hour + MSECS_PER_MIN * t->tm_min +
01704 1000 * t->tm_sec );
01705 #endif
01706
01707 return ct->ds < (uint) MSECS_PER_MIN;
01708 }
01709
01726 bool QTime::isValid( int h, int m, int s, int ms )
01727 {
01728 return (uint)h < 24 && (uint)m < 60 && (uint)s < 60 && (uint)ms < 1000;
01729 }
01730
01731
01745 void QTime::start()
01746 {
01747 *this = currentTime();
01748 }
01749
01770 int QTime::restart()
01771 {
01772 QTime t = currentTime();
01773 int n = msecsTo( t );
01774 if ( n < 0 )
01775 n += 86400*1000;
01776 *this = t;
01777 return n;
01778 }
01779
01798 int QTime::elapsed() const
01799 {
01800 int n = msecsTo( currentTime() );
01801 if ( n < 0 )
01802 n += 86400*1000;
01803 return n;
01804 }
01805
01806
01807
01808
01809
01810
01871 QDateTime::QDateTime( const QDate &date )
01872 : d(date)
01873 {
01874 }
01875
01880 QDateTime::QDateTime( const QDate &date, const QTime &time )
01881 : d(date), t(time)
01882 {
01883 }
01884
01885
01947 uint QDateTime::toTime_t() const
01948 {
01949 tm brokenDown;
01950 brokenDown.tm_sec = t.second();
01951 brokenDown.tm_min = t.minute();
01952 brokenDown.tm_hour = t.hour();
01953 brokenDown.tm_mday = d.day();
01954 brokenDown.tm_mon = d.month() - 1;
01955 brokenDown.tm_year = d.year() - 1900;
01956 brokenDown.tm_isdst = -1;
01957 int secsSince1Jan1970UTC = (int) mktime( &brokenDown );
01958 if ( secsSince1Jan1970UTC < -1 )
01959 secsSince1Jan1970UTC = -1;
01960 return (uint) secsSince1Jan1970UTC;
01961 }
01962
01970 void QDateTime::setTime_t( uint secsSince1Jan1970UTC )
01971 {
01972 setTime_t( secsSince1Jan1970UTC, Qt::LocalTime );
01973 }
01974
01987 void QDateTime::setTime_t( uint secsSince1Jan1970UTC, Qt::TimeSpec ts )
01988 {
01989 time_t tmp = (time_t) secsSince1Jan1970UTC;
01990 tm *brokenDown = 0;
01991
01992 #if defined(Q_OS_UNIX) && defined(QT_THREAD_SUPPORT) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
01993
01994
01995 tm res;
01996 if ( ts == Qt::LocalTime )
01997 brokenDown = localtime_r( &tmp, &res );
01998 if ( !brokenDown ) {
01999 brokenDown = gmtime_r( &tmp, &res );
02000 if ( !brokenDown ) {
02001 d.jd = QDate::gregorianToJulian( 1970, 1, 1 );
02002 t.ds = 0;
02003 return;
02004 }
02005 }
02006 #else
02007 if ( ts == Qt::LocalTime )
02008 brokenDown = localtime( &tmp );
02009 if ( !brokenDown ) {
02010 brokenDown = gmtime( &tmp );
02011 if ( !brokenDown ) {
02012 d.jd = QDate::gregorianToJulian( 1970, 1, 1 );
02013 t.ds = 0;
02014 return;
02015 }
02016 }
02017 #endif
02018
02019 d.jd = QDate::gregorianToJulian( brokenDown->tm_year + 1900,
02020 brokenDown->tm_mon + 1,
02021 brokenDown->tm_mday );
02022 t.ds = MSECS_PER_HOUR * brokenDown->tm_hour +
02023 MSECS_PER_MIN * brokenDown->tm_min +
02024 1000 * brokenDown->tm_sec;
02025 }
02026 #ifndef QT_NO_DATESTRING
02027 #ifndef QT_NO_SPRINTF
02028
02051 QString QDateTime::toString( Qt::DateFormat f ) const
02052 {
02053 if ( f == Qt::ISODate ) {
02054 return d.toString( Qt::ISODate ) + "T" + t.toString( Qt::ISODate );
02055 }
02056 #ifndef QT_NO_TEXTDATE
02057 else if ( f == Qt::TextDate ) {
02058 #ifndef Q_WS_WIN
02059 QString buf = d.shortDayName( d.dayOfWeek() );
02060 buf += ' ';
02061 buf += d.shortMonthName( d.month() );
02062 buf += ' ';
02063 buf += QString().setNum( d.day() );
02064 buf += ' ';
02065 #else
02066 QString buf;
02067 QString winstr;
02068 QT_WA( {
02069 TCHAR out[255];
02070 GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255 );
02071 winstr = QString::fromUcs2( (ushort*)out );
02072 } , {
02073 char out[255];
02074 GetLocaleInfoA( LOCALE_USER_DEFAULT, LOCALE_ILDATE, (char*)&out, 255 );
02075 winstr = QString::fromLocal8Bit( out );
02076 } );
02077 switch ( winstr.toInt() ) {
02078 case 1:
02079 buf = d.shortDayName( d.dayOfWeek() ) + " " + QString().setNum( d.day() ) + ". " + d.shortMonthName( d.month() ) + " ";
02080 break;
02081 default:
02082 buf = d.shortDayName( d.dayOfWeek() ) + " " + d.shortMonthName( d.month() ) + " " + QString().setNum( d.day() ) + " ";
02083 break;
02084 }
02085 #endif
02086 buf += t.toString();
02087 buf += ' ';
02088 buf += QString().setNum( d.year() );
02089 return buf;
02090 }
02091 #endif
02092 else if ( f == Qt::LocalDate ) {
02093 return d.toString( Qt::LocalDate ) + " " + t.toString( Qt::LocalDate );
02094 }
02095 return QString::null;
02096 }
02097 #endif
02098
02162 QString QDateTime::toString( const QString& format ) const
02163 {
02164 return fmtDateTime( format, &t, &d );
02165 }
02166 #endif //QT_NO_DATESTRING
02167
02176 QDateTime QDateTime::addDays( int ndays ) const
02177 {
02178 return QDateTime( d.addDays(ndays), t );
02179 }
02180
02189 QDateTime QDateTime::addMonths( int nmonths ) const
02190 {
02191 return QDateTime( d.addMonths(nmonths), t );
02192 }
02193
02202 QDateTime QDateTime::addYears( int nyears ) const
02203 {
02204 return QDateTime( d.addYears(nyears), t );
02205 }
02206
02215 QDateTime QDateTime::addSecs( int nsecs ) const
02216 {
02217 uint dd = d.jd;
02218 int tt = t.ds;
02219 int sign = 1;
02220 if ( nsecs < 0 ) {
02221 nsecs = -nsecs;
02222 sign = -1;
02223 }
02224 if ( nsecs >= (int)SECS_PER_DAY ) {
02225 dd += sign*(nsecs/SECS_PER_DAY);
02226 nsecs %= SECS_PER_DAY;
02227 }
02228 tt += sign*nsecs*1000;
02229 if ( tt < 0 ) {
02230 tt = MSECS_PER_DAY - tt - 1;
02231 dd -= tt / MSECS_PER_DAY;
02232 tt = tt % MSECS_PER_DAY;
02233 tt = MSECS_PER_DAY - tt - 1;
02234 } else if ( tt >= (int)MSECS_PER_DAY ) {
02235 dd += ( tt / MSECS_PER_DAY );
02236 tt = tt % MSECS_PER_DAY;
02237 }
02238 QDateTime ret;
02239 ret.t.ds = tt;
02240 ret.d.jd = dd;
02241 return ret;
02242 }
02243
02251 int QDateTime::daysTo( const QDateTime &dt ) const
02252 {
02253 return d.daysTo( dt.d );
02254 }
02255
02270 int QDateTime::secsTo( const QDateTime &dt ) const
02271 {
02272 return t.secsTo(dt.t) + d.daysTo(dt.d)*SECS_PER_DAY;
02273 }
02274
02275
02282 bool QDateTime::operator==( const QDateTime &dt ) const
02283 {
02284 return t == dt.t && d == dt.d;
02285 }
02286
02294 bool QDateTime::operator!=( const QDateTime &dt ) const
02295 {
02296 return t != dt.t || d != dt.d;
02297 }
02298
02304 bool QDateTime::operator<( const QDateTime &dt ) const
02305 {
02306 if ( d < dt.d )
02307 return TRUE;
02308 return d == dt.d ? t < dt.t : FALSE;
02309 }
02310
02316 bool QDateTime::operator<=( const QDateTime &dt ) const
02317 {
02318 if ( d < dt.d )
02319 return TRUE;
02320 return d == dt.d ? t <= dt.t : FALSE;
02321 }
02322
02328 bool QDateTime::operator>( const QDateTime &dt ) const
02329 {
02330 if ( d > dt.d )
02331 return TRUE;
02332 return d == dt.d ? t > dt.t : FALSE;
02333 }
02334
02340 bool QDateTime::operator>=( const QDateTime &dt ) const
02341 {
02342 if ( d > dt.d )
02343 return TRUE;
02344 return d == dt.d ? t >= dt.t : FALSE;
02345 }
02346
02355 QDateTime QDateTime::currentDateTime()
02356 {
02357 return currentDateTime( Qt::LocalTime );
02358 }
02359
02367 QDateTime QDateTime::currentDateTime( Qt::TimeSpec ts )
02368 {
02369 QDateTime dt;
02370 QTime t;
02371 dt.setDate( QDate::currentDate(ts) );
02372 if ( QTime::currentTime(&t, ts) )
02373 dt.setDate( QDate::currentDate(ts) );
02374 dt.setTime( t );
02375 return dt;
02376 }
02377
02378 #ifndef QT_NO_DATESTRING
02379
02389 QDateTime QDateTime::fromString( const QString& s, Qt::DateFormat f )
02390 {
02391 if ( ( s.isEmpty() ) || ( f == Qt::LocalDate ) ) {
02392 #if defined(QT_CHECK_RANGE)
02393 qWarning( "QDateTime::fromString: Parameter out of range" );
02394 #endif
02395 return QDateTime();
02396 }
02397 if ( f == Qt::ISODate ) {
02398 return QDateTime( QDate::fromString( s.mid(0,10), Qt::ISODate ),
02399 QTime::fromString( s.mid(11), Qt::ISODate ) );
02400 }
02401 #if !defined(QT_NO_REGEXP) && !defined(QT_NO_TEXTDATE)
02402 else if ( f == Qt::TextDate ) {
02403 QString monthName( s.mid( 4, 3 ) );
02404 int month = -1;
02405
02406 for ( int i = 0; i < 12; ++i ) {
02407 if ( monthName == qt_shortMonthNames[i] ) {
02408 month = i + 1;
02409 break;
02410 }
02411 }
02412
02413 if ( month == -1 ) {
02414 for ( int i = 1; i <= 12; ++i ) {
02415 if ( monthName == QDate::shortMonthName( i ) ) {
02416 month = i;
02417 break;
02418 }
02419 }
02420 }
02421 #if defined(QT_CHECK_RANGE)
02422 if ( month < 1 || month > 12 ) {
02423 qWarning( "QDateTime::fromString: Parameter out of range." );
02424 month = 1;
02425 }
02426 #endif
02427 int day = s.mid( 8, 2 ).simplifyWhiteSpace().toInt();
02428 int year = s.right( 4 ).toInt();
02429 QDate date( year, month, day );
02430 QTime time;
02431 int hour, minute, second;
02432 int pivot = s.find( QRegExp("[0-9][0-9]:[0-9][0-9]:[0-9][0-9]") );
02433 if ( pivot != -1 ) {
02434 hour = s.mid( pivot, 2 ).toInt();
02435 minute = s.mid( pivot+3, 2 ).toInt();
02436 second = s.mid( pivot+6, 2 ).toInt();
02437 time.setHMS( hour, minute, second );
02438 }
02439 return QDateTime( date, time );
02440 }
02441 #endif //QT_NO_REGEXP
02442 return QDateTime();
02443 }
02444 #endif //QT_NO_DATESTRING
02445
02446
02447
02448
02449
02450
02451 #ifndef QT_NO_DATASTREAM
02452
02460 QDataStream &operator<<( QDataStream &s, const QDate &d )
02461 {
02462 return s << (Q_UINT32)(d.jd);
02463 }
02464
02473 QDataStream &operator>>( QDataStream &s, QDate &d )
02474 {
02475 Q_UINT32 jd;
02476 s >> jd;
02477 d.jd = jd;
02478 return s;
02479 }
02480
02489 QDataStream &operator<<( QDataStream &s, const QTime &t )
02490 {
02491 return s << (Q_UINT32)(t.ds);
02492 }
02493
02502 QDataStream &operator>>( QDataStream &s, QTime &t )
02503 {
02504 Q_UINT32 ds;
02505 s >> ds;
02506 t.ds = ds;
02507 return s;
02508 }
02509
02518 QDataStream &operator<<( QDataStream &s, const QDateTime &dt )
02519 {
02520 return s << dt.d << dt.t;
02521 }
02522
02531 QDataStream &operator>>( QDataStream &s, QDateTime &dt )
02532 {
02533 s >> dt.d >> dt.t;
02534 return s;
02535 }
02536 #endif //QT_NO_DATASTREAM