src/script/utils/qscriptdate.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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 QtScript 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 "qscriptdate_p.h"
       
    43 
       
    44 #include <QtCore/qnumeric.h>
       
    45 #include <QtCore/qstringlist.h>
       
    46 
       
    47 #include <math.h>
       
    48 
       
    49 #ifndef Q_WS_WIN
       
    50 #   include <time.h>
       
    51 #   include <sys/time.h>
       
    52 #else
       
    53 #   include <windows.h>
       
    54 #endif
       
    55 
       
    56 QT_BEGIN_NAMESPACE
       
    57 
       
    58 namespace QScript {
       
    59 
       
    60 qsreal ToInteger(qsreal n);
       
    61 
       
    62 static const qsreal HoursPerDay = 24.0;
       
    63 static const qsreal MinutesPerHour = 60.0;
       
    64 static const qsreal SecondsPerMinute = 60.0;
       
    65 static const qsreal msPerSecond = 1000.0;
       
    66 static const qsreal msPerMinute = 60000.0;
       
    67 static const qsreal msPerHour = 3600000.0;
       
    68 static const qsreal msPerDay = 86400000.0;
       
    69 
       
    70 static qsreal LocalTZA = 0.0; // initialized at startup
       
    71 
       
    72 static inline qsreal TimeWithinDay(qsreal t)
       
    73 {
       
    74     qsreal r = ::fmod(t, msPerDay);
       
    75     return (r >= 0) ? r : r + msPerDay;
       
    76 }
       
    77 
       
    78 static inline int HourFromTime(qsreal t)
       
    79 {
       
    80     int r = int(::fmod(::floor(t / msPerHour), HoursPerDay));
       
    81     return (r >= 0) ? r : r + int(HoursPerDay);
       
    82 }
       
    83 
       
    84 static inline int MinFromTime(qsreal t)
       
    85 {
       
    86     int r = int(::fmod(::floor(t / msPerMinute), MinutesPerHour));
       
    87     return (r >= 0) ? r : r + int(MinutesPerHour);
       
    88 }
       
    89 
       
    90 static inline int SecFromTime(qsreal t)
       
    91 {
       
    92     int r = int(::fmod(::floor(t / msPerSecond), SecondsPerMinute));
       
    93     return (r >= 0) ? r : r + int(SecondsPerMinute);
       
    94 }
       
    95 
       
    96 static inline int msFromTime(qsreal t)
       
    97 {
       
    98     int r = int(::fmod(t, msPerSecond));
       
    99     return (r >= 0) ? r : r + int(msPerSecond);
       
   100 }
       
   101 
       
   102 static inline qsreal Day(qsreal t)
       
   103 {
       
   104     return ::floor(t / msPerDay);
       
   105 }
       
   106 
       
   107 static inline qsreal DaysInYear(qsreal y)
       
   108 {
       
   109     if (::fmod(y, 4))
       
   110         return 365;
       
   111 
       
   112     else if (::fmod(y, 100))
       
   113         return 366;
       
   114 
       
   115     else if (::fmod(y, 400))
       
   116         return 365;
       
   117 
       
   118     return 366;
       
   119 }
       
   120 
       
   121 static inline qsreal DayFromYear(qsreal y)
       
   122 {
       
   123     return 365 * (y - 1970)
       
   124         + ::floor((y - 1969) / 4)
       
   125         - ::floor((y - 1901) / 100)
       
   126         + ::floor((y - 1601) / 400);
       
   127 }
       
   128 
       
   129 static inline qsreal TimeFromYear(qsreal y)
       
   130 {
       
   131     return msPerDay * DayFromYear(y);
       
   132 }
       
   133 
       
   134 static inline qsreal YearFromTime(qsreal t)
       
   135 {
       
   136     int y = 1970;
       
   137     y += (int) ::floor(t / (msPerDay * 365.2425));
       
   138 
       
   139     qsreal t2 = TimeFromYear(y);
       
   140     return (t2 > t) ? y - 1 : ((t2 + msPerDay * DaysInYear(y)) <= t) ? y + 1 : y;
       
   141 }
       
   142 
       
   143 static inline bool InLeapYear(qsreal t)
       
   144 {
       
   145     qsreal x = DaysInYear(YearFromTime(t));
       
   146     if (x == 365)
       
   147         return 0;
       
   148 
       
   149     Q_ASSERT (x == 366);
       
   150     return 1;
       
   151 }
       
   152 
       
   153 static inline qsreal DayWithinYear(qsreal t)
       
   154 {
       
   155     return Day(t) - DayFromYear(YearFromTime(t));
       
   156 }
       
   157 
       
   158 static inline qsreal MonthFromTime(qsreal t)
       
   159 {
       
   160     qsreal d = DayWithinYear(t);
       
   161     qsreal l = InLeapYear(t);
       
   162 
       
   163     if (d < 31.0)
       
   164         return 0;
       
   165 
       
   166     else if (d < 59.0 + l)
       
   167         return 1;
       
   168 
       
   169     else if (d < 90.0 + l)
       
   170         return 2;
       
   171 
       
   172     else if (d < 120.0 + l)
       
   173         return 3;
       
   174 
       
   175     else if (d < 151.0 + l)
       
   176         return 4;
       
   177 
       
   178     else if (d < 181.0 + l)
       
   179         return 5;
       
   180 
       
   181     else if (d < 212.0 + l)
       
   182         return 6;
       
   183 
       
   184     else if (d < 243.0 + l)
       
   185         return 7;
       
   186 
       
   187     else if (d < 273.0 + l)
       
   188         return 8;
       
   189 
       
   190     else if (d < 304.0 + l)
       
   191         return 9;
       
   192 
       
   193     else if (d < 334.0 + l)
       
   194         return 10;
       
   195 
       
   196     else if (d < 365.0 + l)
       
   197         return 11;
       
   198 
       
   199     return qSNaN(); // ### assert?
       
   200 }
       
   201 
       
   202 static inline qsreal DateFromTime(qsreal t)
       
   203 {
       
   204     int m = (int) ToInteger(MonthFromTime(t));
       
   205     qsreal d = DayWithinYear(t);
       
   206     qsreal l = InLeapYear(t);
       
   207 
       
   208     switch (m) {
       
   209     case 0: return d + 1.0;
       
   210     case 1: return d - 30.0;
       
   211     case 2: return d - 58.0 - l;
       
   212     case 3: return d - 89.0 - l;
       
   213     case 4: return d - 119.0 - l;
       
   214     case 5: return d - 150.0 - l;
       
   215     case 6: return d - 180.0 - l;
       
   216     case 7: return d - 211.0 - l;
       
   217     case 8: return d - 242.0 - l;
       
   218     case 9: return d - 272.0 - l;
       
   219     case 10: return d - 303.0 - l;
       
   220     case 11: return d - 333.0 - l;
       
   221     }
       
   222 
       
   223     return qSNaN(); // ### assert
       
   224 }
       
   225 
       
   226 static inline qsreal WeekDay(qsreal t)
       
   227 {
       
   228     qsreal r = ::fmod (Day(t) + 4.0, 7.0);
       
   229     return (r >= 0) ? r : r + 7.0;
       
   230 }
       
   231 
       
   232 
       
   233 static inline qsreal MakeTime(qsreal hour, qsreal min, qsreal sec, qsreal ms)
       
   234 {
       
   235     return ((hour * MinutesPerHour + min) * SecondsPerMinute + sec) * msPerSecond + ms;
       
   236 }
       
   237 
       
   238 static inline qsreal DayFromMonth(qsreal month, qsreal leap)
       
   239 {
       
   240     switch ((int) month) {
       
   241     case 0: return 0;
       
   242     case 1: return 31.0;
       
   243     case 2: return 59.0 + leap;
       
   244     case 3: return 90.0 + leap;
       
   245     case 4: return 120.0 + leap;
       
   246     case 5: return 151.0 + leap;
       
   247     case 6: return 181.0 + leap;
       
   248     case 7: return 212.0 + leap;
       
   249     case 8: return 243.0 + leap;
       
   250     case 9: return 273.0 + leap;
       
   251     case 10: return 304.0 + leap;
       
   252     case 11: return 334.0 + leap;
       
   253     }
       
   254 
       
   255     return qSNaN(); // ### assert?
       
   256 }
       
   257 
       
   258 static qsreal MakeDay(qsreal year, qsreal month, qsreal day)
       
   259 {
       
   260     year += ::floor(month / 12.0);
       
   261 
       
   262     month = ::fmod(month, 12.0);
       
   263     if (month < 0)
       
   264         month += 12.0;
       
   265 
       
   266     qsreal t = TimeFromYear(year);
       
   267     qsreal leap = InLeapYear(t);
       
   268 
       
   269     day += ::floor(t / msPerDay);
       
   270     day += DayFromMonth(month, leap);
       
   271 
       
   272     return day - 1;
       
   273 }
       
   274 
       
   275 static inline qsreal MakeDate(qsreal day, qsreal time)
       
   276 {
       
   277     return day * msPerDay + time;
       
   278 }
       
   279 
       
   280 static inline qsreal DaylightSavingTA(double t)
       
   281 {
       
   282 #ifndef Q_WS_WIN
       
   283     long int tt = (long int)(t / msPerSecond);
       
   284     struct tm *tmtm = localtime((const time_t*)&tt);
       
   285     if (! tmtm)
       
   286         return 0;
       
   287     return (tmtm->tm_isdst > 0) ? msPerHour : 0;
       
   288 #else
       
   289     Q_UNUSED(t);
       
   290     /// ### implement me
       
   291     return 0;
       
   292 #endif
       
   293 }
       
   294 
       
   295 static inline qsreal LocalTime(qsreal t)
       
   296 {
       
   297     return t + LocalTZA + DaylightSavingTA(t);
       
   298 }
       
   299 
       
   300 static inline qsreal UTC(qsreal t)
       
   301 {
       
   302     return t - LocalTZA - DaylightSavingTA(t - LocalTZA);
       
   303 }
       
   304 
       
   305 static inline qsreal TimeClip(qsreal t)
       
   306 {
       
   307     if (! qIsFinite(t) || fabs(t) > 8.64e15)
       
   308         return qSNaN();
       
   309     return ToInteger(t);
       
   310 }
       
   311 
       
   312 static qsreal getLocalTZA()
       
   313 {
       
   314 #ifndef Q_WS_WIN
       
   315     struct tm* t;
       
   316     time_t curr;
       
   317     time(&curr);
       
   318     t = localtime(&curr);
       
   319     time_t locl = mktime(t);
       
   320     t = gmtime(&curr);
       
   321     time_t globl = mktime(t);
       
   322     return double(locl - globl) * 1000.0;
       
   323 #else
       
   324     TIME_ZONE_INFORMATION tzInfo;
       
   325     GetTimeZoneInformation(&tzInfo);
       
   326     return -tzInfo.Bias * 60.0 * 1000.0;
       
   327 #endif
       
   328 }
       
   329 
       
   330 /*!
       
   331   \internal
       
   332 
       
   333   Converts the QDateTime \a dt to an ECMA Date value (in UTC form).
       
   334 */
       
   335 qsreal FromDateTime(const QDateTime &dt)
       
   336 {
       
   337     if (!dt.isValid())
       
   338         return qSNaN();
       
   339     if (!LocalTZA) // ### move
       
   340         LocalTZA = getLocalTZA();
       
   341     QDate date = dt.date();
       
   342     QTime taim = dt.time();
       
   343     int year = date.year();
       
   344     int month = date.month() - 1;
       
   345     int day = date.day();
       
   346     int hours = taim.hour();
       
   347     int mins = taim.minute();
       
   348     int secs = taim.second();
       
   349     int ms = taim.msec();
       
   350     double t = MakeDate(MakeDay(year, month, day),
       
   351                         MakeTime(hours, mins, secs, ms));
       
   352     if (dt.timeSpec() == Qt::LocalTime)
       
   353         t = UTC(t);
       
   354     return TimeClip(t);
       
   355 }
       
   356 
       
   357 /*!
       
   358   \internal
       
   359 
       
   360   Converts the ECMA Date value \tt (in UTC form) to QDateTime
       
   361   according to \a spec.
       
   362 */
       
   363 QDateTime ToDateTime(qsreal t, Qt::TimeSpec spec)
       
   364 {
       
   365     if (qIsNaN(t))
       
   366         return QDateTime();
       
   367     if (!LocalTZA) // ### move
       
   368         LocalTZA = getLocalTZA();
       
   369     if (spec == Qt::LocalTime)
       
   370         t = LocalTime(t);
       
   371     int year = int(YearFromTime(t));
       
   372     int month = int(MonthFromTime(t) + 1);
       
   373     int day = int(DateFromTime(t));
       
   374     int hours = HourFromTime(t);
       
   375     int mins = MinFromTime(t);
       
   376     int secs = SecFromTime(t);
       
   377     int ms = msFromTime(t);
       
   378     return QDateTime(QDate(year, month, day), QTime(hours, mins, secs, ms), spec);
       
   379 }
       
   380 
       
   381 } // namespace QScript
       
   382 
       
   383 QT_END_NAMESPACE