Commit 014b4536 authored by kmccullo's avatar kmccullo
Browse files

JavaScriptCore:

        Reviewed by Geoff.

        - rdar://problem/5045720
        - DST changes in US affect JavaScript date calculations (12975)
        This fix was to ensure we properly test for the new changes to DST in the US.
        Also this fixes when we apply DST, now we correctly map most past years to current
        DST rules.  We still have a small issue with years before 1900 or after 2100.
        rdar://problem/5055038

        * kjs/DateMath.cpp: Fix DST to match spec better.
        (KJS::getCurrentUTCTime):
        (KJS::mimimumYearForDST):
        (KJS::maximumYearForDST):
        (KJS::equivalentYearForDST):
        (KJS::getDSTOffset):
        * kjs/DateMath.h: Consolodated common funtionality.
        * kjs/date_object.cpp: Consolodated common functionality.
        (KJS::formatLocaleDate):
        (KJS::DateObjectImp::construct):
        * tests/mozilla/ecma/jsref.js: Added functions for finding the correct days when DST starts and ends.
        * tests/mozilla/ecma/shell.js: Added back in the old DST functions for ease of merging with mozilla if needed.
        * tests/mozilla/ecma_2/jsref.js: Added functions for finding the correct days when DST starts and ends.
        * tests/mozilla/ecma_3/Date/shell.js: Added functions for finding the correct days when DST starts and ends.
        * tests/mozilla/expected.html: Updated to show all date tests passing.

LayoutTests:

        Reviewed by Geoff.

        - rdar://problem/5045720
        - DST changes in US affect JavaScript date calculations (12975)
        Changed layout tests to properly check for the new changes to DST in the
        US. Also these now test that equivalent years return the same results for DST.

        * fast/js/date-DST-time-cusps-expected.txt:
        * fast/js/date-big-setdate-expected.txt:
        * fast/js/resources/date-DST-time-cusps.js:
        * fast/js/resources/date-big-setdate.js:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@20203 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 5a5b938d
2007-03-14 Kevin McCullough <kmccullough@apple.com>
Reviewed by Geoff.
- rdar://problem/5045720
- DST changes in US affect JavaScript date calculations (12975)
This fix was to ensure we properly test for the new changes to DST in the US.
Also this fixes when we apply DST, now we correctly map most past years to current
DST rules. We still have a small issue with years before 1900 or after 2100.
rdar://problem/5055038
* kjs/DateMath.cpp: Fix DST to match spec better.
(KJS::getCurrentUTCTime):
(KJS::mimimumYearForDST):
(KJS::maximumYearForDST):
(KJS::equivalentYearForDST):
(KJS::getDSTOffset):
* kjs/DateMath.h: Consolodated common funtionality.
* kjs/date_object.cpp: Consolodated common functionality.
(KJS::formatLocaleDate):
(KJS::DateObjectImp::construct):
* tests/mozilla/ecma/jsref.js: Added functions for finding the correct days when DST starts and ends.
* tests/mozilla/ecma/shell.js: Added back in the old DST functions for ease of merging with mozilla if needed.
* tests/mozilla/ecma_2/jsref.js: Added functions for finding the correct days when DST starts and ends.
* tests/mozilla/ecma_3/Date/shell.js: Added functions for finding the correct days when DST starts and ends.
* tests/mozilla/expected.html: Updated to show all date tests passing.
2007-03-13 Kevin McCullough <kmccullough@apple.com>
 
