Changeset 19943 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Mar 2, 2007, 9:42:20 AM (18 years ago)
Author:
darin
Message:

Reviewed by Kevin McCullough.

  • kjs/DateMath.h: Marked GregorianDateTime as noncopyable, since it has a non-trivial destructor and not the correspoding copy constructor or assignment operator. Changed the GregorianDateTime constructor to use member initialization syntax. Fixed the destructor to use the array delete operator, since timeZone is an array.
  • kjs/DateMath.cpp: (KJS::daysInYear): Changed to call isLeapYear so the rule is not repeated twice. (KJS::getUTCOffset): Added caching on PLATFORM(DARWIN), since we can rely on the notify_check function and "com.apple.system.timezone" to let us know when the offset has changed.
Location:
trunk/JavaScriptCore/kjs
Files:
2 edited

Legend:

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

    r19268 r19943  
    4545#include <math.h>
    4646#include <stdint.h>
    47 #include <wtf/OwnPtr.h>
     47
     48#if PLATFORM(DARWIN)
     49#include <notify.h>
     50#endif
    4851
    4952namespace KJS {
     
    5760static const double usecPerSec = 1000000.0;
    5861
    59 static const double maxUnixTime = 2145859200.0; /*equivalent to 12/31/2037 */
    60 
    61 /*
    62  * The following array contains the day of year for the first day of
    63  * each month, where index 0 is January, and day 0 is January 1.
    64  */
    65 static int firstDayOfMonth[2][12] = {
     62static const double maxUnixTime = 2145859200.0; // 12/31/2037
     63
     64// Day of year for the first day of each month, where index 0 is January, and day 0 is January 1.
     65// First for non-leap years, then for leap years.
     66static const int firstDayOfMonth[2][12] = {
    6667    {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
    6768    {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
    6869};
    69 
    70 static inline int daysInYear(int year)
    71 {
    72     if (year % 4 != 0)
    73         return 365;
    74     if (year % 400 == 0)
    75         return 366;
    76     if (year % 100 == 0)
    77         return 365;
    78     return 366;
    79 }
    80 
    81 static inline double daysFrom1970ToYear(int year)
    82 {
    83     return 365.0 * (year - 1970)
    84         + floor((year - 1969) / 4.0)
    85         - floor((year - 1901) / 100.0)
    86         + floor((year - 1601) / 400.0);
    87 }
    88 
    89 static inline double msFrom1970ToYear(int year)
    90 {
    91     return msPerDay * daysFrom1970ToYear(year);
    92 }
    93 
    94 static inline double msToDays(double ms)
    95 {
    96     return floor(ms / msPerDay);
    97 }
    98 
    99 static inline int msToYear(double ms)
    100 {
    101     int y = static_cast<int>(floor(ms /(msPerDay*365.2425)) + 1970);
    102     double t2 = msFrom1970ToYear(y);
    103 
    104     if (t2 > ms) {
    105         y--;
    106     } else {
    107         if (t2 + msPerDay * daysInYear(y) <= ms)
    108             y++;
    109     }
    110     return y;
    111 }
    11270
    11371static inline bool isLeapYear(int year)
     
    12280}
    12381
     82static inline int daysInYear(int year)
     83{
     84    return 365 + isLeapYear(year);
     85}
     86
     87static inline double daysFrom1970ToYear(int year)
     88{
     89    return 365.0 * (year - 1970)
     90        + floor((year - 1969) / 4.0)
     91        - floor((year - 1901) / 100.0)
     92        + floor((year - 1601) / 400.0);
     93}
     94
     95static inline double msFrom1970ToYear(int year)
     96{
     97    return msPerDay * daysFrom1970ToYear(year);
     98}
     99
     100static inline double msToDays(double ms)
     101{
     102    return floor(ms / msPerDay);
     103}
     104
     105static inline int msToYear(double ms)
     106{
     107    int y = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970);
     108    double t2 = msFrom1970ToYear(y);
     109    if (t2 > ms) {
     110        y--;
     111    } else {
     112        if (t2 + msPerDay * daysInYear(y) <= ms)
     113            y++;
     114    }
     115    return y;
     116}
     117
    124118static inline bool isInLeapYear(double ms)
    125119{
     
    134128static inline double msToMilliseconds(double ms)
    135129{
    136     double result;
    137     result = fmod(ms, msPerDay);
     130    double result = fmod(ms, msPerDay);
    138131    if (result < 0)
    139132        result += msPerDay;
     
    144137static inline int msToWeekDay(double ms)
    145138{
    146     int wd = ((int)msToDays(ms) + 4) % 7;
     139    int wd = (static_cast<int>(msToDays(ms)) + 4) % 7;
    147140    if (wd < 0)
    148141        wd += 7;
     
    152145static inline int msToSeconds(double ms)
    153146{
    154     int result = (int) fmod(floor(ms / msPerSecond), secondsPerMinute);
     147    double result = fmod(floor(ms / msPerSecond), secondsPerMinute);
    155148    if (result < 0)
    156         result += (int)secondsPerMinute;
    157     return result;
     149        result += secondsPerMinute;
     150    return static_cast<int>(result);
    158151}
    159152
    160153static inline int msToMinutes(double ms)
    161154{
    162     int result = (int) fmod(floor(ms / msPerMinute), minutesPerHour);
     155    double result = fmod(floor(ms / msPerMinute), minutesPerHour);
    163156    if (result < 0)
    164         result += (int)minutesPerHour;
    165     return result;
     157        result += minutesPerHour;
     158    return static_cast<int>(result);
    166159}
    167160
    168161static inline int msToHours(double ms)
    169162{
    170     int result = (int) fmod(floor(ms/msPerHour), hoursPerDay);
     163    double result = fmod(floor(ms/msPerHour), hoursPerDay);
    171164    if (result < 0)
    172         result += (int)hoursPerDay;
    173     return result;
     165        result += hoursPerDay;
     166    return static_cast<int>(result);
    174167}
    175168
    176169static inline int msToMonth(double ms)
    177170{
    178     int d, step;
     171    int step;
    179172    int year = msToYear(ms);
    180     d = dayInYear(ms, year);
     173    int d = dayInYear(ms, year);
    181174
    182175    if (d < (step = 31))
     
    208201static inline int msToDayInMonth(double ms)
    209202{
    210     int d, step, next;
     203    int step, next;
    211204    int year = msToYear(ms);
    212     d = dayInYear(ms, year);
     205    int d = dayInYear(ms, year);
    213206
    214207    if (d <= (next = 30))
     
    294287 * NOT including DST.
    295288 */
    296 double getUTCOffset() {
     289double getUTCOffset()
     290{
     291#if PLATFORM(DARWIN)
     292    // Register for a notification whenever the time zone changes.
     293    static bool triedToRegister = false;
     294    static bool haveNotificationToken = false;
     295    static int notificationToken;
     296    if (!triedToRegister) {
     297        triedToRegister = true;
     298        uint32_t status = notify_register_check("com.apple.system.timezone", &notificationToken);
     299        if (status == NOTIFY_STATUS_OK)
     300            haveNotificationToken = true;
     301    }
     302
     303    // If we can verify that we have not received a time zone notification,
     304    // then use the cached offset from the last time this function was called.
     305    static bool haveCachedOffset = false;
     306    static double cachedOffset;
     307    if (haveNotificationToken && haveCachedOffset) {
     308        int notified;
     309        uint32_t status = notify_check(notificationToken, &notified);
     310        if (status == NOTIFY_STATUS_OK && !notified)
     311            return cachedOffset;
     312    }
     313#endif
     314
    297315    tm localt;
    298316
     
    305323
    306324    utcOffset *= msPerSecond;
     325
     326#if PLATFORM(DARWIN)
     327    haveCachedOffset = true;
     328    cachedOffset = utcOffset;
     329#endif
    307330
    308331    return utcOffset;
     
    316339static double getDSTOffsetSimple(double localTimeSeconds)
    317340{
    318     if(localTimeSeconds > maxUnixTime)
     341    if (localTimeSeconds > maxUnixTime)
    319342        localTimeSeconds = maxUnixTime;
    320343    else if(localTimeSeconds < 0) // Go ahead a day to make localtime work (does not work with 0)
     
    322345
    323346    //input is UTC so we have to shift back to local time to determine DST thus the + getUTCOffset()
    324     double offsetTime = (localTimeSeconds * msPerSecond) + getUTCOffset() ;
     347    double offsetTime = (localTimeSeconds * msPerSecond) + getUTCOffset();
    325348
    326349    // Offset from UTC but doesn't include DST obviously
     
    332355
    333356    tm localTM;
    334     #if PLATFORM(WIN_OS)
     357#if PLATFORM(WIN_OS)
    335358    localtime_s(&localTM, &localTime);
    336     #else
     359#else
    337360    localtime_r(&localTime, &localTM);
    338     #endif
    339    
     361#endif
     362
    340363    double diff = ((localTM.tm_hour - offsetHour) * secondsPerHour) + ((localTM.tm_min - offsetMinute) * 60);
    341364
     
    346369}
    347370
    348 // Get the DST offset the time passed in
    349 // ms is in UTC
     371// Get the DST offset, given a time in UTC
    350372static double getDSTOffset(double ms)
    351373{
    352     // On mac the call to localtime (see getDSTOffsetSimple) will return historically accurate
     374    // On Mac OS X, the call to localtime (see getDSTOffsetSimple) will return historically accurate
    353375    // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript
    354376    // standard explicitly dictates that historical information should not be considered when
    355     // determining DST.  For this reason we shift years that localtime can handle but would
     377    // determining DST. For this reason we shift away from years that localtime can handle but would
    356378    // return historically accurate information.
    357379
    358380    // if before Jan 01, 2000 12:00:00 AM UTC or after Jan 01, 2038 12:00:00 AM UTC
    359381    if (ms < 946684800000.0 || ms > 2145916800000.0) {
    360         int year;
    361         int day;
    362 
    363         year = equivalentYearForDST(msToYear(ms));
    364         day = dateToDayInYear(year, msToMonth(ms), msToDayInMonth(ms));
     382        int year = equivalentYearForDST(msToYear(ms));
     383        int day = dateToDayInYear(year, msToMonth(ms), msToDayInMonth(ms));
    365384        ms = (day * msPerDay) + msToMilliseconds(ms);
    366385    }
     
    371390double gregorianDateTimeToMS(const GregorianDateTime& t, double milliSeconds, bool inputIsUTC)
    372391{
    373 
    374392    int day = dateToDayInYear(t.year + 1900, t.month, t.monthDay);
    375393    double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds);
    376394    double result = (day * msPerDay) + ms;
    377395
    378     if(!inputIsUTC) { // convert to UTC
     396    if (!inputIsUTC) { // convert to UTC
    379397        result -= getUTCOffset();       
    380398        result -= getDSTOffset(result);
     
    389407    double dstOff = 0.0;
    390408   
    391     if(!outputIsUTC) {  // convert to local time
     409    if (!outputIsUTC) {  // convert to local time
    392410        dstOff = getDSTOffset(ms);
    393411        ms += dstOff + getUTCOffset();
     
    402420    tm.month    =  msToMonth(ms);
    403421    tm.year     =  msToYear(ms) - 1900;
    404     tm.isDST =  dstOff != 0.0;
     422    tm.isDST    =  dstOff != 0.0;
    405423
    406424    tm.utcOffset = static_cast<long>((dstOff + getUTCOffset()) / msPerSecond);
     
    408426}
    409427
    410 }   // namespace KJS
     428} // namespace KJS
  • trunk/JavaScriptCore/kjs/DateMath.h

    r17444 r19943  
    11/*
    22 * Copyright (C) 1999-2000 Harri Porten ([email protected])
    3  * Copyright (C) 2006 Apple Computer
     3 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
    44 *
    55 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
     
    4444#include <time.h>
    4545#include <string.h>
     46#include <wtf/Noncopyable.h>
    4647
    4748namespace KJS {
    4849
    49 // Constants //
    5050const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
    5151const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
     
    6060const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0;
    6161
    62 
    63 // Forward //
    64 struct GregorianDateTime;
    65 
    66 // Exported Functions //
    67 void msToGregorianDateTime(double, bool outputIsUTC, struct GregorianDateTime&);
    68 double gregorianDateTimeToMS(const GregorianDateTime&, double, bool inputIsUTC);
    69 double getUTCOffset();
    70 int equivalentYearForDST(int year);
    71 
    7262// Intentionally overridding the default tm of the system
    7363// Not all OS' have the same members of their tm's
    74 struct GregorianDateTime {
     64struct GregorianDateTime : Noncopyable{
    7565    GregorianDateTime()
     66        : second(0)
     67        , minute(0)
     68        , hour(0)
     69        , weekDay(0)
     70        , monthDay(0)
     71        , yearDay(0)
     72        , month(0)
     73        , year(0)
     74        , isDST(0)
     75        , utcOffset(0)
     76        , timeZone(0)
    7677    {
    77         second = 0;
    78         minute = 0;
    79         hour = 0;
    80         weekDay = 0;
    81         monthDay = 0;
    82         yearDay = 0;
    83         month = 0;
    84         year = 0;
    85         isDST = 0;
    86         utcOffset = 0;
    87         timeZone = NULL;
    8878    }
    8979
    9080    ~GregorianDateTime()
    9181    {
    92         if (timeZone)
    93             delete timeZone;
     82        delete [] timeZone;
    9483    }
    9584   
     
    148137    int month;
    149138    int year;
    150     int  isDST;
     139    int isDST;
    151140    int utcOffset;
    152141    char* timeZone;
    153142};
    154143
     144void msToGregorianDateTime(double, bool outputIsUTC, struct GregorianDateTime&);
     145double gregorianDateTimeToMS(const GregorianDateTime&, double, bool inputIsUTC);
     146double getUTCOffset();
     147int equivalentYearForDST(int year);
     148
    155149}   //namespace KJS
    156150
Note: See TracChangeset for help on using the changeset viewer.