Changeset 272127 in webkit


Ignore:
Timestamp:
Jan 31, 2021 12:48:01 PM (18 months ago)
Author:
ysuzuki@apple.com
Message:

Date.parse returns non-integral time value
https://bugs.webkit.org/show_bug.cgi?id=220687

Reviewed by Ross Kirsling.

JSTests:

  • complex.yaml:
  • complex/date-parse-milliseconds.js: Added.

(shouldBe):

Source/WTF:

Use milliseconds instead of seconds as a base unit to avoid floating point rounding for milliseconds.

  • wtf/DateMath.cpp:

(WTF::ymdhmsToMilliseconds):
(WTF::parseES5TimePortion):
(WTF::parseES5DateFromNullTerminatedCharacters):
(WTF::parseDateFromNullTerminatedCharacters):
(WTF::ymdhmsToSeconds): Deleted.

Location:
trunk
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r272099 r272127  
     12021-01-31  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        Date.parse returns non-integral time value
     4        https://bugs.webkit.org/show_bug.cgi?id=220687
     5
     6        Reviewed by Ross Kirsling.
     7
     8        * complex.yaml:
     9        * complex/date-parse-milliseconds.js: Added.
     10        (shouldBe):
     11
    1122021-01-29  Yusuke Suzuki  <ysuzuki@apple.com>
    213
  • trunk/JSTests/complex.yaml

    r270861 r272127  
    4141- path: complex/timezone-range-cache-with-dst.js
    4242  cmd: runComplexTest [], [], "TZ=America/Los_Angeles", "--useDollarVM=1"
     43
     44- path: complex/date-parse-milliseconds.js
     45  cmd: runComplexTest [], [], "TZ=America/Los_Angeles", "--useDollarVM=1"
  • trunk/Source/WTF/ChangeLog

    r272120 r272127  
     12021-01-31  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        Date.parse returns non-integral time value
     4        https://bugs.webkit.org/show_bug.cgi?id=220687
     5
     6        Reviewed by Ross Kirsling.
     7
     8        Use milliseconds instead of seconds as a base unit to avoid floating point rounding for milliseconds.
     9
     10        * wtf/DateMath.cpp:
     11        (WTF::ymdhmsToMilliseconds):
     12        (WTF::parseES5TimePortion):
     13        (WTF::parseES5DateFromNullTerminatedCharacters):
     14        (WTF::parseDateFromNullTerminatedCharacters):
     15        (WTF::ymdhmsToSeconds): Deleted.
     16
    1172021-01-30  Antti Koivisto  <antti@apple.com>
    218
  • trunk/Source/WTF/wtf/DateMath.cpp

    r261661 r272127  
    372372}
    373373
    374 static inline double ymdhmsToSeconds(int year, long mon, long day, long hour, long minute, double second)
     374static inline double ymdhmsToMilliseconds(int year, long mon, long day, long hour, long minute, long second, double milliseconds)
    375375{
    376376    int mday = firstDayOfMonth[isLeapYear(year)][mon - 1];
    377377    double ydays = daysFrom1970ToYear(year);
    378378
    379     double dateSeconds = second + minute * secondsPerMinute + hour * secondsPerHour + (mday + day - 1 + ydays) * secondsPerDay;
     379    double dateMilliseconds = milliseconds + second * msPerSecond + minute * (secondsPerMinute * msPerSecond) + hour * (secondsPerHour * msPerSecond) + (mday + day - 1 + ydays) * (secondsPerDay * msPerSecond);
    380380
    381381    // Clamp to EcmaScript standard (ecma262/#sec-time-values-and-time-range) of
    382382    //  +/- 100,000,000 days from 01 January, 1970.
    383     if (dateSeconds < -8640000000000.0 || dateSeconds > 8640000000000.0)
    384         return std::numeric_limits<double>::quiet_NaN();
    385    
    386     return dateSeconds;
     383    if (dateMilliseconds < -8640000000000000.0 || dateMilliseconds > 8640000000000000.0)
     384        return std::numeric_limits<double>::quiet_NaN();
     385   
     386    return dateMilliseconds;
    387387}
    388388
     
    507507// Fractional seconds parsing is lenient, allows any number of digits.
    508508// Returns 0 if a parse error occurs, else returns the end of the parsed portion of the string.
    509 static char* parseES5TimePortion(char* currentPosition, long& hours, long& minutes, double& seconds, bool& isLocalTime, long& timeZoneSeconds)
     509static char* parseES5TimePortion(char* currentPosition, long& hours, long& minutes, long& seconds, double& milliseconds, bool& isLocalTime, long& timeZoneSeconds)
    510510{
    511511    isLocalTime = false;
     
    532532        ++currentPosition;
    533533   
    534         long intSeconds;
    535534        if (!isASCIIDigit(*currentPosition))
    536535            return nullptr;
    537         if (!parseLong(currentPosition, &postParsePosition, 10, &intSeconds))
     536        if (!parseLong(currentPosition, &postParsePosition, 10, &seconds))
    538537            return nullptr;
    539538        if ((postParsePosition - currentPosition) != 2)
    540539            return nullptr;
    541         seconds = intSeconds;
    542540        if (*postParsePosition == '.') {
    543541            currentPosition = postParsePosition + 1;
     
    555553           
    556554            long numFracDigits = postParsePosition - currentPosition;
    557             seconds += fracSeconds * pow(10.0, static_cast<double>(-numFracDigits));
     555            milliseconds = fracSeconds * pow(10.0, static_cast<double>(-numFracDigits + 3));
    558556        }
    559557        currentPosition = postParsePosition;
     
    638636    long hours = 0;
    639637    long minutes = 0;
    640     double seconds = 0;
     638    long seconds = 0;
     639    double milliseconds = 0;
    641640    long timeZoneSeconds = 0;
    642641
     
    649648    if (*currentPosition == 'T') {
    650649        // Parse the time HH:mm[:ss[.sss]][Z|(+|-)(00:00|0000|00)]
    651         currentPosition = parseES5TimePortion(currentPosition + 1, hours, minutes, seconds, isLocalTime, timeZoneSeconds);
     650        currentPosition = parseES5TimePortion(currentPosition + 1, hours, minutes, seconds, milliseconds, isLocalTime, timeZoneSeconds);
    652651        if (!currentPosition)
    653652            return std::numeric_limits<double>::quiet_NaN();
     
    673672    if (seconds < 0 || seconds >= 61)
    674673        return std::numeric_limits<double>::quiet_NaN();
    675     if (seconds > 60) {
     674    if (seconds == 60) {
    676675        // Discard leap seconds by clamping to the end of a minute.
    677         seconds = 60;
     676        milliseconds = 0;
    678677    }
    679678       
    680     double dateSeconds = ymdhmsToSeconds(year, month, day, hours, minutes, seconds) - timeZoneSeconds;
    681     return dateSeconds * msPerSecond;
     679    return ymdhmsToMilliseconds(year, month, day, hours, minutes, seconds, milliseconds) - (timeZoneSeconds * msPerSecond);
    682680}
    683681
     
    984982    ASSERT(year);
    985983
    986     double dateSeconds = ymdhmsToSeconds(year.value(), month + 1, day, hour, minute, second) - offset * secondsPerMinute;
    987     return dateSeconds * msPerSecond;
     984    return ymdhmsToMilliseconds(year.value(), month + 1, day, hour, minute, second, 0) - offset * (secondsPerMinute * msPerSecond);
    988985}
    989986
Note: See TracChangeset for help on using the changeset viewer.