Reviewed by .
......
......@@ -44,6 +44,9 @@
#include <math.h>
#include <stdint.h>
#include <value.h>
#include <wtf/Assertions.h>
#if PLATFORM(DARWIN)
#include <notify.h>
......@@ -267,19 +270,74 @@ static int dateToDayInYear(int year, int month, int day)
return yearday + monthday + day - 1;
}
double getCurrentUTCTime()
{
#if PLATFORM(WIN_OS)
#if COMPILER(BORLAND)
struct timeb timebuffer;
ftime(&timebuffer);
#else
struct _timeb timebuffer;
_ftime(&timebuffer);
#endif
double utc = timebuffer.time * msPerSecond + timebuffer.millitm;
#else
struct timeval tv;
gettimeofday(&tv, 0);
double utc = floor(tv.tv_sec * msPerSecond + tv.tv_usec / 1000);
#endif
return utc;
}
// There is a hard limit at 2038 that we currently do not have a workaround
// for (rdar://problem/5052975).
static inline int maximumYearForDST()
{
return 2037;
}
// It is ok if the cached year is not the current year (e.g. Dec 31st)
// so long as the rules for DST did not change between the two years, if it does
// the app would need to be restarted.
static int mimimumYearForDST()
{
// Because of the 2038 issue (see maximumYearForDST) if the current year is
// greater than the max year minus 27 (2010), we want to use the max year
// minus 27 instead, to ensure there is a range of 28 years that all years
// can map to.
static int minYear = std::min(msToYear(getCurrentUTCTime()), maximumYearForDST()-27) ;
return minYear;
}
/*
* Find a year for which any given date will fall on the same weekday.
* Find an equivalent year for the one given, where equivalence is deterined by
* the two years having the same leapness and the first day of the year, falling
* on the same day of the week.
*
* This function should be used with caution when used other than
* for determining DST; it hasn't been proven not to produce an
* incorrect year for times near year boundaries.
* This function returns a year between this current year and 2037, however this
* function will potentially return incorrect results if the current year is after
* 2010, (rdar://problem/5052975), if the year passed in is before 1900 or after
* 2100, (rdar://problem/5055038).
*/
int equivalentYearForDST(int year)
{
int difference = 2000 - year; // Arbitrary year around which most dates equivalence is correct
int quotient = difference / 28; // Integer division, no remainder.
int product = quotient * 28;
return year + product;
static int minYear = mimimumYearForDST();
static int maxYear = maximumYearForDST();
int difference;
if (year > maxYear)
difference = minYear - year;
else if (year < minYear)
difference = maxYear - year;
else
return year;
int quotient = difference / 28;
int product = (quotient) * 28;
year += product;
ASSERT((year >= minYear && year <= maxYear) || (product - year == static_cast<int>(NaN)));
return year;
}
/*
......@@ -376,11 +434,10 @@ static double getDSTOffset(double ms)
// standard explicitly dictates that historical information should not be considered when
// determining DST. For this reason we shift away from years that localtime can handle but would
// return historically accurate information.
// if before Jan 01, 2000 12:00:00 AM UTC or after Jan 01, 2038 12:00:00 AM UTC
if (ms < 946684800000.0 || ms > 2145916800000.0) {
int year = equivalentYearForDST(msToYear(ms));
int day = dateToDayInYear(year, msToMonth(ms), msToDayInMonth(ms));
int year = msToYear(ms);
int equvalentYear = equivalentYearForDST(year);
if (year != equvalentYear) {
int day = dateToDayInYear(equvalentYear, msToMonth(ms), msToDayInMonth(ms));
ms = (day * msPerDay) + msToMilliseconds(ms);
}
......
......@@ -53,6 +53,7 @@ void msToGregorianDateTime(double, bool outputIsUTC, GregorianDateTime&);
double gregorianDateTimeToMS(const GregorianDateTime&, double, bool inputIsUTC);
double getUTCOffset();
int equivalentYearForDST(int year);
double getCurrentUTCTime();
const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
......
......@@ -471,7 +471,7 @@ function DaylightSavingTA( t ) {
return UTC(dst_start + LocalTZA());
}
function GetSecondSundayInMarch( t ) {
function GetFirstSundayInApril( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
......@@ -486,7 +486,7 @@ function GetSecondSundayInMarch( t ) {
return first_sunday;
}
function GetFirstSundayInNovember( t ) {
function GetLastSundayInOctober( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
......@@ -500,6 +500,40 @@ function GetFirstSundayInNovember( t ) {
}
return last_sunday;
}
// Added these two functions because DST rules changed for the US.
function GetSecondSundayInMarch( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
var march = TimeFromYear(year) + TimeInMonth(0, leap) + TimeInMonth(1,leap);
var sundayCount = 0;
var flag = true;
for ( var second_sunday = march; flag; second_sunday += msPerDay )
{
if (WeekDay(second_sunday) == 0) {
if(++sundayCount == 2)
flag = false;
}
}
return second_sunday;
}
function GetFirstSundayInNovember( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
for ( var nov = TimeFromYear(year), m = 0; m < 10; m++ ) {
nov += TimeInMonth(m, leap);
}
for ( var first_sunday = nov; WeekDay(first_sunday) > 0;
first_sunday += msPerDay )
{
;
}
return first_sunday;
}
function LocalTime( t ) {
return ( t + LocalTZA() + DaylightSavingTA(t) );
}
......
......@@ -513,6 +513,38 @@ function DaylightSavingTA( t ) {
return UTC(dst_start + LocalTZA());
}
function GetFirstSundayInApril( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
var april = TimeFromYear(year) + TimeInMonth(0, leap) + TimeInMonth(1,leap) +
TimeInMonth(2,leap);
for ( var first_sunday = april; WeekDay(first_sunday) > 0;
first_sunday += msPerDay )
{
;
}
return first_sunday;
}
function GetLastSundayInOctober( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
for ( var oct = TimeFromYear(year), m = 0; m < 9; m++ ) {
oct += TimeInMonth(m, leap);
}
for ( var last_sunday = oct + 30*msPerDay; WeekDay(last_sunday) > 0;
last_sunday -= msPerDay )
{
;
}
return last_sunday;
}
// Added these two functions because DST rules changed for the US.
function GetSecondSundayInMarch( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
......@@ -535,7 +567,7 @@ function GetFirstSundayInNovember( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
for ( var nov = TimeFromYear(year), m = 0; m < 11; m++ ) {
for ( var nov = TimeFromYear(year), m = 0; m < 10; m++ ) {
nov += TimeInMonth(m, leap);
}
for ( var first_sunday = nov; WeekDay(first_sunday) > 0;
......
......@@ -431,7 +431,8 @@ function DaylightSavingTA( t ) {
return UTC(dst_start + LocalTZA());
}
function GetSecondSundayInMarch( t ) {
function GetFirstSundayInApril( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
......@@ -446,7 +447,7 @@ function GetSecondSundayInMarch( t ) {
return first_sunday;
}
function GetFirstSundayInNovember( t ) {
function GetLastSundayInOctober( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
......@@ -460,6 +461,40 @@ function GetFirstSundayInNovember( t ) {
}
return last_sunday;
}
// Added these two functions because DST rules changed for the US.
function GetSecondSundayInMarch( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
var march = TimeFromYear(year) + TimeInMonth(0, leap) + TimeInMonth(1,leap);
var sundayCount = 0;
var flag = true;
for ( var second_sunday = march; flag; second_sunday += msPerDay )
{
if (WeekDay(second_sunday) == 0) {
if(++sundayCount == 2)
flag = false;
}
}
return second_sunday;
}
function GetFirstSundayInNovember( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
for ( var nov = TimeFromYear(year), m = 0; m < 10; m++ ) {
nov += TimeInMonth(m, leap);
}
for ( var first_sunday = nov; WeekDay(first_sunday) > 0;
first_sunday += msPerDay )
{
;
}
return first_sunday;
}
function LocalTime( t ) {
return ( t + LocalTZA() + DaylightSavingTA(t) );
}
......
......@@ -457,39 +457,68 @@ print( new Date( UTC(dst_start + LocalTZA())) );
return UTC(dst_start + LocalTZA());
}
function GetFirstSundayInApril( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
function GetSecondSundayInMarch( t )
{
var year = YearFromTime(t);
var leap = InLeapYear(t);
var april = TimeFromYear(year) + TimeInMonth(0, leap) + TimeInMonth(1,leap) + TimeInMonth(2,leap);
var april = TimeFromYear(year) + TimeInMonth(0, leap) + TimeInMonth(1,leap) +
TimeInMonth(2,leap);
for ( var first_sunday = april; WeekDay(first_sunday) > 0; first_sunday += msPerDay )
{
;
}
for ( var first_sunday = april; WeekDay(first_sunday) > 0;
first_sunday += msPerDay )
{
;
}
return first_sunday;
return first_sunday;
}
function GetLastSundayInOctober( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
function GetFirstSundayInNovember( t )
{
var year = YearFromTime(t);
var leap = InLeapYear(t);
for ( var oct = TimeFromYear(year), m =0; m < 9; m++ )
{
oct += TimeInMonth(m, leap);
}
for ( var last_sunday = oct + 30*msPerDay; WeekDay(last_sunday) > 0; last_sunday -= msPerDay )
{
;
}
return last_sunday;
for ( var oct = TimeFromYear(year), m = 0; m < 9; m++ ) {
oct += TimeInMonth(m, leap);
}
for ( var last_sunday = oct + 30*msPerDay; WeekDay(last_sunday) > 0;
last_sunday -= msPerDay )
{
;
}
return last_sunday;
}
// Added these two functions because DST rules changed for the US.
function GetSecondSundayInMarch( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
var march = TimeFromYear(year) + TimeInMonth(0, leap) + TimeInMonth(1,leap);
var sundayCount = 0;
var flag = true;
for ( var second_sunday = march; flag; second_sunday += msPerDay )
{
if (WeekDay(second_sunday) == 0) {
if(++sundayCount == 2)
flag = false;
}
}
return second_sunday;
}
function GetFirstSundayInNovember( t ) {
var year = YearFromTime(t);
var leap = InLeapYear(t);
for ( var nov = TimeFromYear(year), m = 0; m < 10; m++ ) {
nov += TimeInMonth(m, leap);
}
for ( var first_sunday = nov; WeekDay(first_sunday) > 0;
first_sunday += msPerDay )
{
;
}
return first_sunday;
}
......
This diff is collapsed.
2007-03-14 Kevin McCullough <kmccullough@apple.com>
Reviewed by Geoff.
- rdar://problem/5045720
- DST changes in US affect JavaScript date calculations (12975)
Changed layout tests to properly check for the new changes to DST in the
US. Also these now test that equivalent years return the same results for DST.
* fast/js/date-DST-time-cusps-expected.txt:
* fast/js/date-big-setdate-expected.txt:
* fast/js/resources/date-DST-time-cusps.js:
* fast/js/resources/date-big-setdate.js:
t: 2007-03-15 Mitz Pettel <mitz@webkit.org>
 
Reviewed by Hyatt.
......@@ -3,10 +3,10 @@ For times that happen twice the behavior of all major browsers seems to be to pi
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS (new Date(1982, 3, 25, 2, 10)).getHours() is 1
PASS (new Date(1982,3,25,2)).getHours() is 1
PASS (new Date(1982, 9, 31, 1, 10)).getTimezoneOffset() is 480
PASS (new Date(1982, 9, 31, 1)).getTimezoneOffset() is 480
PASS (new Date(1982, 2, 14, 2, 10)).getHours() is 1
PASS (new Date(1982, 2, 14, 2)).getHours() is 1
PASS (new Date(1982, 11, 7, 1, 10)).getTimezoneOffset() is 480
PASS (new Date(1982, 11, 7, 1)).getTimezoneOffset() is 480
PASS successfullyParsed is true
TEST COMPLETE
......
This test checks for regression against: 3381 Date.prototype.setDate() incorrect for values >=128.
This test checks for regression against: 3381 Date.prototype.setDate() incorrect for values >=128.
12975: DST changes in US affect JavaScript date calculations
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
......@@ -13,6 +14,10 @@ PASS d.valueOf() - curValue is millisecondsPerDay
PASS d.valueOf() - curValue is millisecondsPerDay
PASS d.valueOf() - curValue is millisecondsPerDay
PASS d.valueOf() - c.valueOf() is millisecondsPerDay - millisecondsPerHour
PASS d.valueOf() - c.valueOf() is millisecondsPerDay - millisecondsPerHour
PASS d.valueOf() - c.valueOf() is millisecondsPerDay - millisecondsPerHour
PASS d.valueOf() - c.valueOf() is millisecondsPerDay - millisecondsPerHour
PASS d.valueOf() - c.valueOf() is millisecondsPerDay - millisecondsPerHour
PASS successfullyParsed is true
TEST COMPLETE
......
......@@ -10,9 +10,10 @@ description(
"For times that happen twice the behavior of all major browsers seems to be to pick the second occurance, i.e. Standard Time not Daylight Time"
);
shouldBe("(new Date(1982, 3, 25, 2, 10)).getHours()", "1");
shouldBe("(new Date(1982,3,25,2)).getHours()", "1");
shouldBe("(new Date(1982, 9, 31, 1, 10)).getTimezoneOffset()", "480");
shouldBe("(new Date(1982, 9, 31, 1)).getTimezoneOffset()", "480");
shouldBe("(new Date(1982, 2, 14, 2, 10)).getHours()", "1");
shouldBe("(new Date(1982, 2, 14, 2)).getHours()", "1");
shouldBe("(new Date(1982, 11, 7, 1, 10)).getTimezoneOffset()", "480");
shouldBe("(new Date(1982, 11, 7, 1)).getTimezoneOffset()", "480");
var successfullyParsed = true;
var successfullyParsed = true;
\ No newline at end of file
description(
'This test checks for regression against: <a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=3381"> 3381 Date.prototype.setDate() incorrect for values >=128.</a>'
'This test checks for regression against: <a href="http://bugs.webkit.org/show_bug.cgi?id=3381"> 3381 Date.prototype.setDate() incorrect for values >=128.</a> <br /> <a href="http://bugs.webkit.org/show_bug.cgi?id=12975">12975: DST changes in US affect JavaScript date calculations</a>'
);
......@@ -26,8 +26,36 @@ for (var i = 116; i < 126; i++) {
var c = new Date(0);
var d = new Date(0);
c.setDate(125);
d.setDate(126);
c.setDate(97);
d.setDate(98);
shouldBe("d.valueOf() - c.valueOf()", "millisecondsPerDay - millisecondsPerHour");
// Added more special cases. These dates match the recent DST changes in the US.
// These tests check that the new changes are correctly propogated to the past and
// all of the tests should show DST occurring on the same date.
var c = new Date(1970, 0,0,0,0,0,0);
var d = new Date(1970, 0,0,0,0,0,0);
c.setDate(98);
d.setDate(99);
shouldBe("d.valueOf() - c.valueOf()", "millisecondsPerDay - millisecondsPerHour");
var c = new Date(1998, 0,0,0,0,0,0);
var d = new Date(1998, 0,0,0,0,0,0);
c.setDate(98);
d.setDate(99);
shouldBe("d.valueOf() - c.valueOf()", "millisecondsPerDay - millisecondsPerHour");
var c = new Date(2026, 0,0,0,0,0,0);
var d = new Date(2026, 0,0,0,0,0,0);
c.setDate(98);
d.setDate(99);
shouldBe("d.valueOf() - c.valueOf()", "millisecondsPerDay - millisecondsPerHour");
var c = new Date(2054, 0,0,0,0,0,0);
var d = new Date(2054, 0,0,0,0,0,0);
c.setDate(98);
d.setDate(99);
shouldBe("d.valueOf() - c.valueOf()", "millisecondsPerDay - millisecondsPerHour");
var successfullyParsed = true;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment