src/messaging/win32wce/qmailtimestamp.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 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 Qt Mobility Components.
       
     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 "qmailtimestamp.h"
       
    43 
       
    44 #include <QDate>
       
    45 #include <QStringList>
       
    46 #include <QTime>
       
    47 
       
    48 #include <stdlib.h>
       
    49 
       
    50 
       
    51 class QMailTimeStampPrivate : public QSharedData
       
    52 {
       
    53 public:
       
    54     QMailTimeStampPrivate();
       
    55     explicit QMailTimeStampPrivate(const QString& timeText);
       
    56     explicit QMailTimeStampPrivate(const QDateTime& dateTime);
       
    57     QMailTimeStampPrivate(const QMailTimeStampPrivate& other);
       
    58     ~QMailTimeStampPrivate();
       
    59 
       
    60     const QMailTimeStampPrivate& operator= (const QMailTimeStampPrivate& other);
       
    61 
       
    62     QString toString(QMailTimeStamp::OutputFormat format) const;
       
    63 
       
    64     QDateTime toLocalTime() const;
       
    65     QDateTime toUTC() const;
       
    66 
       
    67     bool isNull() const;
       
    68     bool isValid() const;
       
    69 
       
    70     bool operator== (const QMailTimeStampPrivate& other) const;
       
    71     bool operator!= (const QMailTimeStampPrivate& other) const;
       
    72 
       
    73     bool operator< (const QMailTimeStampPrivate& other) const;
       
    74     bool operator<= (const QMailTimeStampPrivate& other) const;
       
    75 
       
    76     bool operator> (const QMailTimeStampPrivate& other) const;
       
    77     bool operator>= (const QMailTimeStampPrivate& other) const;
       
    78 
       
    79 private:
       
    80     // Make these private - since they must be accessed through a smart pointer from the
       
    81     // owner class, it's better if all access is restricted to this class
       
    82     QDateTime time;
       
    83     int utcOffset;
       
    84 };
       
    85 
       
    86 QMailTimeStampPrivate::QMailTimeStampPrivate()
       
    87     : utcOffset(0)
       
    88 {
       
    89 }
       
    90 
       
    91 QMailTimeStampPrivate::QMailTimeStampPrivate(const QString& timeText)
       
    92     : utcOffset(0)
       
    93 {
       
    94     int month = -1, day = -1, year = -1;
       
    95     bool ok;
       
    96     QString timeStr, offsetStr;
       
    97 
       
    98     // Remove any comments from the text
       
    99     QString uncommented;
       
   100     uncommented.reserve( timeText.length() );
       
   101 
       
   102     int commentDepth = 0;
       
   103     bool escaped = false;
       
   104 
       
   105     const QChar* it = timeText.constData();
       
   106     const QChar* end = it + timeText.length();
       
   107     for ( ; it != end; ++it ) {
       
   108         if ( !escaped && ( *it == '\\' ) ) {
       
   109             escaped = true;
       
   110             continue;
       
   111         }
       
   112 
       
   113         if ( *it == '(' && !escaped )
       
   114             commentDepth += 1;
       
   115         else if ( *it == ')' && !escaped && ( commentDepth > 0 ) )
       
   116             commentDepth -= 1;
       
   117         else if ( commentDepth == 0 ) {
       
   118             // Remove characters we don't want
       
   119             if ( *it != ',' && *it != '\n' && *it != '\r' )
       
   120                 uncommented.append( *it );
       
   121         }
       
   122 
       
   123         escaped = false;
       
   124     }
       
   125 
       
   126     // Extract the date/time elements
       
   127     uncommented = uncommented.trimmed();
       
   128     QStringList tokens = uncommented.split(' ', QString::SkipEmptyParts);
       
   129 
       
   130     int tokenCount = tokens.count();
       
   131     if ( tokenCount > 0 ) {
       
   132         static const QString Days("sunmontuewedthufrisat");
       
   133         if (Days.indexOf(tokens[0].left(3).toLower()) != -1) {
       
   134             tokens.removeAt(0);
       
   135             tokenCount -= 1;
       
   136         }
       
   137         if (tokenCount > 0) {
       
   138             int value = tokens[0].toInt(&ok);
       
   139             if ( ok )
       
   140                 day = value;
       
   141         }
       
   142     }
       
   143     if ( tokenCount > 1 ) {
       
   144         static const QString Months("janfebmaraprmayjunjulaugsepoctnovdec");
       
   145         int value = Months.indexOf( tokens[1].left( 3 ).toLower() );
       
   146         if ( value != -1 )
       
   147             month = (value + 3) / 3;
       
   148     }
       
   149     if ( tokenCount > 2 ) {
       
   150         int value = tokens[2].toInt(&ok);
       
   151         if ( ok ) {
       
   152             // Interpret year according to RFC2822
       
   153             year = value;
       
   154             if ( year < 100 ) {
       
   155                 year += ( year <= 49 ? 2000 : 1900 );
       
   156             } 
       
   157             else if ( year < 1000 ) {
       
   158                 year += 1900;
       
   159             }
       
   160         }
       
   161     }
       
   162     if ( tokenCount > 3 ) {
       
   163         timeStr = tokens[3].trimmed();
       
   164     }
       
   165     if ( tokenCount > 4 ) {
       
   166         offsetStr = tokens[4].trimmed();
       
   167     }
       
   168 
       
   169     // Parse the text into UTC-adjusted time part and UTC-offset indicator
       
   170     if ( (day != -1) && (month != -1) && (year != -1) ) {
       
   171         QDate dateComponent(year, month, day);
       
   172         QTime timeComponent;
       
   173 
       
   174         QTime parsedTime;
       
   175         if ( timeStr.length() == 8 ) { 
       
   176             parsedTime = QTime::fromString( timeStr, "hh:mm:ss" );
       
   177         }
       
   178         else if ( timeStr.length() == 5 ) { 
       
   179             // Is this legal?  Either way, it seems desirable for robustness...
       
   180             parsedTime = QTime::fromString( timeStr, "hh:mm" );
       
   181         }
       
   182         if ( parsedTime.isValid() )
       
   183             timeComponent = parsedTime;
       
   184 
       
   185         time = QDateTime( dateComponent, timeComponent, Qt::UTC );
       
   186 
       
   187         if ( offsetStr.length() == 5 ) {
       
   188             int h = offsetStr.left(3).toInt(&ok);
       
   189             if ( ok ) {
       
   190                 int m = offsetStr.right(2).toInt(&ok);
       
   191                 if ( ok ) {
       
   192                     utcOffset = ( h * 3600 ) + ( m * 60 * ( h < 0 ? -1 : 1 ) );
       
   193 
       
   194                     time = time.addSecs( -utcOffset );
       
   195                 }
       
   196             }
       
   197         }
       
   198     }
       
   199 }
       
   200 
       
   201 QMailTimeStampPrivate::QMailTimeStampPrivate(const QDateTime& dateTime)
       
   202 {
       
   203     // Store the time as UTC
       
   204     if ( dateTime.timeSpec() == Qt::LocalTime ) {
       
   205         QDateTime original(dateTime);
       
   206         original.setTimeSpec( Qt::UTC );
       
   207 
       
   208         time = dateTime.toUTC();
       
   209 
       
   210         // Find the difference
       
   211         utcOffset = time.secsTo( original );
       
   212     }
       
   213     else {
       
   214         // Time is already in UTC
       
   215         time = dateTime;
       
   216 
       
   217         // Is this the right thing to do? What does it mean if we get a UTC timestamp?
       
   218         utcOffset = 0;
       
   219     }
       
   220 
       
   221     // Since we can't include milliseconds in our textual representation, and we
       
   222     // need to ensure the following works:
       
   223     //    assert( someTimeStamp == QMailTimeStamp(someTimeStamp.toString()) )
       
   224     // then we need to make sure that we have no sub-second component
       
   225     qint64 ms = time.time().msec();
       
   226     if (ms != 0)
       
   227         time = time.addMSecs(0 - ms);
       
   228 }
       
   229 
       
   230 QMailTimeStampPrivate::QMailTimeStampPrivate(const QMailTimeStampPrivate& other)
       
   231     : QSharedData(other) 
       
   232 {
       
   233     this->operator=(other);
       
   234 }
       
   235 
       
   236 QMailTimeStampPrivate::~QMailTimeStampPrivate()
       
   237 {
       
   238 }
       
   239 
       
   240 const QMailTimeStampPrivate& QMailTimeStampPrivate::operator= (const QMailTimeStampPrivate& other)
       
   241 {
       
   242     time = other.time;
       
   243     utcOffset = other.utcOffset;
       
   244     return *this;
       
   245 }
       
   246 
       
   247 QString QMailTimeStampPrivate::toString(QMailTimeStamp::OutputFormat format) const
       
   248 {
       
   249     // We can't use QDateTime to provide day and month names, since they may get localized into UTF-8
       
   250     static const char Days[] = "MonTueWedThuFriSatSun";
       
   251     static const char Months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
       
   252 
       
   253     if (time.isNull() || !time.isValid())
       
   254         return QString();
       
   255 
       
   256     QString result;
       
   257 
       
   258     QDateTime originalTime = time.addSecs( utcOffset );
       
   259     QDate originalDate = originalTime.date();
       
   260 
       
   261     int hOffset = utcOffset / 3600;
       
   262     int mOffset = ( abs(utcOffset) - abs(hOffset * 3600) ) / 60;
       
   263 
       
   264     if (format == QMailTimeStamp::Rfc2822) {
       
   265         result = QString( originalTime.toString( "%1, d %2 yyyy hh:mm:ss %3" ) );
       
   266         result = result.arg( QString::fromAscii( Days + ( originalDate.dayOfWeek() - 1 ) * 3, 3 ) );
       
   267         result = result.arg( QString::fromAscii( Months + ( originalDate.month() - 1 ) * 3, 3 ) );
       
   268         result = result.arg( QString().sprintf( "%+.2d%.2d", hOffset, mOffset ) );
       
   269     } else if (format == QMailTimeStamp::Rfc3501) {
       
   270         result = QString( originalTime.toString( "dd-%1-yyyy hh:mm:ss %2" ) );
       
   271         result = result.arg( QString::fromAscii( Months + ( originalDate.month() - 1 ) * 3, 3 ) );
       
   272         result = result.arg( QString().sprintf( "%+.2d%.2d", hOffset, mOffset ) );
       
   273 
       
   274         // The day number should be space-padded
       
   275         if (result[0] == '0') {
       
   276             result[0] = ' ';
       
   277         }
       
   278     } else if (format == QMailTimeStamp::Rfc3339) {
       
   279         result = QString( originalTime.toString( "yyyy-MM-ddThh:mm:ss%1" ) );
       
   280         result = result.arg( utcOffset == 0 ? QString("Z") : QString().sprintf( "%+.2d:%.2d", hOffset, mOffset ) );
       
   281     }
       
   282 
       
   283     return result;
       
   284 }
       
   285 
       
   286 QDateTime QMailTimeStampPrivate::toLocalTime() const
       
   287 {
       
   288     return time.toLocalTime();
       
   289 }
       
   290 
       
   291 QDateTime QMailTimeStampPrivate::toUTC() const
       
   292 {
       
   293     return time;
       
   294 }
       
   295 
       
   296 bool QMailTimeStampPrivate::isNull() const
       
   297 {
       
   298     return time.isNull();
       
   299 }
       
   300 
       
   301 bool QMailTimeStampPrivate::isValid() const
       
   302 {
       
   303     return time.isValid();
       
   304 }
       
   305 
       
   306 bool QMailTimeStampPrivate::operator== (const QMailTimeStampPrivate& other) const
       
   307 {
       
   308     return ( toUTC() == other.toUTC() );
       
   309 }
       
   310 
       
   311 bool QMailTimeStampPrivate::operator!= (const QMailTimeStampPrivate& other) const
       
   312 {
       
   313     return !operator==(other);
       
   314 }
       
   315 
       
   316 bool QMailTimeStampPrivate::operator< (const QMailTimeStampPrivate& other) const
       
   317 {
       
   318     return ( toUTC() < other.toUTC() );
       
   319 }
       
   320 
       
   321 bool QMailTimeStampPrivate::operator<= (const QMailTimeStampPrivate& other) const
       
   322 {
       
   323     return !operator>(other);
       
   324 }
       
   325 
       
   326 bool QMailTimeStampPrivate::operator> (const QMailTimeStampPrivate& other) const
       
   327 {
       
   328     return ( toUTC() > other.toUTC() );
       
   329 }
       
   330 
       
   331 bool QMailTimeStampPrivate::operator>= (const QMailTimeStampPrivate& other) const
       
   332 {
       
   333     return !operator<(other);
       
   334 }
       
   335 
       
   336 
       
   337 /*!
       
   338     \class QMailTimeStamp
       
   339 
       
   340     \brief The QMailTimeStamp class manages message time stamps.
       
   341     \ingroup messaginglibrary
       
   342 
       
   343     QMailTimeStamp provides functions for creating and manipulating the time stamps of messages.
       
   344     QMailTimeStamp can be created from time stamp strings, or from QDateTime objects.  The 
       
   345     time stamp information can be extracted in UTC time, local time, or as a formatted 
       
   346     string.
       
   347 
       
   348     QMailTimeStamp maintains the timezone information of a time stamp, so it can be used to
       
   349     convert time stamp information between UTC time and localized time values.
       
   350 
       
   351     \sa QDateTime, QMailMessage
       
   352 */
       
   353 
       
   354 /*!
       
   355     \enum QMailTimeStamp::OutputFormat
       
   356     
       
   357     This enum type is used to select a format for timestamp output.
       
   358 
       
   359     \value Rfc2822  The format used in SMTP message format; example: "Wed, 17 May 2006 20:45:00 +0100".
       
   360     \value Rfc3501  The format used in IMAP message append; example: "17-May-2006 20:45:00 +0100".
       
   361     \value Rfc3339  The format specified for future protocols (a variant of ISO 8601); example: "2006-05-17T20:45:00+01:00".
       
   362 */
       
   363 
       
   364 /*!
       
   365     Returns a QMailTimeStamp object initialised to contain the current
       
   366     date and time, in the local time zone.
       
   367 */
       
   368 QMailTimeStamp QMailTimeStamp::currentDateTime()
       
   369 {
       
   370     return QMailTimeStamp(QDateTime::currentDateTime());
       
   371 }
       
   372 
       
   373 /*!
       
   374     Constructs a null QMailTimeStamp object. A null timestamp is invalid.
       
   375 */
       
   376 QMailTimeStamp::QMailTimeStamp()
       
   377 {
       
   378     d = new QMailTimeStampPrivate();
       
   379 }
       
   380 
       
   381 /*! \internal */
       
   382 QMailTimeStamp::QMailTimeStamp(const QMailTimeStamp& other)
       
   383 {
       
   384     this->operator=(other);
       
   385 }
       
   386 
       
   387 /*!
       
   388     Constructs a QMailTimeStamp object by parsing \a timeText.
       
   389 */
       
   390 QMailTimeStamp::QMailTimeStamp(const QString& timeText)
       
   391 {
       
   392     d = new QMailTimeStampPrivate(timeText);
       
   393 }
       
   394 
       
   395 /*!
       
   396     Constructs a QMailTimeStamp object from the given \a dateTime.
       
   397 */
       
   398 QMailTimeStamp::QMailTimeStamp(const QDateTime& dateTime)
       
   399 {
       
   400     d = new QMailTimeStampPrivate(dateTime);
       
   401 }
       
   402 
       
   403 /*!
       
   404     Destroys a QMailTimeStamp object.
       
   405 */
       
   406 QMailTimeStamp::~QMailTimeStamp()
       
   407 {
       
   408 }
       
   409 
       
   410 /*! \internal */
       
   411 const QMailTimeStamp& QMailTimeStamp::operator= (const QMailTimeStamp& other)
       
   412 {
       
   413     d = other.d;
       
   414     return *this;
       
   415 }
       
   416 
       
   417 /*!
       
   418     Returns the time stamp information in the format specified by \a format.
       
   419 */
       
   420 QString QMailTimeStamp::toString(QMailTimeStamp::OutputFormat format) const
       
   421 {
       
   422     return d->toString(format);
       
   423 }
       
   424 
       
   425 /*!
       
   426     Returns a QDateTime containing the time stamp converted to the local time zone.
       
   427 */
       
   428 QDateTime QMailTimeStamp::toLocalTime() const
       
   429 {
       
   430     return d->toLocalTime();
       
   431 }
       
   432 
       
   433 /*!
       
   434     Returns a QDateTime containing the time stamp in UTC time.
       
   435 */
       
   436 QDateTime QMailTimeStamp::toUTC() const
       
   437 {
       
   438     return d->toUTC();
       
   439 }
       
   440 
       
   441 /*!
       
   442     Returns true if the timestamp has not been initialized to contain a value.
       
   443 */
       
   444 bool QMailTimeStamp::isNull() const
       
   445 {
       
   446     return d->isNull();
       
   447 }
       
   448 
       
   449 /*!
       
   450     Returns true if the timestamp is valid; otherwise returns false;
       
   451 */
       
   452 bool QMailTimeStamp::isValid() const
       
   453 {
       
   454     return d->isValid();
       
   455 }
       
   456 
       
   457 /*!
       
   458     Returns true if this time stamp is equal to \a other; otherwise returns false.
       
   459 
       
   460     \sa operator!=()
       
   461 */
       
   462 bool QMailTimeStamp::operator== (const QMailTimeStamp& other) const
       
   463 {
       
   464     return d->operator==(*other.d);
       
   465 }
       
   466 
       
   467 /*!
       
   468     Returns true if this time stamp is different from \a other; otherwise returns false.
       
   469 
       
   470     Two time stamps are different if either the date, the time, or the time zone components are different.
       
   471 
       
   472     \sa operator==()
       
   473 */
       
   474 bool QMailTimeStamp::operator!= (const QMailTimeStamp& other) const
       
   475 {
       
   476     return d->operator!=(*other.d);
       
   477 }
       
   478 
       
   479 /*!
       
   480     Returns true if this time stamp is earlier than \a other; otherwise returns false.
       
   481 */
       
   482 bool QMailTimeStamp::operator< (const QMailTimeStamp& other) const
       
   483 {
       
   484     return d->operator<(*other.d);
       
   485 }
       
   486 
       
   487 /*!
       
   488     Returns true if this time stamp is earlier than or equal to \a other; otherwise returns false.
       
   489 */
       
   490 bool QMailTimeStamp::operator<= (const QMailTimeStamp& other) const
       
   491 {
       
   492     return d->operator<=(*other.d);
       
   493 }
       
   494 
       
   495 /*!
       
   496     Returns true if this time stamp is later than \a other; otherwise returns false.
       
   497 */
       
   498 bool QMailTimeStamp::operator> (const QMailTimeStamp& other) const
       
   499 {
       
   500     return d->operator>(*other.d);
       
   501 }
       
   502 
       
   503 /*!
       
   504     Returns true if this time stamp is later than or equal to \a other; otherwise returns false.
       
   505 */
       
   506 bool QMailTimeStamp::operator>= (const QMailTimeStamp& other) const
       
   507 {
       
   508     return d->operator>=(*other.d);
       
   509 }
       
   510