Ignore:
Timestamp:
Dec 23, 2002, 2:35:52 PM (22 years ago)
Author:
darin
Message:

Reviewed by Don and John.

  • fixed 3134449 -- Date.UTC returns NaN (invalid date)

Did more testing of the date functions and made them behave like the other browsers.
There were three problems:

1) We did a validity check that other browsers don't do (hence the NaN).
2) We treated passed-in dates as local time even in Date.UTC (hence a wrong result

once I fixed the NaN).

3) The results of ToUTCString (and ToGMTString) weren't formatted quite the same

as other browsers.

Also found a couple of silly but unrelated coding mistakes.

  • kjs/date_object.cpp: (timetUsingCF): Added. Has the guts of mktimeUsingCF, but without the CFGregorianDateIsValid check. Other browsers accept invalid dates. Also takes a time zone parameter. (mktimeUsingCF): Calls timetUsingCF with the current time zone. (timegmUsingCF): Calls timetUsingCF with the UTC time zone. (formatDate): Remove the includeComma flag. (formatDateUTCVariant): Added. For use instead of formatDate with the includeComma flag. Puts the day before the month name. (DateProtoFuncImp::call): Use the new formatDateUTCVariant for ToGMTString and ToUTCString. Without this change the date didn't match other browsers. (DateObjectImp::DateObjectImp): Use UTCPropertyName. Somehow I declared this and didn't use it before. (DateObjectImp::construct): Pass -1 for is_dst literally instead of using invalidDate. Changing this to invalidDate was just a mistake (although no real difference in compiled code since invalidDate is just -1). (DateObjectFuncImp::call): Call timegm for the UTC case instead of mktime.
File:
1 edited

Legend:

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

    r3098 r3177  
    7474#define localtime(x) localtimeUsingCF(x)
    7575#define mktime(x) mktimeUsingCF(x)
     76#define timegm(x) timegmUsingCF(x)
    7677#define time(x) timeUsingCF(x)
    7778
     
    123124}
    124125
    125 static time_t mktimeUsingCF(struct tm *tm)
     126static time_t timetUsingCF(struct tm *tm, CFTimeZoneRef timeZone)
    126127{
    127128    CFGregorianDate date;
     
    135136    // CFGregorianDateGetAbsoluteTime will go nuts if the year is too large,
    136137    // so we pick an arbitrary cutoff.
    137     if (!CFGregorianDateIsValid(date, kCFGregorianAllUnits) || date.year > 2500) {
     138    if (date.year > 2500) {
    138139        return invalidDate;
    139140    }
    140141
     142    CFAbsoluteTime absoluteTime = CFGregorianDateGetAbsoluteTime(date, timeZone);
     143
     144    return (time_t)(absoluteTime + kCFAbsoluteTimeIntervalSince1970);
     145}
     146
     147static time_t mktimeUsingCF(struct tm *tm)
     148{
    141149    CFTimeZoneRef timeZone = CFTimeZoneCopyDefault();
    142     CFAbsoluteTime absoluteTime = CFGregorianDateGetAbsoluteTime(date, timeZone);
     150    time_t result = timetUsingCF(tm, timeZone);
    143151    CFRelease(timeZone);
    144 
    145     return (time_t)(absoluteTime + kCFAbsoluteTimeIntervalSince1970);
     152    return result;
     153}
     154
     155static time_t timegmUsingCF(struct tm *tm)
     156{
     157    static CFTimeZoneRef timeZoneUTC = CFTimeZoneCreateWithName(NULL, CFSTR("UTC"), TRUE);
     158    return timetUsingCF(tm, timeZoneUTC);
    146159}
    147160
     
    155168}
    156169
    157 static UString formatDate(struct tm &tm, bool includeComma = false)
     170static UString formatDate(struct tm &tm)
    158171{
    159172    char buffer[100];
    160     snprintf(buffer, sizeof(buffer), "%s%s %s %02d %04d",
    161         weekdayName[(tm.tm_wday + 6) % 7], includeComma ? "," : "",
     173    snprintf(buffer, sizeof(buffer), "%s %s %02d %04d",
     174        weekdayName[(tm.tm_wday + 6) % 7],
    162175        monthName[tm.tm_mon], tm.tm_mday, tm.tm_year + 1900);
     176    return buffer;
     177}
     178
     179static UString formatDateUTCVariant(struct tm &tm)
     180{
     181    char buffer[100];
     182    snprintf(buffer, sizeof(buffer), "%s, %02d %s %04d",
     183        weekdayName[(tm.tm_wday + 6) % 7],
     184        tm.tm_mday, monthName[tm.tm_mon], tm.tm_year + 1900);
    163185    return buffer;
    164186}
     
    377399  case ToGMTString:
    378400  case ToUTCString:
    379     result = String(formatDate(*t, true) + " " + formatTime(*t));
     401    result = String(formatDateUTCVariant(*t) + " " + formatTime(*t));
    380402    break;
    381403  case ToLocaleString:
     
    532554  putDirect(parsePropertyName, new DateObjectFuncImp(exec,funcProto,DateObjectFuncImp::Parse, 1), DontEnum);
    533555  static const Identifier UTCPropertyName("UTC");
    534   putDirect("UTC",   new DateObjectFuncImp(exec,funcProto,DateObjectFuncImp::UTC,   7),   DontEnum);
     556  putDirect(UTCPropertyName,   new DateObjectFuncImp(exec,funcProto,DateObjectFuncImp::UTC,   7),   DontEnum);
    535557
    536558  // no. of arguments for constructor
     
    595617      t.tm_min = (numArgs >= 5) ? args[4].toInt32(exec) : 0;
    596618      t.tm_sec = (numArgs >= 6) ? args[5].toInt32(exec) : 0;
    597       t.tm_isdst = invalidDate;
     619      t.tm_isdst = -1;
    598620      int ms = (numArgs >= 7) ? args[6].toInt32(exec) : 0;
    599621      time_t mktimeResult = mktime(&t);
     
    679701    t.tm_sec = (n >= 6) ? args[5].toInt32(exec) : 0;
    680702    int ms = (n >= 7) ? args[6].toInt32(exec) : 0;
    681     time_t mktimeResult = mktime(&t);
     703    time_t mktimeResult = timegm(&t);
    682704    if (mktimeResult == invalidDate)
    683705      return Number(NaN);
Note: See TracChangeset for help on using the changeset viewer.