示例#1
0
 ///------------------------------------------------------------------------------
 /// Get a time value from SYSTEMTIME structure.
 ///
 /// Returns number of milliseconds since Jan 1, 1970
 ///------------------------------------------------------------------------------
 double
 DateUtilities::TimeFromSt(SYSTEMTIME *pst)
 {
     return TvFromDate(pst->wYear,pst->wMonth-1,pst->wDay-1, DayTimeFromSt(pst));
 }
bool DateImplementation::TryParseIsoString(const char16 *const str, const size_t length, double &timeValue, ScriptContext *scriptContext)
{
    Assert(str);

    size_t i = 0;
    const Js::CharClassifier *classifier = scriptContext->GetCharClassifier();
    // Skip leading whitespace (for cross-browser compatibility)
    // Also skip bidirectional characters, for Round tripping locale formatted date
    while ((classifier->IsWhiteSpace(str[i]) || classifier->IsBiDirectionalChar(str[i])) && ++i < length);

    // Minimum length must be 4 (YYYY)
    if(length - i < 4)
        return false;

    // YYYY|(+|-)YYYYYY
    int year;
    switch(str[i])
    {
    case _u('+'):
        ++i;
        if(!TryParseDecimalDigits(str, length, i, 6, year))
            return false;
        i += 6;
        break;

    case _u('-'):
        ++i;
        if(!TryParseDecimalDigits(str, length, i, 6, year) || year == 0)
            return false;
        year = -year;
        i += 6;
        break;

    case _u('0'):
    case _u('1'):
    case _u('2'):
    case _u('3'):
    case _u('4'):
    case _u('5'):
    case _u('6'):
    case _u('7'):
    case _u('8'):
    case _u('9'):
        if(!TryParseDecimalDigits(str, length, i, 4, year))
            return false;
        i += 4;
        break;

    default:
        return false;
    }

    // Skip bidirectional characters, for Round tripping locale formatted date
    i += classifier->SkipBiDirectionalChars(str, i, length);

    int month = 0,
        day = 0,
        timePortionMilliseconds = 0,
        utcOffsetMilliseconds = 0;
    bool isLocalTime = false;

    do // while(false);
    {
        do // while(false);
        {
            // -MM
            if(i >= length || str[i] != _u('-'))
                break;
            ++i;
            if(!TryParseTwoDecimalDigits(str, length, i, month))
                return false;
            --month;
            if(month < 0 || month > 11)
                return false;
            i += 2;

            // Skip bidirectional characters, for Round tripping locale formatted date
            i += classifier->SkipBiDirectionalChars(str, i, length);

            // -DD
            if(i >= length || str[i] != _u('-'))
                break;
            ++i;
            if(!TryParseTwoDecimalDigits(str, length, i, day))
                return false;
            --day;
            if(day < 0 || day > 30)
                return false;
            i += 2;

            // Skip bidirectional characters, for Round tripping locale formatted date
            i += classifier->SkipBiDirectionalChars(str, i, length);
        } while(false);

        // THH:mm
        if(i >= length || str[i] != _u('T'))
            break;
        ++i;
        int t;
        if(!TryParseTwoDecimalDigits(str, length, i, t) || t > 24)
            return false;
        timePortionMilliseconds += t * (60 * 60 * 1000);
        i += 2;

        // Skip bidirectional characters, for Round tripping locale formatted date
        i += classifier->SkipBiDirectionalChars(str, i, length);

        if(i >= length || str[i] != _u(':'))
            return false;
        ++i;
        if(!TryParseTwoDecimalDigits(str, length, i, t) || t > 59)
            return false;
        timePortionMilliseconds += t * (60 * 1000);
        i += 2;

        // Skip bidirectional characters, for Round tripping locale formatted date
        i += classifier->SkipBiDirectionalChars(str, i, length);

        do // while(false);
        {
            // :ss
            if(i >= length || str[i] != _u(':'))
                break;
            ++i;
            if(!TryParseTwoDecimalDigits(str, length, i, t) || t > 59)
                return false;
            timePortionMilliseconds += t * 1000;
            i += 2;

            // Skip bidirectional characters, for Round tripping locale formatted date
            i += classifier->SkipBiDirectionalChars(str, i, length);

            // .sss
            if(i >= length || str[i] != _u('.'))
                break;
            ++i;
            // Require one or more decimal digits. Ignore digits beyond the third
            size_t foundDigits = 0;
            if(!TryParseMilliseconds(str, length, i, t, foundDigits))
                return false;
            timePortionMilliseconds += t;
            i += foundDigits;

            // Skip bidirectional characters, for Round tripping locale formatted date
            i += classifier->SkipBiDirectionalChars(str, i, length);
        } while(false);

        // Z|(+|-)HH:mm
        if(i >= length)
        {
            isLocalTime = true;
            break;
        }
        const char16 utcOffsetSign = str[i];
        if(utcOffsetSign == _u('Z'))
        {
            ++i;
            break;
        }
        if(utcOffsetSign != _u('+') && utcOffsetSign != _u('-'))
        {
            isLocalTime = true;
            break;
        }
        ++i;
        // In -version:6 we allow optional colons in the timezone offset
        if (!TryParseTwoDecimalDigits(str, length, i, t, scriptContext->GetConfig()->IsES6DateParseFixEnabled() /* Timezone may be 4 sequential digits */) || t > 24)
            return false;
        utcOffsetMilliseconds += t * (60 * 60 * 1000);
        i += 2;

        // Skip bidirectional characters, for Round tripping locale formatted date
        i += classifier->SkipBiDirectionalChars(str, i, length);

        if(i >= length)
            return false;
        // The ':' is optional in ISO 8601
        if (str[i] == _u(':'))
        {
            ++i;
        }
        if(!TryParseTwoDecimalDigits(str, length, i, t) || t > 59)
            return false;
        utcOffsetMilliseconds += t * (60 * 1000);
        i += 2;

        // Skip bidirectional characters, for Round tripping locale formatted date
        i += classifier->SkipBiDirectionalChars(str, i, length);

        if(utcOffsetSign == _u('-'))
            utcOffsetMilliseconds = -utcOffsetMilliseconds;
    } while(false);

    // Skip trailing whitespace (for cross-browser compatibility)
    // Skip bidirectional characters, for Round tripping locale formatted date
    while (i < length && (classifier->IsWhiteSpace(str[i]) || classifier->IsBiDirectionalChar(str[i])))
        ++i;

    // There should only have been whitespace remaining, if any
    if(i < length)
        return false;
    Assert(i == length);

    // Compute the time value
    timeValue = TvFromDate(year, month, day, timePortionMilliseconds - utcOffsetMilliseconds);
    if (isLocalTime)
    {
        // Compatibility note:
        // In ES5, it was unspecified how to handle date strings without the trailing time zone offset "Z|(+|-)HH:mm".
        // In ES5.1, an absent time zone offset defaulted to "Z", which contradicted ISO8601:2004(E).
        // This was corrected in an ES5.1 errata note. Moreover, the ES6 draft now follows ISO8601.
        timeValue = GetTvUtc(timeValue, scriptContext);
    }
    return true;
}