Changeset 69833 in webkit for trunk/JavaScriptCore/wtf/DateMath.cpp
- Timestamp:
- Oct 14, 2010, 7:45:03 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/wtf/DateMath.cpp
r53921 r69833 4 4 * Copyright (C) 2009 Google Inc. All rights reserved. 5 5 * Copyright (C) 2007-2009 Torch Mobile, Inc. 6 * Copyright (C) 2010 &yet, LLC. ([email protected]) 6 7 * 7 8 * The Original Code is Mozilla Communicator client code, released … … 480 481 } 481 482 482 static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, intsecond)483 static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, double second) 483 484 { 484 485 double days = (day - 32075) … … 556 557 return false; 557 558 return true; 559 } 560 561 double parseES5DateFromNullTerminatedCharacters(const char* dateString) 562 { 563 // This parses a date of the form defined in ECMA-262-5, section 15.9.1.15 564 // (similar to RFC 3339 / ISO 8601: YYYY-MM-DDTHH:mm:ss[.sss]Z). 565 // In most cases it is intentionally strict (e.g. correct field widths, no stray whitespace). 566 567 static const long daysPerMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 568 569 const char* currentPosition = dateString; 570 char* postParsePosition; 571 572 // This is a bit more lenient on the year string than ES5 specifies: 573 // instead of restricting to 4 digits (or 6 digits with mandatory +/-), 574 // it accepts any integer value. Consider this an implementation fallback. 575 long year; 576 if (!parseLong(currentPosition, &postParsePosition, 10, &year)) 577 return NaN; 578 if (*postParsePosition != '-') 579 return NaN; 580 currentPosition = postParsePosition + 1; 581 582 long month; 583 if (!isASCIIDigit(*currentPosition)) 584 return NaN; 585 if (!parseLong(currentPosition, &postParsePosition, 10, &month)) 586 return NaN; 587 if (*postParsePosition != '-' || (postParsePosition - currentPosition) != 2) 588 return NaN; 589 currentPosition = postParsePosition + 1; 590 591 long day; 592 if (!isASCIIDigit(*currentPosition)) 593 return NaN; 594 if (!parseLong(currentPosition, &postParsePosition, 10, &day)) 595 return NaN; 596 if (*postParsePosition != 'T' || (postParsePosition - currentPosition) != 2) 597 return NaN; 598 currentPosition = postParsePosition + 1; 599 600 long hours; 601 if (!isASCIIDigit(*currentPosition)) 602 return NaN; 603 if (!parseLong(currentPosition, &postParsePosition, 10, &hours)) 604 return NaN; 605 if (*postParsePosition != ':' || (postParsePosition - currentPosition) != 2) 606 return NaN; 607 currentPosition = postParsePosition + 1; 608 609 long minutes; 610 if (!isASCIIDigit(*currentPosition)) 611 return NaN; 612 if (!parseLong(currentPosition, &postParsePosition, 10, &minutes)) 613 return NaN; 614 if (*postParsePosition != ':' || (postParsePosition - currentPosition) != 2) 615 return NaN; 616 currentPosition = postParsePosition + 1; 617 618 long intSeconds; 619 if (!isASCIIDigit(*currentPosition)) 620 return NaN; 621 if (!parseLong(currentPosition, &postParsePosition, 10, &intSeconds)) 622 return NaN; 623 if ((postParsePosition - currentPosition) != 2) 624 return NaN; 625 626 double seconds = intSeconds; 627 if (*postParsePosition == '.') { 628 currentPosition = postParsePosition + 1; 629 630 // In ECMA-262-5 it's a bit unclear if '.' can be present without milliseconds, but 631 // a reasonable interpretation guided by the given examples and RFC 3339 says "no". 632 // We check the next character to avoid reading +/- timezone hours after an invalid decimal. 633 if (!isASCIIDigit(*currentPosition)) 634 return NaN; 635 636 // We are more lenient than ES5 by accepting more or less than 3 fraction digits. 637 long fracSeconds; 638 if (!parseLong(currentPosition, &postParsePosition, 10, &fracSeconds)) 639 return NaN; 640 641 long numFracDigits = postParsePosition - currentPosition; 642 seconds += fracSeconds * pow(10, -numFracDigits); 643 } 644 currentPosition = postParsePosition; 645 646 // A few of these checks could be done inline above, but since many of them are interrelated 647 // we would be sacrificing readability to "optimize" the (presumably less common) failure path. 648 if (month < 1 || month > 12) 649 return NaN; 650 if (day < 1 || day > daysPerMonth[month - 1]) 651 return NaN; 652 if (month == 2 && day > 28 && !isLeapYear(year)) 653 return NaN; 654 if (hours < 0 || hours > 24) 655 return NaN; 656 if (hours == 24 && (minutes || seconds)) 657 return NaN; 658 if (minutes < 0 || minutes > 59) 659 return NaN; 660 if (seconds < 0 || seconds >= 61) 661 return NaN; 662 if (seconds > 60) { 663 // Discard leap seconds by clamping to the end of a minute. 664 seconds = 60; 665 } 666 667 long timeZoneSeconds = 0; 668 if (*currentPosition != 'Z') { 669 bool tzNegative; 670 if (*currentPosition == '-') 671 tzNegative = true; 672 else if (*currentPosition == '+') 673 tzNegative = false; 674 else 675 return NaN; 676 currentPosition += 1; 677 678 long tzHours; 679 long tzHoursAbs; 680 long tzMinutes; 681 682 if (!isASCIIDigit(*currentPosition)) 683 return NaN; 684 if (!parseLong(currentPosition, &postParsePosition, 10, &tzHours)) 685 return NaN; 686 if (*postParsePosition != ':' || (postParsePosition - currentPosition) != 2) 687 return NaN; 688 tzHoursAbs = abs(tzHours); 689 currentPosition = postParsePosition + 1; 690 691 if (!isASCIIDigit(*currentPosition)) 692 return NaN; 693 if (!parseLong(currentPosition, &postParsePosition, 10, &tzMinutes)) 694 return NaN; 695 if ((postParsePosition - currentPosition) != 2) 696 return NaN; 697 currentPosition = postParsePosition; 698 699 if (tzHoursAbs > 24) 700 return NaN; 701 if (tzMinutes < 0 || tzMinutes > 59) 702 return NaN; 703 704 timeZoneSeconds = 60 * (tzMinutes + (60 * tzHoursAbs)); 705 if (tzNegative) 706 timeZoneSeconds = -timeZoneSeconds; 707 } else { 708 currentPosition += 1; 709 } 710 if (*currentPosition) 711 return NaN; 712 713 double dateSeconds = ymdhmsToSeconds(year, month, day, hours, minutes, seconds) - timeZoneSeconds; 714 return dateSeconds * msPerSecond; 558 715 } 559 716
Note:
See TracChangeset
for help on using the changeset viewer.