Changeset 16780 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Oct 4, 2006, 11:36:29 AM (19 years ago)
Author:
kmccullo
Message:

Reviewed by GGaren

  • This is a big makeover for our Date implemenetation. This solves many platform specific issues, specifically dates before 1970, and simplifies some ugly code. The purpose of this was to get us to pass many of the JavaScriptCore tests on windows.
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • kjs/DateMath.cpp: Added. (KJS::): (KJS::daysInYear): (KJS::daysFrom1970ToYear): (KJS::msFrom1970ToYear): (KJS::msToDays): (KJS::msToYear): (KJS::isLeapYear): (KJS::isInLeapYear): (KJS::dayInYear): (KJS::msToMilliseconds): (KJS::msToWeekDay): (KJS::msToSeconds): (KJS::msToMinutes): (KJS::msToHours): (KJS::msToMonth): (KJS::msToDayInMonth): (KJS::monthToDayInYear): (KJS::timeToMseconds): (KJS::dateToDayInYear): (KJS::equivalentYearForDST): (KJS::getUTCOffset): (KJS::getDSTOffsetSimple): (KJS::getDSTOffset): (KJS::localTimeToUTC): (KJS::UTCToLocalTime): (KJS::dateToMseconds): (KJS::msToTM): (KJS::isDST):
  • kjs/DateMath.h: Added. (KJS::):
  • kjs/date_object.cpp: (KJS::gmtoffset): (KJS::formatTime): (KJS::DateInstance::getTime): (KJS::DateInstance::getUTCTime): (KJS::DateProtoFunc::callAsFunction): (KJS::DateObjectImp::construct): (KJS::DateObjectFuncImp::callAsFunction): (KJS::parseDate):
  • kjs/testkjs.cpp:
  • os-win32/stdint.h:
