Ignore:
Timestamp:
Feb 6, 2006, 10:11:17 PM (19 years ago)
Author:
ap
Message:

Reviewed by Darin.

  • No tests added - only changed functionality on WIN32, which should be covered by existing tests.
  • kjs/date_object.cpp: (gmtoffset): On WIN32, use the recommended global (_timezone rather than timezone). Updated comments. (KJS::timeZoneOffset): Removed, was basically the same as the above. (KJS::formatTime): Pass an UTC flag - UTC/local cannot be correctly selected on Windows based on struct tm itself. (KJS::DateInstance::getTime): Added. (KJS::DateInstance::getUTCTime): Added. (KJS::millisecondsToTM): Factored out from DateProtoFunc::callAsFunction(). (KJS::DateObjectImp::callAsFunction): Use the new parameter to formatTime(). (KJS::DateProtoFunc::callAsFunction): Updated for the other changes. The code for GetTimezoneOffset was incorrect on WIN32 - _daylight global has nothing to do with daylight savings time being in effect.
  • kjs/date_object.h: Added prototypes for new functions.
File:
1 edited

Legend:

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

    r12445 r12624  
    6666{
    6767#if WIN32
    68     // FIXME: This might not be completely correct if the time is not the current timezone.
    69     return -(timezone / 60 - (t.tm_isdst > 0 ? 60 : 0 )) * 60;
     68    // Time is supposed to be in the current timezone.
     69    // FIXME: Use undocumented _dstbias?
     70    return -(_timezone / 60 - (t.tm_isdst > 0 ? 60 : 0 )) * 60;
    7071#else
    7172    return t.tm_gmtoff;
     
    141142static double parseDate(const UString &);
    142143static double timeClip(double);
     144static void millisecondsToTM(double milli, bool utc, tm *t);
    143145
    144146#if __APPLE__
     
    227229}
    228230
    229 static UString formatTime(const tm &t)
     231static UString formatTime(const tm &t, bool utc)
    230232{
    231233    char buffer[100];
    232     if (gmtoffset(t) == 0) {
     234    if (utc) {
     235#if !WIN32
     236        ASSERT(t.tm_gmtoff == 0);
     237#endif
    233238        snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT", t.tm_hour, t.tm_min, t.tm_sec);
    234239    } else {
     
    300305        wd += 7;
    301306    return wd;
    302 }
    303 
    304 static long timeZoneOffset(const tm &t)
    305 {
    306 #if !WIN32
    307     return -(t.tm_gmtoff / 60);
    308 #else
    309 #  if __BORLANDC__ || __CYGWIN__
    310 // FIXME: Can't be right because time zone is supposed to be from the parameter, not the computer.
    311 // FIXME: consider non one-hour DST change.
    312 #    if !__CYGWIN__
    313 #      error please add daylight savings offset here!
    314 #    endif
    315     return _timezone / 60 - (t.tm_isdst > 0 ? 60 : 0);
    316 #  else
    317     return timezone / 60 - (t.tm_isdst > 0 ? 60 : 0 );
    318 #  endif
    319 #endif
    320307}
    321308
     
    398385{
    399386}
     387
     388bool DateInstance::getTime(tm &t, int &offset) const
     389{
     390    double milli = internalValue()->getNumber();
     391    if (isNaN(milli))
     392        return false;
     393   
     394    millisecondsToTM(milli, false, &t);
     395    offset = gmtoffset(t);
     396    return true;
     397}
     398
     399bool DateInstance::getUTCTime(tm &t) const
     400{
     401    double milli = internalValue()->getNumber();
     402    if (isNaN(milli))
     403        return false;
     404   
     405    millisecondsToTM(milli, true, &t);
     406    return true;
     407}
     408
     409bool DateInstance::getTime(double &milli, int &offset) const
     410{
     411    milli = internalValue()->getNumber();
     412    if (isNaN(milli))
     413        return false;
     414   
     415    tm t;
     416    millisecondsToTM(milli, false, &t);
     417    offset = gmtoffset(t);
     418    return true;
     419}
     420
     421bool DateInstance::getUTCTime(double &milli) const
     422{
     423    milli = internalValue()->getNumber();
     424    if (isNaN(milli))
     425        return false;
     426   
     427    return true;
     428}
     429
     430static inline bool isTime_tSigned()
     431{
     432    time_t minusOne = (time_t)(-1);
     433    return minusOne < 0;
     434}
     435
     436static void millisecondsToTM(double milli, bool utc, tm *t)
     437{
     438  // check whether time value is outside time_t's usual range
     439  // make the necessary transformations if necessary
     440  static bool time_tIsSigned = isTime_tSigned();
     441  static double time_tMin = (time_tIsSigned ? - (double)(1ULL << (8 * sizeof(time_t) - 1)) : 0);
     442  static double time_tMax = (time_tIsSigned ? (1ULL << 8 * sizeof(time_t) - 1) - 1 : 2 * (double)(1ULL << 8 * sizeof(time_t) - 1) - 1);
     443  int realYearOffset = 0;
     444  double milliOffset = 0.0;
     445  double secs = floor(milli / msPerSecond);
     446
     447  if (secs < time_tMin || secs > time_tMax) {
     448    // ### ugly and probably not very precise
     449    int realYear = yearFromTime(milli);
     450    int base = daysInYear(realYear) == 365 ? 2001 : 2000;
     451    milliOffset = timeFromYear(base) - timeFromYear(realYear);
     452    milli += milliOffset;
     453    realYearOffset = realYear - base;
     454  }
     455
     456  time_t tv = (time_t) floor(milli / msPerSecond);
     457
     458  *t = *(utc ? gmtime(&tv) : localtime(&tv));
     459  // We had an out of range year. Restore the year (plus/minus offset
     460  // found by calculating tm_year) and fix the week day calculation.
     461  if (realYearOffset != 0) {
     462    t->tm_year += realYearOffset;
     463    milli -= milliOffset;
     464    // Do our own weekday calculation. Use time zone offset to handle local time.
     465    double m = milli;
     466    if (!utc)
     467      m += gmtoffset(*t) * msPerSecond;
     468    t->tm_wday = weekDay(m);
     469  }
     470}   
     471
    400472
    401473// ------------------------------ DatePrototype -----------------------------
     
    481553}
    482554
    483 static bool isTime_tSigned()
    484 {
    485     time_t minusOne = (time_t)(-1);
    486     return minusOne < 0;
    487 }
    488 
    489555JSValue *DateProtoFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
    490556{
     
    531597  }
    532598 
    533   // check whether time value is outside time_t's usual range
    534   // make the necessary transformations if necessary
    535   static bool time_tIsSigned = isTime_tSigned();
    536   static double time_tMin = (time_tIsSigned ? - (double)(1ULL << (8 * sizeof(time_t) - 1)) : 0);
    537   static double time_tMax = (time_tIsSigned ? (1ULL << 8 * sizeof(time_t) - 1) - 1 : 2 * (double)(1ULL << 8 * sizeof(time_t) - 1) - 1);
    538   int realYearOffset = 0;
    539   double milliOffset = 0.0;
    540599  double secs = floor(milli / msPerSecond);
    541 
    542   if (secs < time_tMin || secs > time_tMax) {
    543     // ### ugly and probably not very precise
    544     int realYear = yearFromTime(milli);
    545     int base = daysInYear(realYear) == 365 ? 2001 : 2000;
    546     milliOffset = timeFromYear(base) - timeFromYear(realYear);
    547     milli += milliOffset;
    548     realYearOffset = realYear - base;
    549   }
    550 
    551   time_t tv = (time_t) floor(milli / msPerSecond);
    552   double ms = milli - tv * msPerSecond;
    553 
    554   tm t = *(utc ? gmtime(&tv) : localtime(&tv));
    555   // We had an out of range year. Restore the year (plus/minus offset
    556   // found by calculating tm_year) and fix the week day calculation.
    557   if (realYearOffset != 0) {
    558     t.tm_year += realYearOffset;
    559     milli -= milliOffset;
    560     // Do our own weekday calculation. Use time zone offset to handle local time.
    561     double m = milli;
    562     if (!utc)
    563       m -= timeZoneOffset(t) * msPerMinute;
    564     t.tm_wday = weekDay(m);
    565   }
     600  double ms = milli - secs * msPerSecond;
     601
     602  tm t;
     603  millisecondsToTM(milli, utc, &t);
    566604
    567605  switch (id) {
    568606  case ToString:
    569     return jsString(formatDate(t) + " " + formatTime(t));
     607    return jsString(formatDate(t) + " " + formatTime(t, utc));
    570608  case ToDateString:
    571609    return jsString(formatDate(t));
    572610    break;
    573611  case ToTimeString:
    574     return jsString(formatTime(t));
     612    return jsString(formatTime(t, utc));
    575613    break;
    576614  case ToGMTString:
    577615  case ToUTCString:
    578     return jsString(formatDateUTCVariant(t) + " " + formatTime(t));
     616    return jsString(formatDateUTCVariant(t) + " " + formatTime(t, utc));
    579617    break;
    580618#if __APPLE__
     
    627665    return jsNumber(ms);
    628666  case GetTimezoneOffset:
    629 #if !WIN32
    630     return jsNumber(-t.tm_gmtoff / 60);
    631 #else
    632 #  if __BORLANDC__
    633 #error please add daylight savings offset here!
    634     // FIXME: Using the daylight value was wrong for BSD, maybe wrong here too.
    635     return jsNumber(_timezone / 60 - (_daylight ? 60 : 0));
    636 #  else
    637     // FIXME: Using the daylight value was wrong for BSD, maybe wrong here too.
    638     return jsNumber(( timezone / 60 - (daylight ? 60 : 0 )));
    639 #  endif
    640 #endif
     667    return jsNumber(-gmtoffset(t) / 60);
    641668  case SetTime:
    642669    milli = roundValue(exec, args[0]);
     
    779806    time_t t = time(0);
    780807    tm ts = *localtime(&t);
    781     return jsString(formatDate(ts) + " " + formatTime(ts));
     808    return jsString(formatDate(ts) + " " + formatTime(ts, false));
    782809}
    783810
Note: See TracChangeset for help on using the changeset viewer.