aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn/internal/objects/NativeDate.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jdk/nashorn/internal/objects/NativeDate.java')
-rw-r--r--src/jdk/nashorn/internal/objects/NativeDate.java1352
1 files changed, 0 insertions, 1352 deletions
diff --git a/src/jdk/nashorn/internal/objects/NativeDate.java b/src/jdk/nashorn/internal/objects/NativeDate.java
deleted file mode 100644
index 4c581db6..00000000
--- a/src/jdk/nashorn/internal/objects/NativeDate.java
+++ /dev/null
@@ -1,1352 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.nashorn.internal.objects;
-
-import static java.lang.Double.NaN;
-import static java.lang.Double.isInfinite;
-import static java.lang.Double.isNaN;
-import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
-import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-
-import java.util.Locale;
-import java.util.TimeZone;
-import java.util.concurrent.Callable;
-import jdk.nashorn.internal.objects.annotations.Attribute;
-import jdk.nashorn.internal.objects.annotations.Constructor;
-import jdk.nashorn.internal.objects.annotations.Function;
-import jdk.nashorn.internal.objects.annotations.ScriptClass;
-import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
-import jdk.nashorn.internal.objects.annotations.Where;
-import jdk.nashorn.internal.parser.DateParser;
-import jdk.nashorn.internal.runtime.JSType;
-import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.ScriptEnvironment;
-import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
-import jdk.nashorn.internal.runtime.linker.Bootstrap;
-import jdk.nashorn.internal.runtime.linker.InvokeByName;
-
-/**
- * ECMA 15.9 Date Objects
- *
- */
-@ScriptClass("Date")
-public final class NativeDate extends ScriptObject {
-
- private static final String INVALID_DATE = "Invalid Date";
-
- private static final int YEAR = 0;
- private static final int MONTH = 1;
- private static final int DAY = 2;
- private static final int HOUR = 3;
- private static final int MINUTE = 4;
- private static final int SECOND = 5;
- private static final int MILLISECOND = 6;
-
- private static final int FORMAT_DATE_TIME = 0;
- private static final int FORMAT_DATE = 1;
- private static final int FORMAT_TIME = 2;
- private static final int FORMAT_LOCAL_DATE_TIME = 3;
- private static final int FORMAT_LOCAL_DATE = 4;
- private static final int FORMAT_LOCAL_TIME = 5;
-
- // Constants defined in ECMA 15.9.1.10
- private static final int hoursPerDay = 24;
- private static final int minutesPerHour = 60;
- private static final int secondsPerMinute = 60;
- private static final int msPerSecond = 1_000;
- private static final int msPerMinute = 60_000;
- private static final double msPerHour = 3_600_000;
- private static final double msPerDay = 86_400_000;
-
- private static int[][] firstDayInMonth = {
- {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, // normal year
- {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335} // leap year
- };
-
- private static String[] weekDays = {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- };
-
- private static String[] months = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
-
- private static final Object TO_ISO_STRING = new Object();
-
- private static InvokeByName getTO_ISO_STRING() {
- return Global.instance().getInvokeByName(TO_ISO_STRING,
- new Callable<InvokeByName>() {
- @Override
- public InvokeByName call() {
- return new InvokeByName("toISOString", ScriptObject.class, Object.class, Object.class);
- }
- });
- }
-
- private double time;
- private final TimeZone timezone;
-
- // initialized by nasgen
- private static PropertyMap $nasgenmap$;
-
- private NativeDate(final double time, final ScriptObject proto, final PropertyMap map) {
- super(proto, map);
- final ScriptEnvironment env = Global.getEnv();
-
- this.time = time;
- this.timezone = env._timezone;
- }
-
- NativeDate(final double time, final ScriptObject proto) {
- this(time, proto, $nasgenmap$);
- }
-
- NativeDate(final double time, final Global global) {
- this(time, global.getDatePrototype(), $nasgenmap$);
- }
-
- private NativeDate (final double time) {
- this(time, Global.instance());
- }
-
- private NativeDate() {
- this(System.currentTimeMillis());
- }
-
- @Override
- public String getClassName() {
- return "Date";
- }
-
- // ECMA 8.12.8 [[DefaultValue]] (hint)
- @Override
- public Object getDefaultValue(final Class<?> hint) {
- // When the [[DefaultValue]] internal method of O is called with no hint,
- // then it behaves as if the hint were Number, unless O is a Date object
- // in which case it behaves as if the hint were String.
- return super.getDefaultValue(hint == null ? String.class : hint);
- }
-
- /**
- * Constructor - ECMA 15.9.3.1 new Date
- *
- * @param isNew is this Date constructed with the new operator
- * @param self self references
- * @return Date representing now
- */
- @SpecializedFunction(isConstructor=true)
- public static Object construct(final boolean isNew, final Object self) {
- final NativeDate result = new NativeDate();
- return isNew ? result : toStringImpl(result, FORMAT_DATE_TIME);
- }
-
- /**
- * Constructor - ECMA 15.9.3.1 new Date (year, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] )
- *
- * @param isNew is this Date constructed with the new operator
- * @param self self reference
- * @param args arguments
- * @return new Date
- */
- @Constructor(arity = 7)
- public static Object construct(final boolean isNew, final Object self, final Object... args) {
- if (! isNew) {
- return toStringImpl(new NativeDate(), FORMAT_DATE_TIME);
- }
-
- NativeDate result;
- switch (args.length) {
- case 0:
- result = new NativeDate();
- break;
-
- case 1:
- double num;
- final Object arg = JSType.toPrimitive(args[0]);
- if (JSType.isString(arg)) {
- num = parseDateString(arg.toString());
- } else {
- num = timeClip(JSType.toNumber(args[0]));
- }
- result = new NativeDate(num);
- break;
-
- default:
- result = new NativeDate(0);
- final double[] d = convertCtorArgs(args);
- if (d == null) {
- result.setTime(Double.NaN);
- } else {
- final double time = timeClip(utc(makeDate(d), result.getTimeZone()));
- result.setTime(time);
- }
- break;
- }
-
- return result;
- }
-
- @Override
- public String safeToString() {
- final String str = isValidDate() ? toISOStringImpl(this) : INVALID_DATE;
- return "[Date " + str + "]";
- }
-
- @Override
- public String toString() {
- return isValidDate() ? toString(this).toString() : INVALID_DATE;
- }
-
- /**
- * ECMA 15.9.4.2 Date.parse (string)
- *
- * @param self self reference
- * @param string string to parse as date
- * @return Date interpreted from the string, or NaN for illegal values
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static double parse(final Object self, final Object string) {
- return parseDateString(JSType.toString(string));
- }
-
- /**
- * ECMA 15.9.4.3 Date.UTC (year, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] )
- *
- * @param self self reference
- * @param args mandatory args are year, month. Optional are date, hours, minutes, seconds and milliseconds
- * @return a time clip according to the ECMA specification
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 7, where = Where.CONSTRUCTOR)
- public static double UTC(final Object self, final Object... args) {
- final NativeDate nd = new NativeDate(0);
- final double[] d = convertCtorArgs(args);
- final double time = d == null ? Double.NaN : timeClip(makeDate(d));
- nd.setTime(time);
- return time;
- }
-
- /**
- * ECMA 15.9.4.4 Date.now ( )
- *
- * @param self self reference
- * @return a Date that points to the current moment in time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
- public static double now(final Object self) {
- // convert to double as long does not represent the primitive JS number type
- return (double) System.currentTimeMillis();
- }
-
- /**
- * ECMA 15.9.5.2 Date.prototype.toString ( )
- *
- * @param self self reference
- * @return string value that represents the Date in the current time zone
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static String toString(final Object self) {
- return toStringImpl(self, FORMAT_DATE_TIME);
- }
-
- /**
- * ECMA 15.9.5.3 Date.prototype.toDateString ( )
- *
- * @param self self reference
- * @return string value with the "date" part of the Date in the current time zone
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static String toDateString(final Object self) {
- return toStringImpl(self, FORMAT_DATE);
- }
-
- /**
- * ECMA 15.9.5.4 Date.prototype.toTimeString ( )
- *
- * @param self self reference
- * @return string value with "time" part of Date in the current time zone
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static String toTimeString(final Object self) {
- return toStringImpl(self, FORMAT_TIME);
- }
-
- /**
- * ECMA 15.9.5.5 Date.prototype.toLocaleString ( )
- *
- * @param self self reference
- * @return string value that represents the Data in the current time zone and locale
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static String toLocaleString(final Object self) {
- return toStringImpl(self, FORMAT_LOCAL_DATE_TIME);
- }
-
- /**
- * ECMA 15.9.5.6 Date.prototype.toLocaleDateString ( )
- *
- * @param self self reference
- * @return string value with the "date" part of the Date in the current time zone and locale
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static String toLocaleDateString(final Object self) {
- return toStringImpl(self, FORMAT_LOCAL_DATE);
- }
-
- /**
- * ECMA 15.9.5.7 Date.prototype.toLocaleTimeString ( )
- *
- * @param self self reference
- * @return string value with the "time" part of Date in the current time zone and locale
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static String toLocaleTimeString(final Object self) {
- return toStringImpl(self, FORMAT_LOCAL_TIME);
- }
-
- /**
- * ECMA 15.9.5.8 Date.prototype.valueOf ( )
- *
- * @param self self reference
- * @return valueOf - a number which is this time value
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double valueOf(final Object self) {
- final NativeDate nd = getNativeDate(self);
- return (nd != null) ? nd.getTime() : Double.NaN;
- }
-
- /**
- * ECMA 15.9.5.9 Date.prototype.getTime ( )
- *
- * @param self self reference
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getTime(final Object self) {
- final NativeDate nd = getNativeDate(self);
- return (nd != null) ? nd.getTime() : Double.NaN;
- }
-
- /**
- * ECMA 15.9.5.10 Date.prototype.getFullYear ( )
- *
- * @param self self reference
- * @return full year
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object getFullYear(final Object self) {
- return getField(self, YEAR);
- }
-
- /**
- * ECMA 15.9.5.11 Date.prototype.getUTCFullYear( )
- *
- * @param self self reference
- * @return UTC full year
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getUTCFullYear(final Object self) {
- return getUTCField(self, YEAR);
- }
-
- /**
- * B.2.4 Date.prototype.getYear ( )
- *
- * @param self self reference
- * @return year
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getYear(final Object self) {
- final NativeDate nd = getNativeDate(self);
- return (nd != null && nd.isValidDate()) ? (yearFromTime(nd.getLocalTime()) - 1900) : Double.NaN;
- }
-
- /**
- * ECMA 15.9.5.12 Date.prototype.getMonth ( )
- *
- * @param self self reference
- * @return month
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getMonth(final Object self) {
- return getField(self, MONTH);
- }
-
- /**
- * ECMA 15.9.5.13 Date.prototype.getUTCMonth ( )
- *
- * @param self self reference
- * @return UTC month
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getUTCMonth(final Object self) {
- return getUTCField(self, MONTH);
- }
-
- /**
- * ECMA 15.9.5.14 Date.prototype.getDate ( )
- *
- * @param self self reference
- * @return date
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getDate(final Object self) {
- return getField(self, DAY);
- }
-
- /**
- * ECMA 15.9.5.15 Date.prototype.getUTCDate ( )
- *
- * @param self self reference
- * @return UTC Date
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getUTCDate(final Object self) {
- return getUTCField(self, DAY);
- }
-
- /**
- * ECMA 15.9.5.16 Date.prototype.getDay ( )
- *
- * @param self self reference
- * @return day
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getDay(final Object self) {
- final NativeDate nd = getNativeDate(self);
- return (nd != null && nd.isValidDate()) ? weekDay(nd.getLocalTime()) : Double.NaN;
- }
-
- /**
- * ECMA 15.9.5.17 Date.prototype.getUTCDay ( )
- *
- * @param self self reference
- * @return UTC day
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getUTCDay(final Object self) {
- final NativeDate nd = getNativeDate(self);
- return (nd != null && nd.isValidDate()) ? weekDay(nd.getTime()) : Double.NaN;
- }
-
- /**
- * ECMA 15.9.5.18 Date.prototype.getHours ( )
- *
- * @param self self reference
- * @return hours
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getHours(final Object self) {
- return getField(self, HOUR);
- }
-
- /**
- * ECMA 15.9.5.19 Date.prototype.getUTCHours ( )
- *
- * @param self self reference
- * @return UTC hours
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getUTCHours(final Object self) {
- return getUTCField(self, HOUR);
- }
-
- /**
- * ECMA 15.9.5.20 Date.prototype.getMinutes ( )
- *
- * @param self self reference
- * @return minutes
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getMinutes(final Object self) {
- return getField(self, MINUTE);
- }
-
- /**
- * ECMA 15.9.5.21 Date.prototype.getUTCMinutes ( )
- *
- * @param self self reference
- * @return UTC minutes
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getUTCMinutes(final Object self) {
- return getUTCField(self, MINUTE);
- }
-
- /**
- * ECMA 15.9.5.22 Date.prototype.getSeconds ( )
- *
- * @param self self reference
- * @return seconds
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getSeconds(final Object self) {
- return getField(self, SECOND);
- }
-
- /**
- * ECMA 15.9.5.23 Date.prototype.getUTCSeconds ( )
- *
- * @param self self reference
- * @return UTC seconds
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getUTCSeconds(final Object self) {
- return getUTCField(self, SECOND);
- }
-
- /**
- * ECMA 15.9.5.24 Date.prototype.getMilliseconds ( )
- *
- * @param self self reference
- * @return milliseconds
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getMilliseconds(final Object self) {
- return getField(self, MILLISECOND);
- }
-
- /**
- * ECMA 15.9.5.25 Date.prototype.getUTCMilliseconds ( )
- *
- * @param self self reference
- * @return UTC milliseconds
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getUTCMilliseconds(final Object self) {
- return getUTCField(self, MILLISECOND);
- }
-
- /**
- * ECMA 15.9.5.26 Date.prototype.getTimezoneOffset ( )
- *
- * @param self self reference
- * @return time zone offset or NaN if N/A
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double getTimezoneOffset(final Object self) {
- final NativeDate nd = getNativeDate(self);
- if (nd != null && nd.isValidDate()) {
- final long msec = (long) nd.getTime();
- return - nd.getTimeZone().getOffset(msec) / msPerMinute;
- }
- return Double.NaN;
- }
-
- /**
- * ECMA 15.9.5.27 Date.prototype.setTime (time)
- *
- * @param self self reference
- * @param time time
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double setTime(final Object self, final Object time) {
- final NativeDate nd = getNativeDate(self);
- final double num = timeClip(JSType.toNumber(time));
- nd.setTime(num);
- return num;
- }
-
- /**
- * ECMA 15.9.5.28 Date.prototype.setMilliseconds (ms)
- *
- * @param self self reference
- * @param args milliseconds
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static double setMilliseconds(final Object self, final Object... args) {
- final NativeDate nd = getNativeDate(self);
- setFields(nd, MILLISECOND, args, true);
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.29 Date.prototype.setUTCMilliseconds (ms)
- *
- * @param self self reference
- * @param args utc milliseconds
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static double setUTCMilliseconds(final Object self, final Object... args) {
- final NativeDate nd = getNativeDate(self);
- setFields(nd, MILLISECOND, args, false);
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.30 Date.prototype.setSeconds (sec [, ms ] )
- *
- * @param self self reference
- * @param args seconds (milliseconds optional second argument)
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
- public static double setSeconds(final Object self, final Object... args) {
- final NativeDate nd = getNativeDate(self);
- setFields(nd, SECOND, args, true);
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.31 Date.prototype.setUTCSeconds (sec [, ms ] )
- *
- * @param self self reference
- * @param args UTC seconds (milliseconds optional second argument)
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
- public static double setUTCSeconds(final Object self, final Object... args) {
- final NativeDate nd = getNativeDate(self);
- setFields(nd, SECOND, args, false);
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.32 Date.prototype.setMinutes (min [, sec [, ms ] ] )
- *
- * @param self self reference
- * @param args minutes (seconds and milliseconds are optional second and third arguments)
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
- public static double setMinutes(final Object self, final Object... args) {
- final NativeDate nd = getNativeDate(self);
- setFields(nd, MINUTE, args, true);
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.33 Date.prototype.setUTCMinutes (min [, sec [, ms ] ] )
- *
- * @param self self reference
- * @param args minutes (seconds and milliseconds are optional second and third arguments)
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
- public static double setUTCMinutes(final Object self, final Object... args) {
- final NativeDate nd = getNativeDate(self);
- setFields(nd, MINUTE, args, false);
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.34 Date.prototype.setHours (hour [, min [, sec [, ms ] ] ] )
- *
- * @param self self reference
- * @param args hour (optional arguments after are minutes, seconds, milliseconds)
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 4)
- public static double setHours(final Object self, final Object... args) {
- final NativeDate nd = getNativeDate(self);
- setFields(nd, HOUR, args, true);
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.35 Date.prototype.setUTCHours (hour [, min [, sec [, ms ] ] ] )
- *
- * @param self self reference
- * @param args hour (optional arguments after are minutes, seconds, milliseconds)
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 4)
- public static double setUTCHours(final Object self, final Object... args) {
- final NativeDate nd = getNativeDate(self);
- setFields(nd, HOUR, args, false);
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.36 Date.prototype.setDate (date)
- *
- * @param self self reference
- * @param args date
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static double setDate(final Object self, final Object... args) {
- final NativeDate nd = getNativeDate(self);
- setFields(nd, DAY, args, true);
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.37 Date.prototype.setUTCDate (date)
- *
- * @param self self reference
- * @param args UTC date
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
- public static double setUTCDate(final Object self, final Object... args) {
- final NativeDate nd = getNativeDate(self);
- setFields(nd, DAY, args, false);
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.38 Date.prototype.setMonth (month [, date ] )
- *
- * @param self self reference
- * @param args month (optional second argument is date)
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
- public static double setMonth(final Object self, final Object... args) {
- final NativeDate nd = getNativeDate(self);
- setFields(nd, MONTH, args, true);
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.39 Date.prototype.setUTCMonth (month [, date ] )
- *
- * @param self self reference
- * @param args UTC month (optional second argument is date)
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
- public static double setUTCMonth(final Object self, final Object... args) {
- final NativeDate nd = ensureNativeDate(self);
- setFields(nd, MONTH, args, false);
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.40 Date.prototype.setFullYear (year [, month [, date ] ] )
- *
- * @param self self reference
- * @param args year (optional second and third arguments are month and date)
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
- public static double setFullYear(final Object self, final Object... args) {
- final NativeDate nd = ensureNativeDate(self);
- if (nd.isValidDate()) {
- setFields(nd, YEAR, args, true);
- } else {
- final double[] d = convertArgs(args, 0, YEAR, YEAR, 3);
- if (d != null) {
- nd.setTime(timeClip(utc(makeDate(makeDay(d[0], d[1], d[2]), 0), nd.getTimeZone())));
- } else {
- nd.setTime(NaN);
- }
- }
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.41 Date.prototype.setUTCFullYear (year [, month [, date ] ] )
- *
- * @param self self reference
- * @param args UTC full year (optional second and third arguments are month and date)
- * @return time
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 3)
- public static double setUTCFullYear(final Object self, final Object... args) {
- final NativeDate nd = ensureNativeDate(self);
- if (nd.isValidDate()) {
- setFields(nd, YEAR, args, false);
- } else {
- final double[] d = convertArgs(args, 0, YEAR, YEAR, 3);
- nd.setTime(timeClip(makeDate(makeDay(d[0], d[1], d[2]), 0)));
- }
- return nd.getTime();
- }
-
- /**
- * ECMA B.2.5 Date.prototype.setYear (year)
- *
- * @param self self reference
- * @param year year
- * @return NativeDate
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static double setYear(final Object self, final Object year) {
- final NativeDate nd = getNativeDate(self);
- if (isNaN(nd.getTime())) {
- nd.setTime(utc(0, nd.getTimeZone()));
- }
-
- final double yearNum = JSType.toNumber(year);
- if (isNaN(yearNum)) {
- nd.setTime(NaN);
- return nd.getTime();
- }
- int yearInt = (int)yearNum;
- if (0 <= yearInt && yearInt <= 99) {
- yearInt += 1900;
- }
- setFields(nd, YEAR, new Object[] {yearInt}, true);
-
- return nd.getTime();
- }
-
- /**
- * ECMA 15.9.5.42 Date.prototype.toUTCString ( )
- *
- * @param self self reference
- * @return string representation of date
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static String toUTCString(final Object self) {
- return toGMTStringImpl(self);
- }
-
- /**
- * ECMA B.2.6 Date.prototype.toGMTString ( )
- *
- * See {@link NativeDate#toUTCString(Object)}
- *
- * @param self self reference
- * @return string representation of date
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static String toGMTString(final Object self) {
- return toGMTStringImpl(self);
- }
-
- /**
- * ECMA 15.9.5.43 Date.prototype.toISOString ( )
- *
- * @param self self reference
- * @return string representation of date
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static String toISOString(final Object self) {
- return toISOStringImpl(self);
- }
-
- /**
- * ECMA 15.9.5.44 Date.prototype.toJSON ( key )
- *
- * Provides a string representation of this Date for use by {@link NativeJSON#stringify(Object, Object, Object, Object)}
- *
- * @param self self reference
- * @param key ignored
- * @return JSON representation of this date
- */
- @Function(attributes = Attribute.NOT_ENUMERABLE)
- public static Object toJSON(final Object self, final Object key) {
- // NOTE: Date.prototype.toJSON is generic. Accepts other objects as well.
- final Object selfObj = Global.toObject(self);
- if (!(selfObj instanceof ScriptObject)) {
- return null;
- }
- final ScriptObject sobj = (ScriptObject)selfObj;
- final Object value = sobj.getDefaultValue(Number.class);
- if (value instanceof Number) {
- final double num = ((Number)value).doubleValue();
- if (isInfinite(num) || isNaN(num)) {
- return null;
- }
- }
-
- try {
- final InvokeByName toIsoString = getTO_ISO_STRING();
- final Object func = toIsoString.getGetter().invokeExact(sobj);
- if (Bootstrap.isCallable(func)) {
- return toIsoString.getInvoker().invokeExact(func, sobj, key);
- }
- throw typeError("not.a.function", ScriptRuntime.safeToString(func));
- } catch (final RuntimeException | Error e) {
- throw e;
- } catch (final Throwable t) {
- throw new RuntimeException(t);
- }
- }
-
- // -- Internals below this point
-
- private static double parseDateString(final String str) {
-
- final DateParser parser = new DateParser(str);
- if (parser.parse()) {
- final Integer[] fields = parser.getDateFields();
- double d = makeDate(fields);
- if (fields[DateParser.TIMEZONE] != null) {
- d -= fields[DateParser.TIMEZONE] * 60000;
- } else {
- d = utc(d, Global.getEnv()._timezone);
- }
- d = timeClip(d);
- return d;
- }
-
- return Double.NaN;
- }
-
- private static void zeroPad(final StringBuilder sb, final int n, final int length) {
- for (int l = 1, d = 10; l < length; l++, d *= 10) {
- if (n < d) {
- sb.append('0');
- }
- }
- sb.append(n);
- }
-
- @SuppressWarnings("fallthrough")
- private static String toStringImpl(final Object self, final int format) {
- final NativeDate nd = getNativeDate(self);
-
- if (nd != null && nd.isValidDate()) {
- final StringBuilder sb = new StringBuilder(40);
- final double t = nd.getLocalTime();
-
- switch (format) {
-
- case FORMAT_DATE_TIME:
- case FORMAT_DATE :
- case FORMAT_LOCAL_DATE_TIME:
- // EEE MMM dd yyyy
- sb.append(weekDays[weekDay(t)])
- .append(' ')
- .append(months[monthFromTime(t)])
- .append(' ');
- zeroPad(sb, dayFromTime(t), 2);
- sb.append(' ');
- zeroPad(sb, yearFromTime(t), 4);
- if (format == FORMAT_DATE) {
- break;
- }
- sb.append(' ');
-
- case FORMAT_TIME:
- final TimeZone tz = nd.getTimeZone();
- final double utcTime = nd.getTime();
- int offset = tz.getOffset((long) utcTime) / 60000;
- final boolean inDaylightTime = offset != tz.getRawOffset() / 60000;
- // Convert minutes to HHmm timezone offset
- offset = (offset / 60) * 100 + offset % 60;
-
- // HH:mm:ss GMT+HHmm
- zeroPad(sb, hourFromTime(t), 2);
- sb.append(':');
- zeroPad(sb, minFromTime(t), 2);
- sb.append(':');
- zeroPad(sb, secFromTime(t), 2);
- sb.append(" GMT")
- .append(offset < 0 ? '-' : '+');
- zeroPad(sb, Math.abs(offset), 4);
- sb.append(" (")
- .append(tz.getDisplayName(inDaylightTime, TimeZone.SHORT, Locale.US))
- .append(')');
- break;
-
- case FORMAT_LOCAL_DATE:
- // yyyy-MM-dd
- zeroPad(sb, yearFromTime(t), 4);
- sb.append('-');
- zeroPad(sb, monthFromTime(t) + 1, 2);
- sb.append('-');
- zeroPad(sb, dayFromTime(t), 2);
- break;
-
- case FORMAT_LOCAL_TIME:
- // HH:mm:ss
- zeroPad(sb, hourFromTime(t), 2);
- sb.append(':');
- zeroPad(sb, minFromTime(t), 2);
- sb.append(':');
- zeroPad(sb, secFromTime(t), 2);
- break;
-
- default:
- throw new IllegalArgumentException("format: " + format);
- }
-
- return sb.toString();
- }
-
- return INVALID_DATE;
- }
-
- private static String toGMTStringImpl(final Object self) {
- final NativeDate nd = getNativeDate(self);
-
- if (nd != null && nd.isValidDate()) {
- final StringBuilder sb = new StringBuilder(29);
- final double t = nd.getTime();
- // EEE, dd MMM yyyy HH:mm:ss z
- sb.append(weekDays[weekDay(t)])
- .append(", ");
- zeroPad(sb, dayFromTime(t), 2);
- sb.append(' ')
- .append(months[monthFromTime(t)])
- .append(' ');
- zeroPad(sb, yearFromTime(t), 4);
- sb.append(' ');
- zeroPad(sb, hourFromTime(t), 2);
- sb.append(':');
- zeroPad(sb, minFromTime(t), 2);
- sb.append(':');
- zeroPad(sb, secFromTime(t), 2);
- sb.append(" GMT");
- return sb.toString();
- }
-
- throw rangeError("invalid.date");
- }
-
- private static String toISOStringImpl(final Object self) {
- final NativeDate nd = getNativeDate(self);
-
- if (nd != null && nd.isValidDate()) {
- final StringBuilder sb = new StringBuilder(24);
- final double t = nd.getTime();
- // yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
- zeroPad(sb, yearFromTime(t), 4);
- sb.append('-');
- zeroPad(sb, monthFromTime(t) + 1, 2);
- sb.append('-');
- zeroPad(sb, dayFromTime(t), 2);
- sb.append('T');
- zeroPad(sb, hourFromTime(t), 2);
- sb.append(':');
- zeroPad(sb, minFromTime(t), 2);
- sb.append(':');
- zeroPad(sb, secFromTime(t), 2);
- sb.append('.');
- zeroPad(sb, msFromTime(t), 3);
- sb.append("Z");
- return sb.toString();
- }
-
- throw rangeError("invalid.date");
- }
-
- // ECMA 15.9.1.2 Day (t)
- private static double day(final double t) {
- return Math.floor(t / msPerDay);
- }
-
- // ECMA 15.9.1.2 TimeWithinDay (t)
- private static double timeWithinDay(final double t) {
- final double val = t % msPerDay;
- return val < 0? val + msPerDay : val;
- }
-
- // ECMA 15.9.1.3 InLeapYear (t)
- private static boolean isLeapYear(final int y) {
- return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
- }
-
- // ECMA 15.9.1.3 DaysInYear (y)
- private static int daysInYear(final int y) {
- return isLeapYear(y) ? 366 : 365;
- }
-
- // ECMA 15.9.1.3 DayFromYear (y)
- private static double dayFromYear(final double y) {
- return 365 * (y - 1970)
- + Math.floor((y -1969) / 4.0)
- - Math.floor((y - 1901) / 100.0)
- + Math.floor((y - 1601) / 400.0);
- }
-
- // ECMA 15.9.1.3 Year Number
- private static double timeFromYear(final int y) {
- return dayFromYear(y) * msPerDay;
- }
-
- // ECMA 15.9.1.3 Year Number
- private static int yearFromTime(final double t) {
- int y = (int) Math.floor(t / (msPerDay * 365.2425)) + 1970;
- final double t2 = timeFromYear(y);
- if (t2 > t) {
- y--;
- } else if (t2 + msPerDay * daysInYear(y) <= t) {
- y++;
- }
- return y;
- }
-
- private static int dayWithinYear(final double t, final int year) {
- return (int) (day(t) - dayFromYear(year));
- }
-
- private static int monthFromTime(final double t) {
- final int year = yearFromTime(t);
- final int day = dayWithinYear(t, year);
- final int[] firstDay = firstDayInMonth[isLeapYear(year) ? 1 : 0];
- int month = 0;
-
- while (month < 11 && firstDay[month + 1] <= day) {
- month++;
- }
- return month;
- }
-
- private static int dayFromTime(final double t) {
- final int year = yearFromTime(t);
- final int day = dayWithinYear(t, year);
- final int[] firstDay = firstDayInMonth[isLeapYear(year) ? 1 : 0];
- int month = 0;
-
- while (month < 11 && firstDay[month + 1] <= day) {
- month++;
- }
- return 1 + day - firstDay[month];
- }
-
- private static int dayFromMonth(final int month, final int year) {
- assert(month >= 0 && month <= 11);
- final int[] firstDay = firstDayInMonth[isLeapYear(year) ? 1 : 0];
- return firstDay[month];
- }
-
- private static int weekDay(final double time) {
- final int day = (int) (day(time) + 4) % 7;
- return day < 0 ? day + 7 : day;
- }
-
- // ECMA 15.9.1.9 LocalTime
- private static double localTime(final double time, final TimeZone tz) {
- return time + tz.getOffset((long) time);
- }
-
- // ECMA 15.9.1.9 UTC
- private static double utc(final double time, final TimeZone tz) {
- return time - tz.getOffset((long) (time - tz.getRawOffset()));
- }
-
- // ECMA 15.9.1.10 Hours, Minutes, Second, and Milliseconds
- private static int hourFromTime(final double t) {
- final int h = (int) (Math.floor(t / msPerHour) % hoursPerDay);
- return h < 0 ? h + hoursPerDay: h;
- }
- private static int minFromTime(final double t) {
- final int m = (int) (Math.floor(t / msPerMinute) % minutesPerHour);
- return m < 0 ? m + minutesPerHour : m;
- }
-
- private static int secFromTime(final double t) {
- final int s = (int) (Math.floor(t / msPerSecond) % secondsPerMinute);
- return s < 0 ? s + secondsPerMinute : s;
- }
-
- private static int msFromTime(final double t) {
- final int m = (int) (t % msPerSecond);
- return m < 0 ? m + msPerSecond : m;
- }
-
- private static int valueFromTime(final int unit, final double t) {
- switch (unit) {
- case YEAR: return yearFromTime(t);
- case MONTH: return monthFromTime(t);
- case DAY: return dayFromTime(t);
- case HOUR: return hourFromTime(t);
- case MINUTE: return minFromTime(t);
- case SECOND: return secFromTime(t);
- case MILLISECOND: return msFromTime(t);
- default: throw new IllegalArgumentException(Integer.toString(unit));
- }
- }
-
- // ECMA 15.9.1.11 MakeTime (hour, min, sec, ms)
- private static double makeTime(final double hour, final double min, final double sec, final double ms) {
- return hour * 3600000 + min * 60000 + sec * 1000 + ms;
- }
-
- // ECMA 15.9.1.12 MakeDay (year, month, date)
- private static double makeDay(final double year, final double month, final double date) {
- final double y = year + Math.floor(month / 12);
- int m = (int) (month % 12);
- if (m < 0) {
- m += 12;
- }
- double d = dayFromYear(y);
- d += dayFromMonth(m, (int) y);
-
- return d + date - 1;
- }
-
- // ECMA 15.9.1.13 MakeDate (day, time)
- private static double makeDate(final double day, final double time) {
- return day * msPerDay + time;
- }
-
-
- private static double makeDate(final Integer[] d) {
- final double time = makeDay(d[0], d[1], d[2]) * msPerDay;
- return time + makeTime(d[3], d[4], d[5], d[6]);
- }
-
- private static double makeDate(final double[] d) {
- final double time = makeDay(d[0], d[1], d[2]) * msPerDay;
- return time + makeTime(d[3], d[4], d[5], d[6]);
- }
-
- // Convert Date constructor args, checking for NaN, filling in defaults etc.
- private static double[] convertCtorArgs(final Object[] args) {
- final double[] d = new double[7];
- boolean nullReturn = false;
-
- // should not bailout on first NaN or infinite. Need to convert all
- // subsequent args for possible side-effects via valueOf/toString overrides
- // on argument objects.
- for (int i = 0; i < d.length; i++) {
- if (i < args.length) {
- final double darg = JSType.toNumber(args[i]);
- if (isNaN(darg) || isInfinite(darg)) {
- nullReturn = true;
- }
-
- d[i] = (long)darg;
- } else {
- d[i] = i == 2 ? 1 : 0; // day in month defaults to 1
- }
- }
-
- if (0 <= d[0] && d[0] <= 99) {
- d[0] += 1900;
- }
-
- return nullReturn? null : d;
- }
-
- // This method does the hard work for all setter methods: If a value is provided
- // as argument it is used, otherwise the value is calculated from the existing time value.
- private static double[] convertArgs(final Object[] args, final double time, final int fieldId, final int start, final int length) {
- final double[] d = new double[length];
- boolean nullReturn = false;
-
- // Need to call toNumber on all args for side-effects - even if an argument
- // fails to convert to number, subsequent toNumber calls needed for possible
- // side-effects via valueOf/toString overrides.
- for (int i = start; i < start + length; i++) {
- if (fieldId <= i && i < fieldId + args.length) {
- final double darg = JSType.toNumber(args[i - fieldId]);
- if (isNaN(darg) || isInfinite(darg)) {
- nullReturn = true;
- }
-
- d[i - start] = (long) darg;
- } else {
- // Date.prototype.set* methods require first argument to be defined
- if (i == fieldId) {
- nullReturn = true;
- }
-
- if (!nullReturn && !isNaN(time)) {
- d[i - start] = valueFromTime(i, time);
- }
- }
- }
-
- return nullReturn ? null : d;
- }
-
- // ECMA 15.9.1.14 TimeClip (time)
- private static double timeClip(final double time) {
- if (isInfinite(time) || isNaN(time) || Math.abs(time) > 8.64e15) {
- return Double.NaN;
- }
- return (long)time;
- }
-
- private static NativeDate ensureNativeDate(final Object self) {
- return getNativeDate(self);
- }
-
- private static NativeDate getNativeDate(final Object self) {
- if (self instanceof NativeDate) {
- return (NativeDate)self;
- } else if (self != null && self == Global.instance().getDatePrototype()) {
- return Global.instance().getDefaultDate();
- } else {
- throw typeError("not.a.date", ScriptRuntime.safeToString(self));
- }
- }
-
- private static double getField(final Object self, final int field) {
- final NativeDate nd = getNativeDate(self);
- return (nd != null && nd.isValidDate()) ? (double)valueFromTime(field, nd.getLocalTime()) : Double.NaN;
- }
-
- private static double getUTCField(final Object self, final int field) {
- final NativeDate nd = getNativeDate(self);
- return (nd != null && nd.isValidDate()) ? (double)valueFromTime(field, nd.getTime()) : Double.NaN;
- }
-
- private static void setFields(final NativeDate nd, final int fieldId, final Object[] args, final boolean local) {
- int start, length;
- if (fieldId < HOUR) {
- start = YEAR;
- length = 3;
- } else {
- start = HOUR;
- length = 4;
- }
- final double time = local ? nd.getLocalTime() : nd.getTime();
- final double d[] = convertArgs(args, time, fieldId, start, length);
-
- if (! nd.isValidDate()) {
- return;
- }
-
- double newTime;
- if (d == null) {
- newTime = NaN;
- } else {
- if (start == YEAR) {
- newTime = makeDate(makeDay(d[0], d[1], d[2]), timeWithinDay(time));
- } else {
- newTime = makeDate(day(time), makeTime(d[0], d[1], d[2], d[3]));
- }
- if (local) {
- newTime = utc(newTime, nd.getTimeZone());
- }
- newTime = timeClip(newTime);
- }
- nd.setTime(newTime);
- }
-
- private boolean isValidDate() {
- return !isNaN(time);
- }
-
- private double getLocalTime() {
- return localTime(time, timezone);
- }
-
- private double getTime() {
- return time;
- }
-
- private void setTime(final double time) {
- this.time = time;
- }
-
- private TimeZone getTimeZone() {
- return timezone;
- }
-}