Location:
trunk/JavaScriptCore/kjs
Files:
2 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/date_object.cpp

    r16164 r16780  
    5252#include "error_object.h"
    5353#include "operations.h"
     54#include <DateMath.h>
    5455
    5556#include <wtf/MathExtras.h>
     
    5758
    5859#if PLATFORM(MAC)
    59 #include <CoreFoundation/CoreFoundation.h>
    60 #endif
     60    #include <CoreFoundation/CoreFoundation.h>
     61#endif
     62
     63namespace KJS {
     64
     65static double parseDate(const UString&);
     66static double timeClip(double);
    6167
    6268inline int gmtoffset(const tm& t)
     
    6470#if PLATFORM(WIN_OS)
    6571    // Time is supposed to be in the current timezone.
    66     // FIXME: Use undocumented _dstbias?
    67     return -(_timezone / 60 - (t.tm_isdst > 0 ? 60 : 0 )) * 60;
     72    return static_cast<int>(getUTCOffset()/1000.0);
    6873#else
    6974    return t.tm_gmtoff;
     
    7176}
    7277
    73 namespace KJS {
    7478
    7579/**
     
    9094    int id;
    9195};
    92 
    93 // some constants
    94 const double hoursPerDay = 24;
    95 const double minutesPerHour = 60;
    96 const double secondsPerMinute = 60;
    97 const double msPerSecond = 1000;
    98 const double msPerMinute = 60 * 1000;
    99 const double msPerHour = 60 * 60 * 1000;
    100 const double msPerDay = 24 * 60 * 60 * 1000;
    101 
    102 static const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
    103 static const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
    104 
    105 static double makeTime(tm *, double ms, bool utc);
    106 static double parseDate(const UString &);
    107 static double timeClip(double);
    108 static void millisecondsToTM(double milli, bool utc, tm *t);
    10996
    11097#if PLATFORM(MAC)
     
    197184    char buffer[100];
    198185    if (utc) {
    199         // FIXME: why not on windows?
    200 #if !PLATFORM(WIN_OS)
     186#if !PLATFORM(WIN_OS)   //win doesn't have the tm_gtoff member
    201187        ASSERT(t.tm_gmtoff == 0);
    202188#endif
     
    221207    }
    222208    return UString(buffer);
    223 }
    224 
    225 static int day(double t)
    226 {
    227     return int(floor(t / msPerDay));
    228 }
    229 
    230 static double dayFromYear(int year)
    231 {
    232     return 365.0 * (year - 1970)
    233         + floor((year - 1969) / 4.0)
    234         - floor((year - 1901) / 100.0)
    235         + floor((year - 1601) / 400.0);
    236 }
    237 
    238 // based on the rule for whether it's a leap year or not
    239 static int daysInYear(int year)
    240 {
    241     if (year % 4 != 0)
    242         return 365;
    243     if (year % 400 == 0)
    244         return 366;
    245     if (year % 100 == 0)
    246         return 365;
    247     return 366;
    248 }
    249 
    250 // time value of the start of a year
    251 static double timeFromYear(int year)
    252 {
    253     return msPerDay * dayFromYear(year);
    254 }
    255 
    256 // year determined by time value
    257 static int yearFromTime(double t)
    258 {
    259     // ### there must be an easier way
    260 
    261     // initial guess
    262     int y = 1970 + int(t / (365.25 * msPerDay));
    263 
    264     // adjustment
    265     if (timeFromYear(y) > t) {
    266         do
    267             --y;
    268         while (timeFromYear(y) > t);
    269     } else {
    270         while (timeFromYear(y + 1) < t)
    271             ++y;
    272     }
    273 
    274     return y;
    275 }
    276 
    277 // 0: Sunday, 1: Monday, etc.
    278 static int weekDay(double t)
    279 {
    280     int wd = (day(t) + 4) % 7;
    281     if (wd < 0)
    282         wd += 7;
    283     return wd;
    284209}
    285210
     
    369294        return false;
    370295   
    371     millisecondsToTM(milli, false, &t);
     296    msToTM(milli, false, t);
    372297    offset = gmtoffset(t);
    373298    return true;
     
    380305        return false;
    381306   
    382     millisecondsToTM(milli, true, &t);
     307    msToTM(milli, true, t);
    383308    return true;
    384309}
     
    391316   
    392317    tm t;
    393     millisecondsToTM(milli, false, &t);
     318    msToTM(milli, false, t);
    394319    offset = gmtoffset(t);
    395320    return true;
     
    410335    return minusOne < 0;
    411336}
    412 
    413 static void millisecondsToTM(double milli, bool utc, tm *t)
    414 {
    415   // check whether time value is outside time_t's usual range
    416   // make the necessary transformations if necessary
    417   static bool time_tIsSigned = isTime_tSigned();
    418   static double time_tMin = (time_tIsSigned ? - (double)(1ULL << (8 * sizeof(time_t) - 1)) : 0);
    419   static double time_tMax = (time_tIsSigned ? (1ULL << 8 * sizeof(time_t) - 1) - 1 : 2 * (double)(1ULL << 8 * sizeof(time_t) - 1) - 1);
    420   int realYearOffset = 0;
    421   double milliOffset = 0.0;
    422   double secs = floor(milli / msPerSecond);
    423 
    424   if (secs < time_tMin || secs > time_tMax) {
    425     // ### ugly and probably not very precise
    426     int realYear = yearFromTime(milli);
    427     int base = daysInYear(realYear) == 365 ? 2001 : 2000;
    428     milliOffset = timeFromYear(base) - timeFromYear(realYear);
    429     milli += milliOffset;
    430     realYearOffset = realYear - base;
    431   }
    432 
    433   time_t tv = (time_t) floor(milli / msPerSecond);
    434 
    435   *t = *(utc ? gmtime(&tv) : localtime(&tv));
    436   // We had an out of range year. Restore the year (plus/minus offset
    437   // found by calculating tm_year) and fix the week day calculation.
    438   if (realYearOffset != 0) {
    439     t->tm_year += realYearOffset;
    440     milli -= milliOffset;
    441     // Do our own weekday calculation. Use time zone offset to handle local time.
    442     double m = milli;
    443     if (!utc)
    444       m += gmtoffset(*t) * msPerSecond;
    445     t->tm_wday = weekDay(m);
    446   }
    447 }   
    448 
    449337
    450338// ------------------------------ DatePrototype -----------------------------
     
    576464
    577465  tm t;
    578   millisecondsToTM(milli, utc, &t);
     466  msToTM(milli, utc, t);
    579467
    580468  switch (id) {
     
    675563      id == SetMinutes || id == SetHours || id == SetDate ||
    676564      id == SetMonth || id == SetFullYear ) {
    677     result = jsNumber(makeTime(&t, ms, utc));
     565    result = jsNumber(dateToMseconds(&t, ms, utc));
    678566    thisDateObj->setInternalValue(result);
    679567  }
     
    762650      t.tm_isdst = -1;
    763651      double ms = (numArgs >= 7) ? roundValue(exec, args[6]) : 0;
    764       value = makeTime(&t, ms, false);
     652      value = dateToMseconds(&t, ms, false);
    765653    }
    766654  }
     
    815703    t.tm_sec = (n >= 6) ? args[5]->toInt32(exec) : 0;
    816704    double ms = (n >= 7) ? roundValue(exec, args[6]) : 0;
    817     return jsNumber(makeTime(&t, ms, true));
     705    return jsNumber(dateToMseconds(&t, ms, true));
    818706  }
    819707}
     
    853741    { "PDT", -420 }
    854742};
    855 
    856 static double makeTime(tm *t, double ms, bool utc)
    857 {
    858     int utcOffset;
    859     if (utc) {
    860         time_t zero = 0;
    861 #if PLATFORM(WIN_OS)
    862         // FIXME: not thread safe
    863         (void)localtime(&zero);
    864 #if COMPILER(BORLAND) || COMPILER(CYGWIN)
    865         utcOffset = - _timezone;
    866 #else
    867         utcOffset = - timezone;
    868 #endif
    869         t->tm_isdst = 0;
    870 #else
    871         tm t3;
    872         localtime_r(&zero, &t3);
    873         utcOffset = t3.tm_gmtoff;
    874         t->tm_isdst = t3.tm_isdst;
    875 #endif
    876     } else {
    877         utcOffset = 0;
    878         t->tm_isdst = -1;
    879     }
    880 
    881     double yearOffset = 0.0;
    882     if (t->tm_year < (1970 - 1900) || t->tm_year > (2038 - 1900)) {
    883         // we'll fool mktime() into believing that this year is within
    884         // its normal, portable range (1970-2038) by setting tm_year to
    885         // 2000 or 2001 and adding the difference in milliseconds later.
    886         // choice between offset will depend on whether the year is a
    887         // leap year or not.
    888         int y = t->tm_year + 1900;
    889         int baseYear = daysInYear(y) == 365 ? 2001 : 2000;
    890         double baseTime = timeFromYear(baseYear);
    891         yearOffset = timeFromYear(y) - baseTime;
    892         t->tm_year = baseYear - 1900;
    893     }
    894 
    895     // Determine whether DST is in effect. mktime() can't do this for us because
    896     // it doesn't know about ms and yearOffset.
    897     // NOTE: Casting values of large magnitude to time_t (long) will
    898     // produce incorrect results, but there's no other option when calling localtime_r().
    899     if (!utc) {
    900         time_t tval = mktime(t) + (time_t)((ms + yearOffset) / 1000); 
    901         tm t3 = *localtime(&tval); 
    902         t->tm_isdst = t3.tm_isdst; 
    903     }
    904 
    905     return (mktime(t) + utcOffset) * msPerSecond + ms + yearOffset;
    906 }
    907743
    908744inline static void skipSpacesAndComments(const char *&s)
     
    12341070        t.tm_hour = hour;
    12351071
    1236         // Use our makeTime() rather than mktime() as the latter can't handle the full year range.
    1237         return makeTime(&t, 0, false);
     1072        // Use our dateToMseconds() rather than mktime() as the latter can't handle the full year range.
     1073        return dateToMseconds(&t, 0, false);
    12381074    }
    12391075
  • trunk/JavaScriptCore/kjs/testkjs.cpp

    r15437 r16780  
    3232#include <math.h>
    3333#include <stdio.h>
     34
    3435#include <string.h>
    3536#if HAVE(SYS_TIME_H)
Note: See TracChangeset for help on using the changeset viewer.