Browse Source

Merge branch 'date-localtime-tzoffset-fix'

v1.0-maintenance
Sami Vaarala 10 years ago
parent
commit
a5bb642ae5
  1. 3
      RELEASES.txt
  2. 72
      ecmascript-testcases/test-bi-date-local-parts-fi.js
  3. 137
      ecmascript-testcases/test-bi-date-tzoffset-basic-fi.js
  4. 282
      ecmascript-testcases/test-bi-date-tzoffset-brute-fi.js
  5. 209
      src/duk_bi_date.c
  6. 82
      src/genbuiltins.py

3
RELEASES.txt

@ -473,6 +473,9 @@ Planned
* Use gmtime() + localtime() on Unix (instead of gmtime() twice) for local
tzoffset, fixing some DST cases
* Improve parsing of a local time (new Date(2012, 1, 2, 3, 4, 5)) using an
iterative algorithm to get a more accurate tzoffset/DST estimate
* Minor compile warnings fixes for non-default options (e.g. when reference
counting is disabled)

72
ecmascript-testcases/test-bi-date-local-parts-fi.js

@ -0,0 +1,72 @@
/*
* When parsing a timestamp from local time parts (year, month, etc) the
* implementation needs to figure out the UTC time corresponding to the
* local parts and then convert the UTC time to an Ecmascript time value.
*
* The concrete conversion algorithm tries to figure out the UTC-to-local
* offset so that it can be taken into account in the Ecmascript time value.
* There's a practical problem in this conversion: DUK__GET_LOCAL_TZOFFSET()
* provides a UTC-to-local-time offset for an input time value which is
* essentially a *UTC* timestamp. However, we don't know the UTC time yet
* (we're trying to compute it).
*
* The current solution in Duktape's duk_bi_date.c is to compute an
* approximate time value by treating the local parts like UTC parts,
* yielding a time value that is off by 12 hours maximum. The local time
* offset is computed for this approximate timestamp and the offset is
* then applied to arrive at an approximation of the UTC time which is at
* most 1 hour off. This process is repeated a few times until the time
* offset no longer changes.
*/
// Test is custom because of custom local time formatting
/*---
{
"specialoptions": "test case has been written for Finnish locale",
"custom": true
}
---*/
/*===
finnish locale test
1396141199000 2014-03-30T00:59:59.000Z 2014-03-30 02:59:59.000+02:00
1396141199000 2014-03-30T00:59:59.000Z 2014-03-30 02:59:59.000+02:00
1396141200000 2014-03-30T01:00:00.000Z 2014-03-30 04:00:00.000+03:00
1414281599000 2014-10-25T23:59:59.000Z 2014-10-26 02:59:59.000+03:00
1414285200000 2014-10-26T01:00:00.000Z 2014-10-26 03:00:00.000+02:00
===*/
function finnishLocaleTest() {
var d;
// 2014-03-30 02:59:59 Finnish time is still EET (GMT+0200)
d = new Date(2014, 2, 30, 2, 59, 59);
print(d.getTime(), d.toISOString(), d.toString());
// 2014-03-30 03:59:59 Finnish time never normally occurs (one steps
// from the non-DST 02:59:59 to the DST 04:00:00). This case thus
// has an ambiguous result, but we now test for behavior matching
// V8 and Rhino.
d = new Date(2014, 2, 30, 3, 59, 59);
print(d.getTime(), d.toISOString(), d.toString());
// 2014-03-30 04:00:00 Finnish time is EEST (GMT+0300)
d = new Date(2014, 2, 30, 4, 0, 0);
print(d.getTime(), d.toISOString(), d.toString());
// 2014-10-26 02:59:59 Finnish time is still EEST (GMT+0300)
d = new Date(2014, 9, 26, 2, 59, 59);
print(d.getTime(), d.toISOString(), d.toString());
// 2014-10-26 03:00:00 Finnish time is EET (GMT+0200)
d = new Date(2014, 9, 26, 3, 0, 0);
print(d.getTime(), d.toISOString(), d.toString());
}
print('finnish locale test');
try {
finnishLocaleTest();
} catch (e) {
print(e);
}

137
ecmascript-testcases/test-bi-date-tzoffset-basic-fi.js

