- use DateTimeFormatter instead of SimpleDateFormat

- Date.prototype.toLocaleString now handles locales argument
- make the formatter use Context.timezone instead of system default
- ES6: use FormatStyle.SHORT for the formatter to make it behave more like real browsers when Intl.DateTimeFormat is not supported
This commit is contained in:
Ronald Brill 2024-07-22 17:36:00 +02:00 коммит произвёл Greg Brail
Родитель 7525f813d0
Коммит 3cfa4a00eb
2 изменённых файлов: 526 добавлений и 89 удалений

Просмотреть файл

@ -6,9 +6,15 @@
package org.mozilla.javascript;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
* This class implements the Date native object. See ECMA 15.9.
@ -21,7 +27,6 @@ final class NativeDate extends IdScriptableObject {
private static final long serialVersionUID = -8307438915861678966L;
private static final Object DATE_TAG = "Date";
private static final String js_NaN_date_str = "Invalid Date";
static void init(Scriptable scope, boolean sealed) {
@ -336,7 +341,7 @@ final class NativeDate extends IdScriptableObject {
case Id_toLocaleTimeString:
case Id_toLocaleDateString:
if (!Double.isNaN(t)) {
return toLocale_helper(t, id);
return toLocale_helper(cx, t, id, args);
}
return js_NaN_date_str;
@ -529,10 +534,10 @@ final class NativeDate extends IdScriptableObject {
* floor((1968 - 1969) / 4) == -1
*/
private static double DayFromYear(double y) {
return (365 * (y - 1970)
+ Math.floor((y - 1969) / 4.0)
- Math.floor((y - 1901) / 100.0)
+ Math.floor((y - 1601) / 400.0));
return ((365 * ((y) - 1970)
+ Math.floor(((y) - 1969) / 4.0)
- Math.floor(((y) - 1901) / 100.0)
+ Math.floor(((y) - 1601) / 400.0)));
}
private static double TimeFromYear(double y) {
@ -1348,10 +1353,8 @@ final class NativeDate extends IdScriptableObject {
t = MakeDate(day, TimeWithinDay(t));
}
result.append(" (");
Date date = new Date((long) t);
synchronized (timeZoneFormatter) {
result.append(timeZoneFormatter.format(date));
}
final ZoneId zoneid = cx.getTimeZone().toZoneId();
result.append(timeZoneFormatter.format(Instant.ofEpochMilli((long) t).atZone(zoneid)));
result.append(')');
}
return result.toString();
@ -1399,25 +1402,57 @@ final class NativeDate extends IdScriptableObject {
return obj;
}
private static String toLocale_helper(double t, int methodId) {
DateFormat formatter;
private static String toLocale_helper(Context cx, double t, int methodId, Object[] args) {
DateTimeFormatter formatter;
switch (methodId) {
case Id_toLocaleString:
formatter = localeDateTimeFormatter;
formatter =
cx.getLanguageVersion() >= Context.VERSION_ES6
? localeDateTimeFormatterES6
: localeDateTimeFormatter;
break;
case Id_toLocaleTimeString:
formatter = localeTimeFormatter;
formatter =
cx.getLanguageVersion() >= Context.VERSION_ES6
? localeTimeFormatterES6
: localeTimeFormatter;
break;
case Id_toLocaleDateString:
formatter = localeDateFormatter;
formatter =
cx.getLanguageVersion() >= Context.VERSION_ES6
? localeDateFormatterES6
: localeDateFormatter;
break;
default:
throw new AssertionError(); // unreachable
}
synchronized (formatter) {
return formatter.format(new Date((long) t));
final List<String> languageTags = new ArrayList<>();
if (args.length != 0) {
// we use the 'locales' argument but ignore the second 'options' argument as per spec of
// an
// implementation that has no Intl.DateTimeFormat support
if (args[0] instanceof NativeArray) {
final NativeArray array = (NativeArray) args[0];
for (Object languageTag : array) {
languageTags.add(Context.toString(languageTag));
}
} else {
languageTags.add(Context.toString(args[0]));
}
}
final List<Locale> availableLocales = Arrays.asList(Locale.getAvailableLocales());
for (String languageTag : languageTags) {
Locale locale = Locale.forLanguageTag(languageTag);
if (availableLocales.contains(locale)) {
formatter = formatter.withLocale(locale);
break;
}
}
final ZoneId zoneid = cx.getTimeZone().toZoneId();
return formatter.format(Instant.ofEpochMilli((long) t).atZone(zoneid));
}
private static String js_toUTCString(double date) {
@ -1916,12 +1951,22 @@ final class NativeDate extends IdScriptableObject {
private static final int Id_toGMTString = Id_toUTCString; // Alias, see Ecma B.2.6
// not thread safe
private static final DateFormat timeZoneFormatter = new SimpleDateFormat("zzz");
private static final DateFormat localeDateTimeFormatter =
new SimpleDateFormat("MMMM d, yyyy h:mm:ss a z");
private static final DateFormat localeDateFormatter = new SimpleDateFormat("MMMM d, yyyy");
private static final DateFormat localeTimeFormatter = new SimpleDateFormat("h:mm:ss a z");
private static final DateTimeFormatter timeZoneFormatter = DateTimeFormatter.ofPattern("zzz");
private static final DateTimeFormatter localeDateTimeFormatter =
DateTimeFormatter.ofPattern("MMMM d, yyyy h:mm:ss a z");
private static final DateTimeFormatter localeDateFormatter =
DateTimeFormatter.ofPattern("MMMM d, yyyy");
private static final DateTimeFormatter localeTimeFormatter =
DateTimeFormatter.ofPattern("h:mm:ss a z");
// use FormatStyle.SHORT for these as per spec of an implementation that has no
// Intl.DateTimeFormat support
private static final DateTimeFormatter localeDateTimeFormatterES6 =
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
private static final DateTimeFormatter localeDateFormatterES6 =
DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT);
private static final DateTimeFormatter localeTimeFormatterES6 =
DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
private double date;
}

Просмотреть файл

@ -19,9 +19,120 @@ import org.mozilla.javascript.tests.Utils;
public class NativeDateTest {
@Test
public void ctorDateTime() {
String js = "new Date('2021-12-18T22:23').toISOString()";
public void ctorDateTimeStringGMT() {
ctorDateTimeString(
"2021-12-18T22:23:00.000Z",
"new Date('2021-12-18T22:23:00.000+00:00').toISOString()");
ctorDateTimeString(
"2021-12-18T22:23:00.000Z",
"new Date('Sat, 18 Dec 2021 22:23:00 GMT').toISOString()");
}
@Test
public void ctorDateTimeStringUTC() {
ctorDateTimeString(
"2021-12-18T22:23:00.000Z",
"new Date('2021-12-18T22:23:00.000+00:00').toISOString()");
ctorDateTimeString(
"2021-12-18T22:23:00.000Z",
"new Date('Sat, 18 Dec 2021 22:23:00 UTC').toISOString()");
}
@Test
public void ctorDateTimeStringUT() {
ctorDateTimeString(
"2021-12-18T22:23:00.000Z",
"new Date('Sat, 18 Dec 2021 22:23:00 UT').toISOString()");
}
@Test
public void ctorDateTimeStringEST() {
ctorDateTimeString(
"2021-12-18T12:23:00.000Z",
"new Date('2021-12-18T17:23:00.000+05:00').toISOString()");
ctorDateTimeString(
"2021-12-19T03:23:00.000Z",
"new Date('Sat, 18 Dec 2021 22:23:00 EST').toISOString()");
}
@Test
public void ctorDateTimeStringEDT() {
ctorDateTimeString(
"2021-12-19T02:23:00.000Z",
"new Date('Sat, 18 Dec 2021 22:23:00 EDT').toISOString()");
}
@Test
public void ctorDateTimeStringCST() {
ctorDateTimeString(
"2021-12-19T04:23:00.000Z",
"new Date('Sat, 18 Dec 2021 22:23:00 CST').toISOString()");
}
@Test
public void ctorDateTimeStringCDT() {
ctorDateTimeString(
"2021-12-19T03:23:00.000Z",
"new Date('Sat, 18 Dec 2021 22:23:00 CDT').toISOString()");
}
@Test
public void ctorDateTimeStringMST() {
ctorDateTimeString(
"2021-12-19T05:23:00.000Z",
"new Date('Sat, 18 Dec 2021 22:23:00 MST').toISOString()");
}
@Test
public void ctorDateTimeStringMDT() {
ctorDateTimeString(
"2021-12-19T04:23:00.000Z",
"new Date('Sat, 18 Dec 2021 22:23:00 MDT').toISOString()");
}
@Test
public void ctorDateTimeStringPST() {
ctorDateTimeString(
"2021-12-19T06:23:00.000Z",
"new Date('Sat, 18 Dec 2021 22:23:00 PST').toISOString()");
}
@Test
public void ctorDateTimeStringPDT() {
ctorDateTimeString(
"2021-12-19T05:23:00.000Z",
"new Date('Sat, 18 Dec 2021 22:23:00 PDT').toISOString()");
}
@Test
public void ctorDateTimeStringBerlin() {
ctorDateTimeString(
"2021-12-18T18:23:00.000Z",
"new Date('2021-12-18T17:23:00.000-01:00').toISOString()");
}
@Test
public void ctorDateTimeStringTokyo() {
ctorDateTimeString(
"2021-12-19T02:23:00.000Z",
"new Date('2021-12-18T17:23:00.000-09:00').toISOString()");
}
@Test
public void ctorDateTimeStringJST() {
ctorDateTimeString(
"2021-12-19T02:23:00.000Z",
"new Date('2021-12-18T17:23:00.000-09:00').toISOString()");
}
@Test
public void ctorDateTimeStringNewYork() {
ctorDateTimeString(
"2021-12-18T12:23:00.000Z",
"new Date('2021-12-18T17:23:00.000+05:00').toISOString()");
}
private static void ctorDateTimeString(final String expected, final String js) {
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
@ -29,25 +140,29 @@ public class NativeDateTest {
cx.setTimeZone(TimeZone.getTimeZone("GMT"));
final Object res = cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals("2021-12-18T22:23:00.000Z", res);
assertEquals(expected, res);
return null;
});
}
@Test
public void ctorDateTimeGMT() {
ctorDateTime("2021-12-18T22:23:00.000Z", "GMT");
}
@Test
public void ctorDateTimeUTC() {
ctorDateTime("2021-12-18T22:23:00.000Z", "UTC");
}
@Test
public void ctorDateTimeEST() {
ctorDateTime("2021-12-19T03:23:00.000Z", "EST");
}
@Test
public void ctorDateTimeBerlin() {
String js = "new Date('2021-12-18T22:23').toISOString()";
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
cx.setLanguageVersion(Context.VERSION_ES6);
cx.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
final Object res = cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals("2021-12-18T21:23:00.000Z", res);
return null;
});
ctorDateTime("2021-12-18T21:23:00.000Z", "Europe/Berlin");
}
@Test
@ -67,113 +182,390 @@ public class NativeDateTest {
}
@Test
public void ctorDateTimeNewYork() {
String js = "new Date('2021-12-18T22:23').toISOString()";
public void ctorDateTimeTokyo() {
ctorDateTime("2021-12-18T13:23:00.000Z", "Asia/Tokyo");
}
@Test
public void ctorDateTimeJST() {
ctorDateTime("2021-12-18T13:23:00.000Z", "JST");
}
@Test
public void ctorDateTimeNewYork() {
ctorDateTime("2021-12-19T03:23:00.000Z", "America/New_York");
}
private static void ctorDateTime(final String expected, final String tz) {
final String js = "new Date('2021-12-18T22:23').toISOString()";
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
cx.setLanguageVersion(Context.VERSION_ES6);
cx.setTimeZone(TimeZone.getTimeZone("America/New_York"));
cx.setTimeZone(TimeZone.getTimeZone(tz));
final Object res = cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals("2021-12-19T03:23:00.000Z", res);
assertEquals(expected, res);
return null;
});
}
@Test
public void ctorDate() {
String js = "new Date('2021-12-18').toISOString()";
public void ctorDateGMT() {
ctorDate("2021-12-18T00:00:00.000Z", "GMT");
}
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
cx.setLanguageVersion(Context.VERSION_ES6);
cx.setTimeZone(TimeZone.getTimeZone("GMT"));
@Test
public void ctorDateUTC() {
ctorDate("2021-12-18T00:00:00.000Z", "UTC");
}
final Object res = cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals("2021-12-18T00:00:00.000Z", res);
return null;
});
@Test
public void ctorDateEST() {
ctorDate("2021-12-18T00:00:00.000Z", "EST");
}
@Test
public void ctorDateBerlin() {
String js = "new Date('2021-12-18').toISOString()";
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
cx.setLanguageVersion(Context.VERSION_ES6);
cx.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
final Object res = cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals("2021-12-18T00:00:00.000Z", res);
return null;
});
ctorDate("2021-12-18T00:00:00.000Z", "Europe/Berlin");
}
@Test
public void ctorDateNewYork() {
String js = "new Date('2021-12-18').toISOString()";
ctorDate("2021-12-18T00:00:00.000Z", "America/New_York");
}
@Test
public void ctorDateTokyo() {
ctorDate("2021-12-18T00:00:00.000Z", "Asia/Tokyo");
}
@Test
public void ctorDateJST() {
ctorDate("2021-12-18T00:00:00.000Z", "JST");
}
private static void ctorDate(final String expected, final String tz) {
final String js = "new Date('2021-12-18').toISOString()";
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
cx.setLanguageVersion(Context.VERSION_ES6);
cx.setTimeZone(TimeZone.getTimeZone("America/New_York"));
cx.setTimeZone(TimeZone.getTimeZone(tz));
final Object res = cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals("2021-12-18T00:00:00.000Z", res);
assertEquals(expected, res);
return null;
});
}
@Test
public void timezoneOffset() {
String js = "new Date(0).getTimezoneOffset()";
public void ctorInt() {
final String js = "new Date(951782399000).toISOString()";
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
final Object res = cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals("2000-02-28T23:59:59.000Z", res);
return null;
});
}
@Test
public void ctorDouble() {
final String js = "new Date(208e10).toISOString()";
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
final Object res = cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals("2035-11-30T01:46:40.000Z", res);
return null;
});
}
@Test
public void toLocaleEnUs() {
// real browser toLocale("12/18/2021, 10:23:00 PM", "new
// Date('2021-12-18T22:23').toLocaleString('en-US')");
// toLocale("12/18/21 10:23 PM", "new Date('2021-12-18T22:23').toLocaleString('en-US')");
toLocale("12/18/21, 10:23 PM", "new Date('2021-12-18T22:23').toLocaleString('en-US')");
// real browser toLocale("12/18/2021", "new
// Date('2021-12-18T22:23').toLocaleDateString('en-US')");
toLocale("12/18/21", "new Date('2021-12-18T22:23').toLocaleDateString('en-US')");
// real browser toLocale("10:23:00 PM", "new
// Date('2021-12-18T22:23').toLocaleTimeString('en-US')");
toLocale("10:23 PM", "new Date('2021-12-18T22:23').toLocaleTimeString('en-US')");
}
@Test
public void toLocaleDeDe() {
// real browser toLocale("18.12.2021, 22:23:00", "new
// Date('2021-12-18T22:23').toLocaleString('de-DE')");
// toLocale("18.12.21 22:23", "new Date('2021-12-18T22:23').toLocaleString('de-DE')");
toLocale("18.12.21, 22:23", "new Date('2021-12-18T22:23').toLocaleString('de-DE')");
// real browser toLocale("18.12.2021", "new
// Date('2021-12-18T22:23').toLocaleDateString('de-DE')");
toLocale("18.12.21", "new Date('2021-12-18T22:23').toLocaleDateString('de-DE')");
// real browser toLocale("22:23:00", "new
// Date('2021-12-18T22:23').toLocaleTimeString('de-DE')");
toLocale("22:23", "new Date('2021-12-18T22:23').toLocaleTimeString('de-DE')");
}
@Test
public void toLocaleJaJp() {
// real browser toLocale("2021/12/18 22:23:00", "new
// Date('2021-12-18T22:23').toLocaleString('ja-JP')");
// toLocale("21/12/18 22:23", "new Date('2021-12-18T22:23').toLocaleString('ja-JP')");
toLocale("2021/12/18 22:23", "new Date('2021-12-18T22:23').toLocaleString('ja-JP')");
// real browser toLocale("2021/12/18", "new
// Date('2021-12-18T22:23').toLocaleDateString('ja-JP')");
// toLocale("21/12/18", "new Date('2021-12-18T22:23').toLocaleDateString('ja-JP')");
toLocale("2021/12/18", "new Date('2021-12-18T22:23').toLocaleDateString('ja-JP')");
// real browser toLocale("22:23:00", "new
// Date('2021-12-18T22:23').toLocaleTimeString('ja-JP')");
toLocale("22:23", "new Date('2021-12-18T22:23').toLocaleTimeString('ja-JP')");
}
@Test
public void toLocaleArray() {
// real browser toLocale("2021/12/18 22:23:00", "new
// Date('2021-12-18T22:23').toLocaleString(['foo', 'ja-JP', 'en-US'])");
// toLocale("21/12/18 22:23", "new Date('2021-12-18T22:23').toLocaleString(['foo', 'ja-JP',
// 'en-US'])");
toLocale(
"2021/12/18 22:23",
"new Date('2021-12-18T22:23').toLocaleString(['foo', 'ja-JP', 'en-US'])");
// real browser toLocale("2021/12/18", "new
// Date('2021-12-18T22:23').toLocaleDateString(['foo', 'ja-JP', 'en-US'])");
// toLocale("21/12/18", "new Date('2021-12-18T22:23').toLocaleDateString(['foo', 'ja-JP',
// 'en-US'])");
toLocale(
"2021/12/18",
"new Date('2021-12-18T22:23').toLocaleDateString(['foo', 'ja-JP', 'en-US'])");
// real browser toLocale("22:23:00", "new
// Date('2021-12-18T22:23').toLocaleTimeString(['foo', 'ja-JP', 'en-US'])");
toLocale(
"22:23",
"new Date('2021-12-18T22:23').toLocaleTimeString(['foo', 'ja-JP', 'en-US'])");
}
private static void toLocale(final String expected, final String js) {
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
cx.setLanguageVersion(Context.VERSION_ES6);
cx.setTimeZone(TimeZone.getTimeZone("GMT"));
final Double res = (Double) cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals(0, res.doubleValue(), 0.0001);
final Object res = cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals(expected, res);
return null;
});
}
@Test
public void toDateStringGMT() {
toDateString("Sat Dec 18 2021", "GMT");
}
@Test
public void toDateStringUTC() {
toDateString("Sat Dec 18 2021", "UTC");
}
@Test
public void toDateStringEST() {
toDateString("Sat Dec 18 2021", "EST");
}
@Test
public void toDateStringBerlin() {
toDateString("Sat Dec 18 2021", "Europe/Berlin");
}
@Test
public void toDateStringNewYork() {
toDateString("Sat Dec 18 2021", "America/New_York");
}
@Test
public void toDateStringTokyo() {
toDateString("Sun Dec 19 2021", "Asia/Tokyo");
}
@Test
public void toDateStringJST() {
toDateString("Sun Dec 19 2021", "JST");
}
private static void toDateString(final String expected, final String tz) {
final String js = "new Date('Sat, 18 Dec 2021 22:23:00 UTC').toDateString()";
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
cx.setLanguageVersion(Context.VERSION_ES6);
cx.setTimeZone(TimeZone.getTimeZone(tz));
final Object res = cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals(expected, res);
return null;
});
}
@Test
public void toTimeStringGMT() {
toTimeString("22:23:00 GMT-0000 (GMT)", "GMT");
}
@Test
public void toTimeStringUTC() {
toTimeString("22:23:00 GMT-0000 (UTC)", "UTC");
}
@Test
public void toTimeStringEST() {
toTimeString("17:23:00 GMT-0500 (-05:00)", "EST");
}
@Test
public void toTimeStringBerlin() {
// real browser toTimeString("22:23:00 GMT+0100 (Central European Standard Time)",
// "Europe/Berlin");
toTimeString("23:23:00 GMT+0100 (CET)", "Europe/Berlin");
}
@Test
public void toTimeStringNewYork() {
toTimeString("17:23:00 GMT-0500 (EST)", "America/New_York");
}
@Test
public void toTimeStringTokyo() {
toTimeString("07:23:00 GMT+0900 (JST)", "Asia/Tokyo");
}
@Test
public void toTimeStringJST() {
toTimeString("07:23:00 GMT+0900 (JST)", "JST");
}
private static void toTimeString(final String expected, final String tz) {
final String js = "new Date('Sat, 18 Dec 2021 22:23:00 UTC').toTimeString()";
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
cx.setLanguageVersion(Context.VERSION_ES6);
cx.setTimeZone(TimeZone.getTimeZone(tz));
final Object res = cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals(expected, res);
return null;
});
}
@Test
public void toUTCStringGMT() {
toUTCString("Sat, 18 Dec 2021 22:23:00 GMT", "GMT");
}
@Test
public void toUTCStringUTC() {
toUTCString("Sat, 18 Dec 2021 22:23:00 GMT", "UTC");
}
@Test
public void toUTCStringEST() {
toUTCString("Sat, 18 Dec 2021 22:23:00 GMT", "EST");
}
@Test
public void toUTCStringBerlin() {
toUTCString("Sat, 18 Dec 2021 22:23:00 GMT", "Europe/Berlin");
}
@Test
public void toUTCStringNewYork() {
toUTCString("Sat, 18 Dec 2021 22:23:00 GMT", "America/New_York");
}
@Test
public void toUTCStringTokyo() {
toUTCString("Sat, 18 Dec 2021 22:23:00 GMT", "Asia/Tokyo");
}
@Test
public void toUTCStringJST() {
toUTCString("Sat, 18 Dec 2021 22:23:00 GMT", "JST");
}
private static void toUTCString(final String expected, final String tz) {
final String js = "new Date('Sat, 18 Dec 2021 22:23:00 UTC').toUTCString()";
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
cx.setLanguageVersion(Context.VERSION_ES6);
cx.setTimeZone(TimeZone.getTimeZone(tz));
final Object res = cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals(expected, res);
return null;
});
}
@Test
public void timezoneOffsetGMT() {
timezoneOffset(0, "GMT");
}
@Test
public void timezoneOffsetUTC() {
timezoneOffset(0, "UTC");
}
@Test
public void timezoneOffsetEST() {
timezoneOffset(300, "EST");
}
@Test
public void timezoneOffsetBerlin() {
String js = "new Date(0).getTimezoneOffset()";
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
cx.setLanguageVersion(Context.VERSION_ES6);
cx.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
final Double res = (Double) cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals(-60, res.doubleValue(), 0.0001);
return null;
});
timezoneOffset(-60, "Europe/Berlin");
}
@Test
public void timezoneOffsetNewYork() {
String js = "new Date(0).getTimezoneOffset()";
timezoneOffset(300, "America/New_York");
}
@Test
public void timezoneOffsetTokyo() {
timezoneOffset(-540, "Asia/Tokyo");
}
@Test
public void timezoneOffsetJST() {
timezoneOffset(-540, "JST");
}
private static void timezoneOffset(final int expected, final String tz) {
final String js = "new Date(0).getTimezoneOffset()";
Utils.runWithAllOptimizationLevels(
cx -> {
final Scriptable scope = cx.initStandardObjects();
cx.setLanguageVersion(Context.VERSION_ES6);
cx.setTimeZone(TimeZone.getTimeZone("America/New_York"));
cx.setTimeZone(TimeZone.getTimeZone(tz));
final Double res = (Double) cx.evaluateString(scope, js, "test.js", 0, null);
assertEquals(300, res.doubleValue(), 0.0001);
assertEquals(expected, res.doubleValue(), 0.0001);
return null;
});
}