@ -0,0 +1,137 @@
/*
* Minimal tzoffset test for Finnish locale.
*/
// Custom test because of locale specific timestamp outputs
/*---
{
"specialoptions": "test case has been written for Finnish locale",
"custom": true
}
---*/
/*===
tzo for current time is correct
1325368800000 2011-12-31T22:00:00.000Z 2012-01-01 00:00:00.000+02:00 -120
1343768400000 2012-07-31T21:00:00.000Z 2012-08-01 00:00:00.000+03:00 -180
1396141199000 2014-03-30T00:59:59.000Z 2014-03-30 02:59:59.000+02:00 -120
1396141200000 2014-03-30T01:00:00.000Z 2014-03-30 04:00:00.000+03:00 -180
1396141199000 2014-03-30T00:59:59.000Z 2014-03-30 02:59:59.000+02:00 -120
1396141200000 2014-03-30T01:00:00.000Z 2014-03-30 04:00:00.000+03:00 -180
1414281599000 2014-10-25T23:59:59.000Z 2014-10-26 02:59:59.000+03:00 -180
1414285200000 2014-10-26T01:00:00.000Z 2014-10-26 03:00:00.000+02:00 -120
===*/
/*
Rhino:
tzo for current time is correct
1325368800000 2011-12-31T22:00:00.000Z Sun Jan 01 2012 00:00:00 GMT+0200 (EET) -120
1343768400000 2012-07-31T21:00:00.000Z Wed Aug 01 2012 00:00:00 GMT+0300 (EEST) -180
1396141199000 2014-03-30T00:59:59.000Z Sun Mar 30 2014 02:59:59 GMT+0200 (EET) -120
1396141200000 2014-03-30T01:00:00.000Z Sun Mar 30 2014 04:00:00 GMT+0300 (EEST) -180
1396141199000 2014-03-30T00:59:59.000Z Sun Mar 30 2014 02:59:59 GMT+0200 (EET) -120
1396141200000 2014-03-30T01:00:00.000Z Sun Mar 30 2014 04:00:00 GMT+0300 (EEST) -180
1414281599000 2014-10-25T23:59:59.000Z Sun Oct 26 2014 02:59:59 GMT+0300 (EEST) -180
1414285200000 2014-10-26T01:00:00.000Z Sun Oct 26 2014 03:00:00 GMT+0200 (EET) -120
*/
/*
V8:
tzo for current time is correct
1325368800000 2011-12-31T22:00:00.000Z Sun Jan 01 2012 00:00:00 GMT+0200 (EET) -120
1343768400000 2012-07-31T21:00:00.000Z Wed Aug 01 2012 00:00:00 GMT+0300 (EEST) -180
1396141199000 2014-03-30T00:59:59.000Z Sun Mar 30 2014 02:59:59 GMT+0200 (EET) -120
1396141200000 2014-03-30T01:00:00.000Z Sun Mar 30 2014 04:00:00 GMT+0300 (EEST) -180
1396141199000 2014-03-30T00:59:59.000Z Sun Mar 30 2014 02:59:59 GMT+0200 (EET) -120
1396141200000 2014-03-30T01:00:00.000Z Sun Mar 30 2014 04:00:00 GMT+0300 (EEST) -180
1414281599000 2014-10-25T23:59:59.000Z Sun Oct 26 2014 02:59:59 GMT+0300 (EEST) -180
1414285200000 2014-10-26T01:00:00.000Z Sun Oct 26 2014 03:00:00 GMT+0200 (EET) -120
*/
function finnishTzoffsetBasicTest() {
var d, tzo;
function dump(d) {
print(d.getTime(), d.toISOString(), d.toString(), d.getTimezoneOffset());
}
// Current timezone offset is +02:00 or +03:00
d = new Date();
tzo = d.getTimezoneOffset();
if (tzo == -120 || tzo == -180) {
print('tzo for current time is correct');
} else {
print('tzo for current time is incorrect: ' + tzo);
}
// Jan 1 timezone offset is +02:00
d = new Date(2012, 0, 1, 0, 0, 0);
dump(d);
// Aug 1 timezone offset is +03:00
d = new Date(2012, 7, 1, 0, 0, 0);
dump(d);
// 2014-03-30 02:59:59 Finnish time is still EET (GMT+0200)
d = new Date(2014, 2, 30, 2, 59, 59);
dump(d);
d = new Date(d.getTime() + 1000);
dump(d);
// 2014-03-30 03:NN:NN Finnish time doesn't really exist, as one
// jumps from 02:59:59 (no DST) to 04:00:00 (DST) in local time:
//
// > d = new Date(Date.parse('2014-03-30T00:59:59.000Z'))
// Sun Mar 30 2014 02:59:59 GMT+0200 (EET)
// > d = new Date(d.getTime() + 1000)
// Sun Mar 30 2014 04:00:00 GMT+0300 (EEST)
//
// So, resolving times of the form 03:NN:NN is ambiguous. Rhino
// and V8 seem to favor the earlier time instant (at least in this
// case):
//
// > d = new Date(2014, 2, 30, 3, 59, 59);
// Sun Mar 30 2014 02:59:59 GMT+0200 (EET)
// > d.getTime()
// 1396141199000
//
// Duktape used to iterate for the tzoffset without arriving at a
// conclusive result, like this:
//
// [D] duk_bi_date.c:1209 (duk__get_timeval_from_dparts): tzoffset iteration, i=0, tzoff=0, tzoffnew=10800
// [D] duk_bi_date.c:1209 (duk__get_timeval_from_dparts): tzoffset iteration, i=1, tzoff=10800, tzoffnew=7200
// [D] duk_bi_date.c:1209 (duk__get_timeval_from_dparts): tzoffset iteration, i=2, tzoff=7200, tzoffnew=10800
// [D] duk_bi_date.c:1209 (duk__get_timeval_from_dparts): tzoffset iteration, i=3, tzoff=10800, tzoffnew=7200
// [D] duk_bi_date.c:1216 (duk__get_timeval_from_dparts): tzoffset iteration, tzoff=7200
//
// This was changed to favor a higher value in a two-value loop so that
// 10800 gets selected and behavior matches Rhino/V8, at least in this
// instance. Not sure if this is generically correct:
//
// [D] duk_bi_date.c:1214 (duk__get_timeval_from_dparts): tzoffset iteration, i=0, tzoff=10800, tzoffprev1=0 tzoffprev2=999999999
// [D] duk_bi_date.c:1214 (duk__get_timeval_from_dparts): tzoffset iteration, i=1, tzoff=7200, tzoffprev1=10800 tzoffprev2=0
// [D] duk_bi_date.c:1214 (duk__get_timeval_from_dparts): tzoffset iteration, i=2, tzoff=10800, tzoffprev1=7200 tzoffprev2=10800
// [D] duk_bi_date.c:1226 (duk__get_timeval_from_dparts): tzoffset iteration two-value cycle, i=2, tzoff=10800, tzoffprev1=7200, tzoffprev2=10800
// [D] duk_bi_date.c:1233 (duk__get_timeval_from_dparts): tzoffset iteration, tzoff=10800
d = new Date(2014, 2, 30, 3, 59, 59);
dump(d);
// 2014-03-30 04:00:00 Finnish time is EEST (GMT+0300)
d = new Date(2014, 2, 30, 4, 0, 0);
dump(d);
// 2014-10-26 02:59:59 Finnish time is still EEST (GMT+0300)
d = new Date(2014, 9, 26, 2, 59, 59);
dump(d);
// 2014-10-26 03:00:00 Finnish time is EET (GMT+0200)
d = new Date(2014, 9, 26, 3, 0, 0);
dump(d);
}
try {
finnishTzoffsetBasicTest();
} catch (e) {
print(e);
}

282
ecmascript-testcases/test-bi-date-tzoffset-brute-fi.js

@ -0,0 +1,282 @@
/*
* Brute force tzoffset test for Finnish locale.
*
* Right now (2014-08-09) the only discrepancy to V8 is the year 1970.
* That discrepancy is caused by Duktape using an equivalent year for
* the year 1970. If that behavior is removed, the test should pass
* with no diff.
*/
/*---
{
"specialoptions": "test case has been written for Finnish locale",
"knownissue": "year 1970 deviates from expected, Duktape uses equiv. year for 1970 on purpose at the moment"
}
---*/
/*===
finnish tzoffset/dst brute force test
1900 -> 1993:-120 5208:-180 1559:-120
1901 -> 2137:-120 5040:-180 1583:-120
1902 -> 2113:-120 5040:-180 1607:-120
1903 -> 2089:-120 5040:-180 1631:-120
1904 -> 2065:-120 5208:-180 1511:-120
1905 -> 2017:-120 5208:-180 1535:-120
1906 -> 1993:-120 5208:-180 1559:-120
1907 -> 2137:-120 5040:-180 1583:-120
1908 -> 2113:-120 5040:-180 1631:-120
1909 -> 2065:-120 5208:-180 1487:-120
1910 -> 2041:-120 5208:-180 1511:-120
1911 -> 2017:-120 5208:-180 1535:-120
1912 -> 2161:-120 5040:-180 1583:-120
1913 -> 2113:-120 5040:-180 1607:-120
1914 -> 2089:-120 5040:-180 1631:-120
1915 -> 2065:-120 5208:-180 1487:-120
1916 -> 2041:-120 5208:-180 1535:-120
1917 -> 1993:-120 5208:-180 1559:-120
1918 -> 2137:-120 5040:-180 1583:-120
1919 -> 2113:-120 5040:-180 1607:-120
1920 -> 2089:-120 5208:-180 1487:-120
1921 -> 2041:-120 5208:-180 1511:-120
1922 -> 2017:-120 5208:-180 1535:-120
1923 -> 1993:-120 5208:-180 1559:-120
1924 -> 2137:-120 5040:-180 1607:-120
1925 -> 2089:-120 5040:-180 1631:-120
1926 -> 2065:-120 5208:-180 1487:-120
1927 -> 2041:-120 5208:-180 1511:-120
1928 -> 2017:-120 5208:-180 1559:-120
1929 -> 2137:-120 5040:-180 1583:-120
1930 -> 2113:-120 5040:-180 1607:-120
1931 -> 2089:-120 5040:-180 1631:-120
1932 -> 2065:-120 5208:-180 1511:-120
1933 -> 2017:-120 5208:-180 1535:-120
1934 -> 1993:-120 5208:-180 1559:-120
1935 -> 2137:-120 5040:-180 1583:-120
1936 -> 2113:-120 5040:-180 1631:-120
1937 -> 2065:-120 5208:-180 1487:-120
1938 -> 2041:-120 5208:-180 1511:-120
1939 -> 2017:-120 5208:-180 1535:-120
1940 -> 2161:-120 5040:-180 1583:-120
1941 -> 2113:-120 5040:-180 1607:-120
1942 -> 2089:-120 5040:-180 1631:-120
1943 -> 2065:-120 5208:-180 1487:-120
1944 -> 2041:-120 5208:-180 1535:-120
1945 -> 1993:-120 5208:-180 1559:-120
1946 -> 2137:-120 5040:-180 1583:-120
1947 -> 2113:-120 5040:-180 1607:-120
1948 -> 2089:-120 5208:-180 1487:-120
1949 -> 2041:-120 5208:-180 1511:-120
1950 -> 2017:-120 5208:-180 1535:-120
1951 -> 1993:-120 5208:-180 1559:-120
1952 -> 2137:-120 5040:-180 1607:-120
1953 -> 2089:-120 5040:-180 1631:-120
1954 -> 2065:-120 5208:-180 1487:-120
1955 -> 2041:-120 5208:-180 1511:-120
1956 -> 2017:-120 5208:-180 1559:-120
1957 -> 2137:-120 5040:-180 1583:-120
1958 -> 2113:-120 5040:-180 1607:-120
1959 -> 2089:-120 5040:-180 1631:-120
1960 -> 2065:-120 5208:-180 1511:-120
1961 -> 2017:-120 5208:-180 1535:-120
1962 -> 1993:-120 5208:-180 1559:-120
1963 -> 2137:-120 5040:-180 1583:-120
1964 -> 2113:-120 5040:-180 1631:-120
1965 -> 2065:-120 5208:-180 1487:-120
1966 -> 2041:-120 5208:-180 1511:-120
1967 -> 2017:-120 5208:-180 1535:-120
1968 -> 2161:-120 5040:-180 1583:-120
1969 -> 2113:-120 5040:-180 1607:-120
1970 -> 8760:-120
1971 -> 8760:-120
1972 -> 8784:-120
1973 -> 8760:-120
1974 -> 8760:-120
1975 -> 8760:-120
1976 -> 8784:-120
1977 -> 8760:-120
1978 -> 8760:-120
1979 -> 8760:-120
1980 -> 8784:-120
1981 -> 2088:-120 4368:-180 2304:-120
1982 -> 2064:-120 4368:-180 2328:-120
1983 -> 2041:-120 4368:-180 2351:-120
1984 -> 2017:-120 4536:-180 2231:-120
1985 -> 2137:-120 4368:-180 2255:-120
1986 -> 2113:-120 4368:-180 2279:-120
1987 -> 2089:-120 4368:-180 2303:-120
1988 -> 2065:-120 4368:-180 2351:-120
1989 -> 2017:-120 4368:-180 2375:-120
1990 -> 1993:-120 4536:-180 2231:-120
1991 -> 2137:-120 4368:-180 2255:-120
1992 -> 2113:-120 4368:-180 2303:-120
1993 -> 2065:-120 4368:-180 2327:-120
1994 -> 2041:-120 4368:-180 2351:-120
1995 -> 2017:-120 4368:-180 2375:-120
1996 -> 2161:-120 5040:-180 1583:-120
1997 -> 2113:-120 5040:-180 1607:-120
1998 -> 2089:-120 5040:-180 1631:-120
1999 -> 2065:-120 5208:-180 1487:-120
2000 -> 2041:-120 5208:-180 1535:-120
2001 -> 1993:-120 5208:-180 1559:-120
2002 -> 2137:-120 5040:-180 1583:-120
2003 -> 2113:-120 5040:-180 1607:-120
2004 -> 2089:-120 5208:-180 1487:-120
2005 -> 2041:-120 5208:-180 1511:-120
2006 -> 2017:-120 5208:-180 1535:-120
2007 -> 1993:-120 5208:-180 1559:-120
2008 -> 2137:-120 5040:-180 1607:-120
2009 -> 2089:-120 5040:-180 1631:-120
2010 -> 2065:-120 5208:-180 1487:-120
2011 -> 2041:-120 5208:-180 1511:-120
2012 -> 2017:-120 5208:-180 1559:-120
2013 -> 2137:-120 5040:-180 1583:-120
2014 -> 2113:-120 5040:-180 1607:-120
2015 -> 2089:-120 5040:-180 1631:-120
2016 -> 2065:-120 5208:-180 1511:-120
2017 -> 2017:-120 5208:-180 1535:-120
2018 -> 1993:-120 5208:-180 1559:-120
2019 -> 2137:-120 5040:-180 1583:-120
2020 -> 2113:-120 5040:-180 1631:-120
2021 -> 2065:-120 5208:-180 1487:-120
2022 -> 2041:-120 5208:-180 1511:-120
2023 -> 2017:-120 5208:-180 1535:-120
2024 -> 2161:-120 5040:-180 1583:-120
2025 -> 2113:-120 5040:-180 1607:-120
2026 -> 2089:-120 5040:-180 1631:-120
2027 -> 2065:-120 5208:-180 1487:-120
2028 -> 2041:-120 5208:-180 1535:-120
2029 -> 1993:-120 5208:-180 1559:-120
2030 -> 2137:-120 5040:-180 1583:-120
2031 -> 2113:-120 5040:-180 1607:-120
2032 -> 2089:-120 5208:-180 1487:-120
2033 -> 2041:-120 5208:-180 1511:-120
2034 -> 2017:-120 5208:-180 1535:-120
2035 -> 1993:-120 5208:-180 1559:-120
2036 -> 2137:-120 5040:-180 1607:-120
2037 -> 2089:-120 5040:-180 1631:-120
2038 -> 2065:-120 5208:-180 1487:-120
2039 -> 2041:-120 5208:-180 1511:-120
2040 -> 2017:-120 5208:-180 1559:-120
2041 -> 2137:-120 5040:-180 1583:-120
2042 -> 2113:-120 5040:-180 1607:-120
2043 -> 2089:-120 5040:-180 1631:-120
2044 -> 2065:-120 5208:-180 1511:-120
2045 -> 2017:-120 5208:-180 1535:-120
2046 -> 1993:-120 5208:-180 1559:-120
2047 -> 2137:-120 5040:-180 1583:-120
2048 -> 2113:-120 5040:-180 1631:-120
2049 -> 2065:-120 5208:-180 1487:-120
2050 -> 2041:-120 5208:-180 1511:-120
2051 -> 2017:-120 5208:-180 1535:-120
2052 -> 2161:-120 5040:-180 1583:-120
2053 -> 2113:-120 5040:-180 1607:-120
2054 -> 2089:-120 5040:-180 1631:-120
2055 -> 2065:-120 5208:-180 1487:-120
2056 -> 2041:-120 5208:-180 1535:-120
2057 -> 1993:-120 5208:-180 1559:-120
2058 -> 2137:-120 5040:-180 1583:-120
2059 -> 2113:-120 5040:-180 1607:-120
2060 -> 2089:-120 5208:-180 1487:-120
2061 -> 2041:-120 5208:-180 1511:-120
2062 -> 2017:-120 5208:-180 1535:-120
2063 -> 1993:-120 5208:-180 1559:-120
2064 -> 2137:-120 5040:-180 1607:-120
2065 -> 2089:-120 5040:-180 1631:-120
2066 -> 2065:-120 5208:-180 1487:-120
2067 -> 2041:-120 5208:-180 1511:-120
2068 -> 2017:-120 5208:-180 1559:-120
2069 -> 2137:-120 5040:-180 1583:-120
2070 -> 2113:-120 5040:-180 1607:-120
2071 -> 2089:-120 5040:-180 1631:-120
2072 -> 2065:-120 5208:-180 1511:-120
2073 -> 2017:-120 5208:-180 1535:-120
2074 -> 1993:-120 5208:-180 1559:-120
2075 -> 2137:-120 5040:-180 1583:-120
2076 -> 2113:-120 5040:-180 1631:-120
2077 -> 2065:-120 5208:-180 1487:-120
2078 -> 2041:-120 5208:-180 1511:-120
2079 -> 2017:-120 5208:-180 1535:-120
2080 -> 2161:-120 5040:-180 1583:-120
2081 -> 2113:-120 5040:-180 1607:-120
2082 -> 2089:-120 5040:-180 1631:-120
2083 -> 2065:-120 5208:-180 1487:-120
2084 -> 2041:-120 5208:-180 1535:-120
2085 -> 1993:-120 5208:-180 1559:-120
2086 -> 2137:-120 5040:-180 1583:-120
2087 -> 2113:-120 5040:-180 1607:-120
2088 -> 2089:-120 5208:-180 1487:-120
2089 -> 2041:-120 5208:-180 1511:-120
2090 -> 2017:-120 5208:-180 1535:-120
2091 -> 1993:-120 5208:-180 1559:-120
2092 -> 2137:-120 5040:-180 1607:-120
2093 -> 2089:-120 5040:-180 1631:-120
2094 -> 2065:-120 5208:-180 1487:-120
2095 -> 2041:-120 5208:-180 1511:-120
2096 -> 2017:-120 5208:-180 1559:-120
2097 -> 2137:-120 5040:-180 1583:-120
2098 -> 2113:-120 5040:-180 1607:-120
2099 -> 2089:-120 5040:-180 1631:-120
2100 -> 2065:-120 5208:-180 1487:-120
===*/
function summarizeOffsets(offsets) {
var res = [];
var i, n;
var curroff, currlen;
for (i = 0, n = offsets.length; i < n; i++) {
if (curroff !== offsets[i]) {
if (currlen > 0) {
res.push(currlen + ':' + curroff);
}
curroff = offsets[i];
currlen = 1;
} else {
currlen++;
}
}
if (currlen > 0) {
res.push(currlen + ':' + curroff);
}
return res.join(' ');
}
function finnishTzoffsetTest() {
var offsets;
var timeval_start, timeval_end, timeval, timeval_step;
var year_start, year_curr;
var d;
// Start from Jan 1, 1900, 00:00:00 UTC
timeval_start = -2208988800000;
// End at Jan 1, 2101, 00:00:00 UTC
timeval_end = 4133980800000;
// 60 minute steps
timeval_step = 60 * 60 * 1000;
timeval = timeval_start;
while (timeval < timeval_end) {
year_start = new Date(timeval).getUTCFullYear();
offsets = [];
while (true) {
d = new Date(timeval);
year_curr = d.getUTCFullYear();
if (year_curr != year_start) {
break;
}
offsets.push(d.getTimezoneOffset());
timeval += timeval_step;
}
print(year_start + ' -> ' + summarizeOffsets(offsets));
}
}
print('finnish tzoffset/dst brute force test');
try {
finnishTzoffsetTest();
} catch (e) {
print(e);
}

209
src/duk_bi_date.c

@ -82,14 +82,16 @@ static duk_bool_t duk__is_leap_year(duk_int_t year);
#define DUK__FLAG_NAN_TO_ZERO (1 << 0) /* timeval breakdown: internal time value NaN -> zero */
#define DUK__FLAG_NAN_TO_RANGE_ERROR (1 << 1) /* timeval breakdown: internal time value NaN -> RangeError (toISOString) */
#define DUK__FLAG_ONEBASED (1 << 2) /* timeval breakdown: convert month and day-of-month parts to one-based (default is zero-based) */
#define DUK__FLAG_LOCALTIME (1 << 3) /* convert time value to local time */
#define DUK__FLAG_SUB1900 (1 << 4) /* getter: subtract 1900 from year when getting year part */
#define DUK__FLAG_TOSTRING_DATE (1 << 5) /* include date part in string conversion result */
#define DUK__FLAG_TOSTRING_TIME (1 << 6) /* include time part in string conversion result */
#define DUK__FLAG_TOSTRING_LOCALE (1 << 7) /* use locale specific formatting if available */
#define DUK__FLAG_TIMESETTER (1 << 8) /* setter: call is a time setter (affects hour, min, sec, ms); otherwise date setter (affects year, month, day-in-month) */
#define DUK__FLAG_YEAR_FIXUP (1 << 9) /* setter: perform 2-digit year fixup (00...99 -> 1900...1999) */
#define DUK__FLAG_SEP_T (1 << 10) /* string conversion: use 'T' instead of ' ' as a separator */
#define DUK__FLAG_EQUIVYEAR (1 << 3) /* timeval breakdown: replace year with equivalent year in the [1971,2037] range for DST calculations */
#define DUK__FLAG_LOCALTIME (1 << 4) /* convert time value to local time */
#define DUK__FLAG_SUB1900 (1 << 5) /* getter: subtract 1900 from year when getting year part */
#define DUK__FLAG_TOSTRING_DATE (1 << 6) /* include date part in string conversion result */
#define DUK__FLAG_TOSTRING_TIME (1 << 7) /* include time part in string conversion result */
#define DUK__FLAG_TOSTRING_LOCALE (1 << 8) /* use locale specific formatting if available */
#define DUK__FLAG_TIMESETTER (1 << 9) /* setter: call is a time setter (affects hour, min, sec, ms); otherwise date setter (affects year, month, day-in-month) */
#define DUK__FLAG_YEAR_FIXUP (1 << 10) /* setter: perform 2-digit year fixup (00...99 -> 1900...1999) */
#define DUK__FLAG_SEP_T (1 << 11) /* string conversion: use 'T' instead of ' ' as a separator */
#define DUK__FLAG_VALUE_SHIFT 12 /* additional values begin at bit 12 */
/*
* Platform specific helpers
@ -174,9 +176,6 @@ static duk_int_t duk__get_local_tzoffset(duk_double_t d) {
time_t t, t1, t2;
duk_int_t parts[DUK__NUM_PARTS];
duk_double_t dparts[DUK__NUM_PARTS];
duk_int_t tmp;
duk_bool_t isleap;
duk_small_int_t arridx;
struct tm tms[2];
#ifdef DUK_USE_DATE_TZO_GMTIME
struct tm *tm_ptr;
@ -195,10 +194,10 @@ static duk_int_t duk__get_local_tzoffset(duk_double_t d) {
*
* Current approach:
*
* - Clamp year to stay within portable UNIX limits. Avoid 2038 as
* some conversions start to fail. Avoid 1970, as some conversions
* in January 1970 start to fail (verified in practice). For dates
* before and after these limits, use an equivalent year mapping.
* - Stay within portable UNIX limits by using equivalent year mapping.
* Avoid year 1970 and 2038 as some conversions start to fail, at
* least on some platforms. Avoiding 1970 means that there are
* currently DST discrepancies for 1970.
*
* - Create a UTC and local time breakdowns from 't'. Then create
* a time_t using gmtime() and localtime() and compute the time
@ -237,30 +236,8 @@ static duk_int_t duk__get_local_tzoffset(duk_double_t d) {
* https://bugzilla.mozilla.org/show_bug.cgi?id=351066
*/
duk__timeval_to_parts(d, parts, dparts, 0 /*flags*/);
#if 0 /* clamping approach */
tmp = parts[DUK__IDX_YEAR];
if (tmp < 1971) {
dparts[DUK__IDX_YEAR] = 1971.0;
} else if (tmp > 2037) {
dparts[DUK__IDX_YEAR] = 2037.0;
}
#endif
tmp = parts[DUK__IDX_YEAR];
if (tmp < 1971 || tmp > 2037) {
DUK_ASSERT(parts[DUK__IDX_WEEKDAY] >= 0 && parts[DUK__IDX_WEEKDAY] <= 6);
isleap = duk__is_leap_year(tmp);
DUK_ASSERT(isleap == 0 || isleap == 1);
arridx = parts[DUK__IDX_WEEKDAY];
if (isleap) {
arridx += 7;
}
DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
tmp = (duk_int_t) duk__date_equivyear[arridx] + 1970;
DUK_DDD(DUK_DDDPRINT("replaced year with equivalent year: %ld -> %ld", (long) dparts[DUK__IDX_YEAR], (long) tmp));
dparts[DUK__IDX_YEAR] = tmp;
}
duk__timeval_to_parts(d, parts, dparts, DUK__FLAG_EQUIVYEAR /*flags*/);
DUK_ASSERT(parts[DUK__IDX_YEAR] >= 1970 && parts[DUK__IDX_YEAR] <= 2038);
d = duk__get_timeval_from_dparts(dparts, 0 /*flags*/);
DUK_ASSERT(d >= 0 && d < 2147483648.0 * 1000.0); /* unsigned 31-bit range */
@ -339,6 +316,13 @@ static duk_int_t duk__get_local_tzoffset(duk_double_t d) {
ULARGE_INTEGER tmp3;
FILETIME ft1;
/* FIXME: handling of timestamps outside Windows supported range.
* How does Windows deal with dates before 1600? Does windows
* support all Ecmascript years (like -200000 and +200000)?
* Should equivalent year mapping be used here too? If so, use
* a shared helper (currently integrated into timeval-to-parts).
*/
/* Use the approach described in "Remarks" of FileTimeToLocalFileTime:
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms724277(v=vs.85).aspx
*/
@ -382,7 +366,7 @@ static duk_bool_t duk__parse_string_strptime(duk_context *ctx, const char *str)
"wday:%ld,yday:%ld,isdst:%ld}",
(long) tm.tm_sec, (long) tm.tm_min, (long) tm.tm_hour,
(long) tm.tm_mday, (long) tm.tm_mon, (long) tm.tm_year,
(long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
(long) tm.tm_wday, (long) tm.tm_yday, (long) tm.tm_isdst));
tm.tm_isdst = -1; /* negative: dst info not available */
t = mktime(&tm);
@ -812,7 +796,6 @@ static duk_uint8_t duk__days_in_month[12] = {
(duk_uint8_t) 30, (duk_uint8_t) 31, (duk_uint8_t) 30, (duk_uint8_t) 31
};
/* Equivalent year for DST calculations outside [1970,2038[ range, see
* E5 Section 15.9.1.8. Equivalent year has the same leap-year-ness and
* starts with the same weekday on Jan 1.
@ -850,6 +833,19 @@ static duk_uint8_t duk__date_equivyear[14] = {
};
#undef DUK__YEAR
/* Maximum iteration count for computing UTC-to-local time offset when
* creating an Ecmascript time value from local parts.
*/
#define DUK__LOCAL_TZOFFSET_MAXITER 4
/* Because 'day since epoch' can be negative and is used to compute weekday
* using a modulo operation, add this multiple of 7 to avoid negative values
* when year is below 1970 epoch. Ecmascript time values are restricted to
* +/- 100 million days from epoch, so this adder fits nicely into 32 bits.
* Round to a multiple of 7 (= floor(100000000 / 7) * 7) and add margin.
*/
#define DUK__WEEKDAY_MOD_ADDER (20000000 * 7) /* 0x08583b00 */
static duk_bool_t duk__is_leap_year(duk_int_t year) {
if ((year % 4) != 0) {
return 0;
@ -922,12 +918,12 @@ static duk_int_t duk__year_from_day(duk_int_t day, duk_small_int_t *out_day_with
diff_days = duk__day_from_year(year) - day;
DUK_DDD(DUK_DDDPRINT("year=%ld day=%ld, diff_days=%ld", (long) year, (long) day, (long) diff_days));
if (diff_days <= 0) {
DUK_ASSERT(-diff_days <= 366); /* fits into duk_small_int_t */
DUK_ASSERT(-diff_days < 366); /* fits into duk_small_int_t */
*out_day_within_year = -diff_days;
DUK_DDD(DUK_DDDPRINT("--> year=%ld, day-within-year=%ld",
(long) year, (long) *out_day_within_year));
DUK_ASSERT(*out_day_within_year >= 0);
DUK_ASSERT(*out_day_within_year <= (duk__is_leap_year(year) ? 366 : 365));
DUK_ASSERT(*out_day_within_year < (duk__is_leap_year(year) ? 366 : 365));
return year;
}
@ -998,12 +994,18 @@ static duk_double_t duk__make_day(duk_double_t year, duk_double_t month, duk_dou
static void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t *dparts, duk_small_uint_t flags) {
duk_double_t d1, d2;
duk_int_t t1, t2;
duk_int_t day_since_epoch;
duk_int_t year; /* does not fit into 16 bits */
duk_small_int_t day_in_year;
duk_small_int_t month;
duk_small_int_t day;
duk_small_int_t dim;
duk_int_t jan1_since_epoch;
duk_small_int_t jan1_weekday;
duk_int_t equiv_year;
duk_small_uint_t i;
duk_bool_t is_leap;
duk_small_int_t arridx;
DUK_ASSERT(DUK_ISFINITE(d)); /* caller checks */
DUK_ASSERT(DUK_FLOOR(d) == d); /* no fractions in internal time */
@ -1016,16 +1018,18 @@ static void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t
/* deal with negative values */
d1 += (duk_double_t) DUK__MS_DAY;
}
d2 = DUK_FLOOR(d / (duk_double_t) DUK__MS_DAY);
d2 = DUK_FLOOR((double) (d / (duk_double_t) DUK__MS_DAY));
DUK_ASSERT(d2 * ((duk_double_t) DUK__MS_DAY) + d1 == d);
/* now expected to fit into a 32-bit integer */
t1 = (duk_int_t) d1;
t2 = (duk_int_t) d2;
day_since_epoch = t2;
DUK_ASSERT((duk_double_t) t1 == d1);
DUK_ASSERT((duk_double_t) t2 == d2);
/* t1 = milliseconds within day, t2 = day number */
/* t1 = milliseconds within day (fits 32 bit)
* t2 = day number from epoch (fits 32 bit, may be negative)
*/
parts[DUK__IDX_MILLISECOND] = t1 % 1000; t1 /= 1000;
parts[DUK__IDX_SECOND] = t1 % 60; t1 /= 60;
@ -1036,13 +1040,12 @@ static void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t
DUK_ASSERT(parts[DUK__IDX_MINUTE] >= 0 && parts[DUK__IDX_MINUTE] <= 59);
DUK_ASSERT(parts[DUK__IDX_HOUR] >= 0 && parts[DUK__IDX_HOUR] <= 23);
parts[DUK__IDX_WEEKDAY] = (t2 + 4) % 7; /* E5.1 Section 15.9.1.6 */
if (parts[DUK__IDX_WEEKDAY] < 0) {
/* deal with negative values */
parts[DUK__IDX_WEEKDAY] += 7;
}
DUK_ASSERT(t2 + DUK__WEEKDAY_MOD_ADDER >= 0);
parts[DUK__IDX_WEEKDAY] = (t2 + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
DUK_ASSERT(parts[DUK__IDX_WEEKDAY] >= 0 && parts[DUK__IDX_WEEKDAY] <= 6);
year = duk__year_from_day(t2, &day);
year = duk__year_from_day(t2, &day_in_year);
day = day_in_year;
is_leap = duk__is_leap_year(year);
for (month = 0; month < 12; month++) {
dim = duk__days_in_month[month];
@ -1060,6 +1063,39 @@ static void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t
DUK_ASSERT(month >= 0 && month <= 11);
DUK_ASSERT(day >= 0 && day <= 31);
/* Equivalent year mapping, used to avoid DST trouble when platform
* may fail to provide reasonable DST answers for dates outside the
* ordinary range (e.g. 1970-2038). An equivalent year has the same
* leap-year-ness as the original year and begins on the same weekday
* (Jan 1).
*
* The year 2038 is avoided because there seem to be problems with it
* on some platforms. The year 1970 is also avoided as there were
* practical problems with it; an equivalent year is used for it too,
* which breaks some DST computations for 1970 right now, see e.g.
* test-bi-date-tzoffset-brute-fi.js.
*/
if ((flags & DUK__FLAG_EQUIVYEAR) && (year < 1971 || year > 2037)) {
DUK_ASSERT(is_leap == 0 || is_leap == 1);
jan1_since_epoch = day_since_epoch - day_in_year; /* day number for Jan 1 since epoch */
DUK_ASSERT(jan1_since_epoch + DUK__WEEKDAY_MOD_ADDER >= 0);
jan1_weekday = (jan1_since_epoch + 4 + DUK__WEEKDAY_MOD_ADDER) % 7; /* E5.1 Section 15.9.1.6 */
DUK_ASSERT(jan1_weekday >= 0 && jan1_weekday <= 6);
arridx = jan1_weekday;
if (is_leap) {
arridx += 7;
}
DUK_ASSERT(arridx >= 0 && arridx < (duk_small_int_t) (sizeof(duk__date_equivyear) / sizeof(duk_uint8_t)));
equiv_year = (duk_int_t) duk__date_equivyear[arridx] + 1970;
year = equiv_year;
DUK_DDD(DUK_DDDPRINT("equiv year mapping, year=%ld, day_in_year=%ld, day_since_epoch=%ld, "
"jan1_since_epoch=%ld, jan1_weekday=%ld -> equiv year %ld",
(long) year, (long) day_in_year, (long) day_since_epoch,
(long) jan1_since_epoch, (long) jan1_weekday, (long) equiv_year));
}
parts[DUK__IDX_YEAR] = year;
parts[DUK__IDX_MONTH] = month;
parts[DUK__IDX_DAY] = day;
@ -1076,7 +1112,10 @@ static void duk__timeval_to_parts(duk_double_t d, duk_int_t *parts, duk_double_t
}
}
/* Compute time value from (double) parts. */
/* Compute time value from (double) parts. The parts can be either UTC
* or local time; if local, they need to be (conceptually) converted into
* UTC time.
*/
static duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_small_uint_t flags) {
#if defined(DUK_USE_PARANOID_DATE_COMPUTATION)
/* See comments below on MakeTime why these are volatile. */
@ -1089,6 +1128,7 @@ static duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_small
duk_double_t d;
#endif
duk_small_uint_t i;
duk_int_t tzoff, tzoffprev1, tzoffprev2;
/* Expects 'this' at top of stack on entry. */
@ -1143,23 +1183,64 @@ static duk_double_t duk__get_timeval_from_dparts(duk_double_t *dparts, duk_small
DUK_DDD(DUK_DDDPRINT("time=%lf day=%lf --> timeval=%lf",
(double) tmp_time, (double) tmp_day, (double) d));
/* Optional UTC conversion followed by TimeClip().
* Note that this also handles Infinity -> NaN conversion.
*/
/* Optional UTC conversion. */
if (flags & DUK__FLAG_LOCALTIME) {
/* FIXME: this is now incorrect. 'd' is local time here (as
* we're converting to UTC), but DUK__GET_LOCAL_TZOFFSET() should
* be called with UTC time. This needs to be reworked to avoid
* the chicken-and-egg problem.
/* DUK__GET_LOCAL_TZOFFSET() needs to be called with a time
* value computed from UTC parts. At this point we only have
* 'd' which is a time value computed from local parts, so it
* is off by the UTC-to-local time offset which we don't know
* yet. The current solution for computing the UTC-to-local
* time offset is to iterate a few times and detect a fixed
* point or a two-cycle loop (or a sanity iteration limit),
* see test-bi-date-local-parts.js and test-bi-date-tzoffset-basic-fi.js.
*
* See E5.1 Section 15.9.1.9:
* E5.1 Section 15.9.1.9:
* UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA)
*
* For NaN/inf, DUK__GET_LOCAL_TZOFFSET() returns 0.
*/
d -= DUK__GET_LOCAL_TZOFFSET(d) * 1000L;
#if 0
/* Old solution: don't iterate, incorrect */
tzoff = DUK__GET_LOCAL_TZOFFSET(d);
DUK_DDD(DUK_DDDPRINT("tzoffset w/o iteration, tzoff=%ld", (long) tzoff));
d -= tzoff * 1000L;
DUK_UNREF(tzoffprev1);
DUK_UNREF(tzoffprev2);
#endif
/* Iteration solution */
tzoff = 0;
tzoffprev1 = 999999999L; /* invalid value which never matches */
for (i = 0; i < DUK__LOCAL_TZOFFSET_MAXITER; i++) {
tzoffprev2 = tzoffprev1;
tzoffprev1 = tzoff;
tzoff = DUK__GET_LOCAL_TZOFFSET(d - tzoff * 1000L);
DUK_DDD(DUK_DDDPRINT("tzoffset iteration, i=%d, tzoff=%ld, tzoffprev1=%ld tzoffprev2=%ld",
(int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
if (tzoff == tzoffprev1) {
DUK_DDD(DUK_DDDPRINT("tzoffset iteration finished, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
(int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
break;
} else if (tzoff == tzoffprev2) {
/* Two value cycle, see e.g. test-bi-date-tzoffset-basic-fi.js.
* In these cases, favor a higher tzoffset to get a consistent
* result which is independent of iteration count. Not sure if
* this is a generically correct solution.
*/
DUK_DDD(DUK_DDDPRINT("tzoffset iteration two-value cycle, i=%d, tzoff=%ld, tzoffprev1=%ld, tzoffprev2=%ld",
(int) i, (long) tzoff, (long) tzoffprev1, (long) tzoffprev2));
if (tzoffprev1 > tzoff) {
tzoff = tzoffprev1;
}
break;
}
}
DUK_DDD(DUK_DDDPRINT("tzoffset iteration, tzoff=%ld", (long) tzoff));
d -= tzoff * 1000L;
}
/* TimeClip(), which also handles Infinity -> NaN conversion */
d = duk__timeclip(d);
return d;
@ -1352,7 +1433,7 @@ static duk_ret_t duk__to_string_helper(duk_context *ctx, duk_small_uint_t flags)
static duk_ret_t duk__get_part_helper(duk_context *ctx, duk_small_uint_t flags_and_idx) {
duk_double_t d;
duk_int_t parts[DUK__NUM_PARTS];
duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> 12); /* unpack args */
duk_small_uint_t idx_part = (duk_small_uint_t) (flags_and_idx >> DUK__FLAG_VALUE_SHIFT); /* unpack args */
DUK_ASSERT_DISABLE(idx_part >= 0); /* unsigned */
DUK_ASSERT(idx_part < DUK__NUM_PARTS);
@ -1386,7 +1467,7 @@ static duk_ret_t duk__set_part_helper(duk_context *ctx, duk_small_uint_t flags_a
duk_int_t parts[DUK__NUM_PARTS];
duk_double_t dparts[DUK__NUM_PARTS];
duk_idx_t nargs;
duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> 12); /* unpack args */
duk_small_uint_t maxnargs = (duk_small_uint_t) (flags_and_maxnargs >> DUK__FLAG_VALUE_SHIFT); /* unpack args */
duk_small_uint_t idx_first, idx;
duk_small_uint_t i;

82
src/genbuiltins.py

@ -134,14 +134,16 @@ PROPDESC_FLAG_ACCESSOR = (1 << 3) # unused now
BI_DATE_FLAG_NAN_TO_ZERO = (1 << 0)
BI_DATE_FLAG_NAN_TO_RANGE_ERROR = (1 << 1)
BI_DATE_FLAG_ONEBASED = (1 << 2)
BI_DATE_FLAG_LOCALTIME = (1 << 3)
BI_DATE_FLAG_SUB1900 = (1 << 4)
BI_DATE_FLAG_TOSTRING_DATE = (1 << 5)
BI_DATE_FLAG_TOSTRING_TIME = (1 << 6)
BI_DATE_FLAG_TOSTRING_LOCALE = (1 << 7)
BI_DATE_FLAG_TIMESETTER = (1 << 8)
BI_DATE_FLAG_YEAR_FIXUP = (1 << 9)
BI_DATE_FLAG_SEP_T = (1 << 10)
BI_DATE_FLAG_EQUIVYEAR = (1 << 3)
BI_DATE_FLAG_LOCALTIME = (1 << 4)
BI_DATE_FLAG_SUB1900 = (1 << 5)
BI_DATE_FLAG_TOSTRING_DATE = (1 << 6)
BI_DATE_FLAG_TOSTRING_TIME = (1 << 7)
BI_DATE_FLAG_TOSTRING_LOCALE = (1 << 8)
BI_DATE_FLAG_TIMESETTER = (1 << 9)
BI_DATE_FLAG_YEAR_FIXUP = (1 << 10)
BI_DATE_FLAG_SEP_T = (1 << 11)
BI_DATE_FLAG_VALUE_SHIFT = 12
BI_DATE_IDX_YEAR = 0
BI_DATE_IDX_MONTH = 1
BI_DATE_IDX_DAY = 2
@ -667,46 +669,46 @@ bi_date_prototype = {
{ 'name': 'toJSON', 'native': 'duk_bi_date_prototype_to_json', 'length': 1 },
{ 'name': 'valueOf', 'native': 'duk_bi_date_prototype_value_of', 'length': 0 },
{ 'name': 'getTime', 'native': 'duk_bi_date_prototype_value_of', 'length': 0 }, # Native function shared on purpose
{ 'name': 'getFullYear', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_YEAR << 12) } },
{ 'name': 'getUTCFullYear', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_YEAR << 12) } },
{ 'name': 'getMonth', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_MONTH << 12) } },
{ 'name': 'getUTCMonth', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_MONTH << 12) } },
{ 'name': 'getDate', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_ONEBASED + BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_DAY << 12) } },
{ 'name': 'getUTCDate', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_ONEBASED + (BI_DATE_IDX_DAY << 12) } },
{ 'name': 'getDay', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_WEEKDAY << 12) } },
{ 'name': 'getUTCDay', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_WEEKDAY << 12) } },
{ 'name': 'getHours', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_HOUR << 12) } },
{ 'name': 'getUTCHours', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_HOUR << 12) } },
{ 'name': 'getMinutes', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_MINUTE << 12) } },
{ 'name': 'getUTCMinutes', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_MINUTE << 12) } },
{ 'name': 'getSeconds', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_SECOND << 12) } },
{ 'name': 'getUTCSeconds', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_SECOND << 12) } },
{ 'name': 'getMilliseconds', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_MILLISECOND << 12) } },
{ 'name': 'getUTCMilliseconds', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_MILLISECOND << 12) } },
{ 'name': 'getFullYear', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_YEAR << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getUTCFullYear', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_YEAR << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getMonth', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_MONTH << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getUTCMonth', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_MONTH << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getDate', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_ONEBASED + BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_DAY << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getUTCDate', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_ONEBASED + (BI_DATE_IDX_DAY << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getDay', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_WEEKDAY << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getUTCDay', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_WEEKDAY << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getHours', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_HOUR << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getUTCHours', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_HOUR << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getMinutes', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_MINUTE << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getUTCMinutes', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_MINUTE << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getSeconds', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_SECOND << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getUTCSeconds', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_SECOND << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getMilliseconds', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (BI_DATE_IDX_MILLISECOND << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getUTCMilliseconds', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'magic': { 'type': 'plain', 'value': 0 + (BI_DATE_IDX_MILLISECOND << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'getTimezoneOffset', 'native': 'duk_bi_date_prototype_get_timezone_offset', 'length': 0 },
{ 'name': 'setTime', 'native': 'duk_bi_date_prototype_set_time', 'length': 1 },
{ 'name': 'setMilliseconds', 'native': 'duk_bi_date_prototype_set_shared', 'length': 1, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + BI_DATE_FLAG_LOCALTIME + (1 << 12) } },
{ 'name': 'setUTCMilliseconds', 'native': 'duk_bi_date_prototype_set_shared', 'length': 1, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + (1 << 12) } },
{ 'name': 'setSeconds', 'native': 'duk_bi_date_prototype_set_shared', 'length': 2, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + BI_DATE_FLAG_LOCALTIME + (2 << 12) } },
{ 'name': 'setUTCSeconds', 'native': 'duk_bi_date_prototype_set_shared', 'length': 2, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + (2 << 12) } },
{ 'name': 'setMinutes', 'native': 'duk_bi_date_prototype_set_shared', 'length': 3, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + BI_DATE_FLAG_LOCALTIME + (3 << 12) } },
{ 'name': 'setUTCMinutes', 'native': 'duk_bi_date_prototype_set_shared', 'length': 3, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + (3 << 12) } },
{ 'name': 'setHours', 'native': 'duk_bi_date_prototype_set_shared', 'length': 4, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + BI_DATE_FLAG_LOCALTIME + (4 << 12) } },
{ 'name': 'setUTCHours', 'native': 'duk_bi_date_prototype_set_shared', 'length': 4, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + (4 << 12) } },
{ 'name': 'setDate', 'native': 'duk_bi_date_prototype_set_shared', 'length': 1, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (1 << 12) } },
{ 'name': 'setUTCDate', 'native': 'duk_bi_date_prototype_set_shared', 'length': 1, 'magic': { 'type': 'plain', 'value': 0 + (1 << 12) } },
{ 'name': 'setMonth', 'native': 'duk_bi_date_prototype_set_shared', 'length': 2, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (2 << 12) } },
{ 'name': 'setUTCMonth', 'native': 'duk_bi_date_prototype_set_shared', 'length': 2, 'varargs': True, 'magic': { 'type': 'plain', 'value': 0 + (2 << 12) } },
{ 'name': 'setFullYear', 'native': 'duk_bi_date_prototype_set_shared', 'length': 3, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_NAN_TO_ZERO + BI_DATE_FLAG_LOCALTIME + (3 << 12) } },
{ 'name': 'setUTCFullYear', 'native': 'duk_bi_date_prototype_set_shared', 'length': 3, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_NAN_TO_ZERO + (3 << 12) } },
{ 'name': 'setMilliseconds', 'native': 'duk_bi_date_prototype_set_shared', 'length': 1, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + BI_DATE_FLAG_LOCALTIME + (1 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setUTCMilliseconds', 'native': 'duk_bi_date_prototype_set_shared', 'length': 1, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + (1 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setSeconds', 'native': 'duk_bi_date_prototype_set_shared', 'length': 2, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + BI_DATE_FLAG_LOCALTIME + (2 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setUTCSeconds', 'native': 'duk_bi_date_prototype_set_shared', 'length': 2, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + (2 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setMinutes', 'native': 'duk_bi_date_prototype_set_shared', 'length': 3, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + BI_DATE_FLAG_LOCALTIME + (3 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setUTCMinutes', 'native': 'duk_bi_date_prototype_set_shared', 'length': 3, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + (3 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setHours', 'native': 'duk_bi_date_prototype_set_shared', 'length': 4, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + BI_DATE_FLAG_LOCALTIME + (4 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setUTCHours', 'native': 'duk_bi_date_prototype_set_shared', 'length': 4, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_TIMESETTER + (4 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setDate', 'native': 'duk_bi_date_prototype_set_shared', 'length': 1, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (1 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setUTCDate', 'native': 'duk_bi_date_prototype_set_shared', 'length': 1, 'magic': { 'type': 'plain', 'value': 0 + (1 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setMonth', 'native': 'duk_bi_date_prototype_set_shared', 'length': 2, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + (2 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setUTCMonth', 'native': 'duk_bi_date_prototype_set_shared', 'length': 2, 'varargs': True, 'magic': { 'type': 'plain', 'value': 0 + (2 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setFullYear', 'native': 'duk_bi_date_prototype_set_shared', 'length': 3, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_NAN_TO_ZERO + BI_DATE_FLAG_LOCALTIME + (3 << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setUTCFullYear', 'native': 'duk_bi_date_prototype_set_shared', 'length': 3, 'varargs': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_NAN_TO_ZERO + (3 << BI_DATE_FLAG_VALUE_SHIFT) } },
# Non-standard extensions: E5 Section B.2.4, B.2.5, B.2.6
#
# 'length' values are not given explicitly but follows the general rule.
# The lengths below agree with V8.
{ 'name': 'getYear', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'section_b': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + BI_DATE_FLAG_SUB1900 + (BI_DATE_IDX_YEAR << 12) } },
{ 'name': 'setYear', 'native': 'duk_bi_date_prototype_set_shared', 'length': 1, 'section_b': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_NAN_TO_ZERO + BI_DATE_FLAG_YEAR_FIXUP + (3 << 12) } },
{ 'name': 'getYear', 'native': 'duk_bi_date_prototype_get_shared', 'length': 0, 'section_b': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_LOCALTIME + BI_DATE_FLAG_SUB1900 + (BI_DATE_IDX_YEAR << BI_DATE_FLAG_VALUE_SHIFT) } },
{ 'name': 'setYear', 'native': 'duk_bi_date_prototype_set_shared', 'length': 1, 'section_b': True, 'magic': { 'type': 'plain', 'value': BI_DATE_FLAG_NAN_TO_ZERO + BI_DATE_FLAG_YEAR_FIXUP + (3 << BI_DATE_FLAG_VALUE_SHIFT) } },
# Note: toGMTString() is required to initially be the same Function object as the initial
# Date.prototype.toUTCString. In other words: Date.prototype.toGMTString === Date.prototype.toUTCString --> true.

Loading…
Cancel
Save