/** * Copyright (c) 2012-2016 André Bargull * Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms. * * <https://github.com/anba/es6draft> */ package com.github.anba.es6draft.runtime.objects.date; import static com.github.anba.es6draft.runtime.AbstractOperations.*; import static com.github.anba.es6draft.runtime.internal.Errors.newRangeError; import static com.github.anba.es6draft.runtime.internal.Errors.newTypeError; import static com.github.anba.es6draft.runtime.internal.Properties.createProperties; import static com.github.anba.es6draft.runtime.objects.date.DateAbstractOperations.*; import static com.github.anba.es6draft.runtime.objects.intl.DateTimeFormatConstructor.ToDateTimeOptions; import static com.github.anba.es6draft.runtime.objects.intl.DateTimeFormatConstructor.FormatDateTime; import static com.github.anba.es6draft.runtime.types.Null.NULL; import java.util.TimeZone; import com.github.anba.es6draft.runtime.AbstractOperations; import com.github.anba.es6draft.runtime.AbstractOperations.ToPrimitiveHint; import com.github.anba.es6draft.runtime.ExecutionContext; import com.github.anba.es6draft.runtime.Realm; import com.github.anba.es6draft.runtime.internal.CompatibilityOption; import com.github.anba.es6draft.runtime.internal.Initializable; import com.github.anba.es6draft.runtime.internal.Messages; import com.github.anba.es6draft.runtime.internal.Properties.Attributes; import com.github.anba.es6draft.runtime.internal.Properties.CompatibilityExtension; import com.github.anba.es6draft.runtime.internal.Properties.Function; import com.github.anba.es6draft.runtime.internal.Properties.Optional; import com.github.anba.es6draft.runtime.internal.Properties.Prototype; import com.github.anba.es6draft.runtime.internal.Properties.Value; import com.github.anba.es6draft.runtime.objects.intl.DateTimeFormatConstructor; import com.github.anba.es6draft.runtime.objects.intl.DateTimeFormatObject; import com.github.anba.es6draft.runtime.types.BuiltinSymbol; import com.github.anba.es6draft.runtime.types.Intrinsics; import com.github.anba.es6draft.runtime.types.ScriptObject; import com.github.anba.es6draft.runtime.types.Type; import com.github.anba.es6draft.runtime.types.builtins.OrdinaryObject; /** * <h1>20 Numbers and Dates</h1><br> * <h2>20.3 Date Objects</h2> * <ul> * <li>20.3.4 Properties of the Date Prototype Object * </ul> */ public final class DatePrototype extends OrdinaryObject implements Initializable { /** * Constructs a new Date prototype object. * * @param realm * the realm object */ public DatePrototype(Realm realm) { super(realm); } @Override public void initialize(Realm realm) { createProperties(realm, this, Properties.class); createProperties(realm, this, AdditionalProperties.class); } private static String toISOString(double t) { assert !Double.isNaN(t); int year = (int) YearFromTime(t); int month = (int) MonthFromTime(t) + 1; int date = (int) DateFromTime(t); int hour = (int) HourFromTime(t); int min = (int) MinFromTime(t); int sec = (int) SecFromTime(t); int milli = (int) msFromTime(t); if (year < 0 || year > 9999) { return String.format("%+07d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month, date, hour, min, sec, milli); } return String.format("%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month, date, hour, min, sec, milli); } private static String toUTCString(double t) { assert !Double.isNaN(t); int year = (int) YearFromTime(t); String month = MonthNameFromTime(t); int date = (int) DateFromTime(t); String weekday = WeekDayName(t); int hour = (int) HourFromTime(t); int min = (int) MinFromTime(t); int sec = (int) SecFromTime(t); return String.format("%s, %02d %s %04d %02d:%02d:%02d GMT", weekday, date, month, year, hour, min, sec); } private static boolean isFinite(double d) { return !(Double.isNaN(d) || Double.isInfinite(d)); } public enum DateString { Date, Time, DateTime } /** * 20.3.4.41.1 Runtime Semantics: ToDateString(tv) * * @param realm * the realm instance * @param tv * the date-time value * @param dateString * the date string modifier * @return the date-time string representation */ public static String ToDateString(Realm realm, double tv, DateString dateString) { /* step 1 (not applicable) */ /* step 2 */ if (Double.isNaN(tv)) { return "Invalid Date"; } switch (dateString) { case Date: return ToDateString(realm, tv); case Time: return ToTimeString(realm, tv); case DateTime: return ToDateString(realm, tv) + ' ' + ToTimeString(realm, tv); default: throw new AssertionError(); } } private static String ToDateString(Realm realm, double tv) { assert !Double.isNaN(tv); double t = LocalTime(realm, tv); return String.format("%s %s %02d %04d", WeekDayName(t), MonthNameFromTime(t), (int) DateFromTime(t), (int) YearFromTime(t)); } private static String ToTimeString(Realm realm, double tv) { assert !Double.isNaN(tv); long date = (long) tv; TimeZone tz = realm.getTimeZone(); int tzOffset = TimeZoneInfo.getDefault().getOffset(tz, date) / 60000; tzOffset = (tzOffset / 60) * 100 + tzOffset % 60; double t = LocalTime(realm, tv); String timeZoneDisplayName = TimeZoneInfo.getDefault().getDisplayName(tz, date); return String.format("%02d:%02d:%02d GMT%+05d (%s)", (int) HourFromTime(t), (int) MinFromTime(t), (int) SecFromTime(t), tzOffset, timeZoneDisplayName); } /** * 20.3.4 Properties of the Date Prototype Object */ public enum Properties { ; /** * Abstract operation thisTimeValue(value) * * @param cx * the execution context * @param object * the date object * @return the date-time value */ private static double thisTimeValue(ExecutionContext cx, Object object) { if (object instanceof DateObject) { return ((DateObject) object).getDateValue(); } throw newTypeError(cx, Messages.Key.IncompatibleObject); } @Prototype public static final Intrinsics __proto__ = Intrinsics.ObjectPrototype; /** * 20.3.4.1 Date.prototype.constructor */ @Value(name = "constructor") public static final Intrinsics constructor = Intrinsics.Date; /** * 20.3.4.2 Date.prototype.getDate ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the date of this date object */ @Function(name = "getDate", arity = 0) public static Object getDate(ExecutionContext cx, Object thisValue) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return DateFromTime(LocalTime(realm, t)); } /** * 20.3.4.3 Date.prototype.getDay ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the week day of this date object */ @Function(name = "getDay", arity = 0) public static Object getDay(ExecutionContext cx, Object thisValue) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return WeekDay(LocalTime(realm, t)); } /** * 20.3.4.4 Date.prototype.getFullYear ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the full year of this date object */ @Function(name = "getFullYear", arity = 0) public static Object getFullYear(ExecutionContext cx, Object thisValue) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return YearFromTime(LocalTime(realm, t)); } /** * 20.3.4.5 Date.prototype.getHours ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the hours of this date object */ @Function(name = "getHours", arity = 0) public static Object getHours(ExecutionContext cx, Object thisValue) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return HourFromTime(LocalTime(realm, t)); } /** * 20.3.4.6 Date.prototype.getMilliseconds ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the milli-seconds of this date object */ @Function(name = "getMilliseconds", arity = 0) public static Object getMilliseconds(ExecutionContext cx, Object thisValue) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return msFromTime(LocalTime(realm, t)); } /** * 20.3.4.7 Date.prototype.getMinutes ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the minutes of this date object */ @Function(name = "getMinutes", arity = 0) public static Object getMinutes(ExecutionContext cx, Object thisValue) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return MinFromTime(LocalTime(realm, t)); } /** * 20.3.4.8 Date.prototype.getMonth ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the month of this date object */ @Function(name = "getMonth", arity = 0) public static Object getMonth(ExecutionContext cx, Object thisValue) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return MonthFromTime(LocalTime(realm, t)); } /** * 20.3.4.9 Date.prototype.getSeconds ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the seconds of this date object */ @Function(name = "getSeconds", arity = 0) public static Object getSeconds(ExecutionContext cx, Object thisValue) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return SecFromTime(LocalTime(realm, t)); } /** * 20.3.4.10 Date.prototype.getTime ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the date-time value of this date object */ @Function(name = "getTime", arity = 0) public static Object getTime(ExecutionContext cx, Object thisValue) { /* step 1 */ return thisTimeValue(cx, thisValue); } /** * 20.3.4.11 Date.prototype.getTimezoneOffset ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the time zone offset of this date object */ @Function(name = "getTimezoneOffset", arity = 0) public static Object getTimezoneOffset(ExecutionContext cx, Object thisValue) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return (t - LocalTime(realm, t)) / msPerMinute; } /** * 20.3.4.12 Date.prototype.getUTCDate ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the date in the UTC time zone */ @Function(name = "getUTCDate", arity = 0) public static Object getUTCDate(ExecutionContext cx, Object thisValue) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return DateFromTime(t); } /** * 20.3.4.13 Date.prototype.getUTCDay ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the week day in the UTC time zone */ @Function(name = "getUTCDay", arity = 0) public static Object getUTCDay(ExecutionContext cx, Object thisValue) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return WeekDay(t); } /** * 20.3.4.14 Date.prototype.getUTCFullYear ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the full year in the UTC time zone */ @Function(name = "getUTCFullYear", arity = 0) public static Object getUTCFullYear(ExecutionContext cx, Object thisValue) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return YearFromTime(t); } /** * 20.3.4.15 Date.prototype.getUTCHours ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the hours in the UTC time zone */ @Function(name = "getUTCHours", arity = 0) public static Object getUTCHours(ExecutionContext cx, Object thisValue) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return HourFromTime(t); } /** * 20.3.4.16 Date.prototype.getUTCMilliseconds ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the milli-seconds in the UTC time zone */ @Function(name = "getUTCMilliseconds", arity = 0) public static Object getUTCMilliseconds(ExecutionContext cx, Object thisValue) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return msFromTime(t); } /** * 20.3.4.17 Date.prototype.getUTCMinutes ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the minutes in the UTC time zone */ @Function(name = "getUTCMinutes", arity = 0) public static Object getUTCMinutes(ExecutionContext cx, Object thisValue) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return MinFromTime(t); } /** * 20.3.4.18 Date.prototype.getUTCMonth ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the month in the UTC time zone */ @Function(name = "getUTCMonth", arity = 0) public static Object getUTCMonth(ExecutionContext cx, Object thisValue) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return MonthFromTime(t); } /** * 20.3.4.19 Date.prototype.getUTCSeconds ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the seconds in the UTC time zone */ @Function(name = "getUTCSeconds", arity = 0) public static Object getUTCSeconds(ExecutionContext cx, Object thisValue) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return SecFromTime(t); } /** * 20.3.4.20 Date.prototype.setDate (date) * * @param cx * the execution context * @param thisValue * the function this-value * @param date * the new date value * @return the new date-time value */ @Function(name = "setDate", arity = 1) public static Object setDate(ExecutionContext cx, Object thisValue, Object date) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = LocalTime(realm, thisTimeValue(cx, thisValue)); /* steps 3-4 */ double dt = ToNumber(cx, date); /* step 5 */ double newDate = MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t)); /* step 6 */ double u = TimeClip(UTC(realm, newDate)); /* step 7 */ ((DateObject) thisValue).setDateValue(u); /* step 8 */ return u; } /** * 20.3.4.21 Date.prototype.setFullYear (year [, month [, date ] ] ) * * @param cx * the execution context * @param thisValue * the function this-value * @param year * the new year value * @param month * the new month value * @param date * the new date value * @return the new date-time value */ @Function(name = "setFullYear", arity = 3) public static Object setFullYear(ExecutionContext cx, Object thisValue, Object year, @Optional(Optional.Default.NONE) Object month, @Optional(Optional.Default.NONE) Object date) { Realm realm = cx.getRealm(); /* steps 1-4 */ double t = thisTimeValue(cx, thisValue); t = Double.isNaN(t) ? +0 : LocalTime(realm, t); /* steps 5-6 */ double y = ToNumber(cx, year); /* steps 7-8 */ double m = (month == null ? MonthFromTime(t) : ToNumber(cx, month)); /* steps 9-10 */ double dt = (date == null ? DateFromTime(t) : ToNumber(cx, date)); /* step 11 */ double newDate = MakeDate(MakeDay(y, m, dt), TimeWithinDay(t)); /* step 12 */ double u = TimeClip(UTC(realm, newDate)); /* step 13 */ ((DateObject) thisValue).setDateValue(u); /* step 14 */ return u; } /** * 20.3.4.22 Date.prototype.setHours (hour [, min [, sec [, ms ] ] ] ) * * @param cx * the execution context * @param thisValue * the function this-value * @param hour * the new hours value * @param min * the new minutes value * @param sec * the new seconds value * @param ms * the new milli-seconds value * @return the new date-time value */ @Function(name = "setHours", arity = 4) public static Object setHours(ExecutionContext cx, Object thisValue, Object hour, @Optional(Optional.Default.NONE) Object min, @Optional(Optional.Default.NONE) Object sec, @Optional(Optional.Default.NONE) Object ms) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = LocalTime(realm, thisTimeValue(cx, thisValue)); /* steps 3-4 */ double h = ToNumber(cx, hour); /* steps 5-6 */ double m = (min == null ? MinFromTime(t) : ToNumber(cx, min)); /* steps 7-8 */ double s = (sec == null ? SecFromTime(t) : ToNumber(cx, sec)); /* steps 9-10 */ double milli = (ms == null ? msFromTime(t) : ToNumber(cx, ms)); /* step 11 */ double date = MakeDate(Day(t), MakeTime(h, m, s, milli)); /* step 12 */ double u = TimeClip(UTC(realm, date)); /* step 13 */ ((DateObject) thisValue).setDateValue(u); /* step 14 */ return u; } /** * 20.3.4.23 Date.prototype.setMilliseconds (ms) * * @param cx * the execution context * @param thisValue * the function this-value * @param ms * the new milli-seconds value * @return the new date-time value */ @Function(name = "setMilliseconds", arity = 1) public static Object setMilliseconds(ExecutionContext cx, Object thisValue, Object ms) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = LocalTime(realm, thisTimeValue(cx, thisValue)); /* steps 3-4 */ double milli = ToNumber(cx, ms); /* step 5 */ double time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), milli); /* step 6 */ double u = TimeClip(UTC(realm, MakeDate(Day(t), time))); /* step 7 */ ((DateObject) thisValue).setDateValue(u); /* step 8 */ return u; } /** * 20.3.4.24 Date.prototype.setMinutes (min [, sec [, ms ] ] ) * * @param cx * the execution context * @param thisValue * the function this-value * @param min * the new minutes value * @param sec * the new seconds value * @param ms * the new milli-seconds value * @return the new date-time value */ @Function(name = "setMinutes", arity = 3) public static Object setMinutes(ExecutionContext cx, Object thisValue, Object min, @Optional(Optional.Default.NONE) Object sec, @Optional(Optional.Default.NONE) Object ms) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = LocalTime(realm, thisTimeValue(cx, thisValue)); /* steps 3-4 */ double m = ToNumber(cx, min); /* steps 5-6 */ double s = (sec == null ? SecFromTime(t) : ToNumber(cx, sec)); /* steps 7-8 */ double milli = (ms == null ? msFromTime(t) : ToNumber(cx, ms)); /* step 9 */ double date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli)); /* step 10 */ double u = TimeClip(UTC(realm, date)); /* step 11 */ ((DateObject) thisValue).setDateValue(u); /* step 12 */ return u; } /** * 20.3.4.25 Date.prototype.setMonth (month [, date ] ) * * @param cx * the execution context * @param thisValue * the function this-value * @param month * the new month value * @param date * the new date value * @return the new date-time value */ @Function(name = "setMonth", arity = 2) public static Object setMonth(ExecutionContext cx, Object thisValue, Object month, @Optional(Optional.Default.NONE) Object date) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = LocalTime(realm, thisTimeValue(cx, thisValue)); /* steps 3-4 */ double m = ToNumber(cx, month); /* steps 5-6 */ double dt = (date == null ? DateFromTime(t) : ToNumber(cx, date)); /* step 7 */ double newDate = MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t)); /* step 8 */ double u = TimeClip(UTC(realm, newDate)); /* step 9 */ ((DateObject) thisValue).setDateValue(u); /* step 10 */ return u; } /** * 20.3.4.26 Date.prototype.setSeconds (sec [, ms ] ) * * @param cx * the execution context * @param thisValue * the function this-value * @param sec * the new seconds value * @param ms * the new milli-seconds value * @return the new date-time value */ @Function(name = "setSeconds", arity = 2) public static Object setSeconds(ExecutionContext cx, Object thisValue, Object sec, @Optional(Optional.Default.NONE) Object ms) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = LocalTime(realm, thisTimeValue(cx, thisValue)); /* steps 3-4 */ double s = ToNumber(cx, sec); /* steps 5-6 */ double milli = (ms == null ? msFromTime(t) : ToNumber(cx, ms)); /* step 7 */ double date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli)); /* step 8 */ double u = TimeClip(UTC(realm, date)); /* step 9 */ ((DateObject) thisValue).setDateValue(u); /* step 10 */ return u; } /** * 20.3.4.27 Date.prototype.setTime (time) * * @param cx * the execution context * @param thisValue * the function this-value * @param time * the new time value * @return the new date-time value */ @Function(name = "setTime", arity = 1) public static Object setTime(ExecutionContext cx, Object thisValue, Object time) { /* steps 1-2 */ thisTimeValue(cx, thisValue); /* steps 3-4 */ double t = ToNumber(cx, time); /* step 5 */ double v = TimeClip(t); /* step 6 */ ((DateObject) thisValue).setDateValue(v); /* step 7 */ return v; } /** * 20.3.4.28 Date.prototype.setUTCDate (date) * * @param cx * the execution context * @param thisValue * the function this-value * @param date * the new date value * @return the new date-time value */ @Function(name = "setUTCDate", arity = 1) public static Object setUTCDate(ExecutionContext cx, Object thisValue, Object date) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* steps 3-4 */ double dt = ToNumber(cx, date); /* step 5 */ double newDate = MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t)); /* step 6 */ double v = TimeClip(newDate); /* step 7 */ ((DateObject) thisValue).setDateValue(v); /* step 8 */ return v; } /** * 20.3.4.29 Date.prototype.setUTCFullYear (year [, month [, date ] ] ) * * @param cx * the execution context * @param thisValue * the function this-value * @param year * the new year value * @param month * the new month value * @param date * the new date value * @return the new date-time value */ @Function(name = "setUTCFullYear", arity = 3) public static Object setUTCFullYear(ExecutionContext cx, Object thisValue, Object year, @Optional(Optional.Default.NONE) Object month, @Optional(Optional.Default.NONE) Object date) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { t = +0; } /* steps 4-5 */ double y = ToNumber(cx, year); /* steps 6-7 */ double m = (month == null ? MonthFromTime(t) : ToNumber(cx, month)); /* steps 8-9 */ double dt = (date == null ? DateFromTime(t) : ToNumber(cx, date)); /* step 10 */ double newDate = MakeDate(MakeDay(y, m, dt), TimeWithinDay(t)); /* step 11 */ double v = TimeClip(newDate); /* step 12 */ ((DateObject) thisValue).setDateValue(v); /* step 13 */ return v; } /** * 20.3.4.30 Date.prototype.setUTCHours (hour [, min [, sec [, ms ] ] ] ) * * @param cx * the execution context * @param thisValue * the function this-value * @param hour * the new hours value * @param min * the new minutes value * @param sec * the new seconds value * @param ms * the new milli-seconds value * @return the new date-time value */ @Function(name = "setUTCHours", arity = 4) public static Object setUTCHours(ExecutionContext cx, Object thisValue, Object hour, @Optional(Optional.Default.NONE) Object min, @Optional(Optional.Default.NONE) Object sec, @Optional(Optional.Default.NONE) Object ms) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* steps 3-4 */ double h = ToNumber(cx, hour); /* steps 5-6 */ double m = (min == null ? MinFromTime(t) : ToNumber(cx, min)); /* steps 7-8 */ double s = (sec == null ? SecFromTime(t) : ToNumber(cx, sec)); /* steps 9-10 */ double milli = (ms == null ? msFromTime(t) : ToNumber(cx, ms)); /* step 11 */ double newDate = MakeDate(Day(t), MakeTime(h, m, s, milli)); /* step 12 */ double v = TimeClip(newDate); /* step 13 */ ((DateObject) thisValue).setDateValue(v); /* step 14 */ return v; } /** * 20.3.4.31 Date.prototype.setUTCMilliseconds (ms) * * @param cx * the execution context * @param thisValue * the function this-value * @param ms * the new milli-seconds value * @return the new date-time value */ @Function(name = "setUTCMilliseconds", arity = 1) public static Object setUTCMilliseconds(ExecutionContext cx, Object thisValue, Object ms) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* steps 3-4 */ double milli = ToNumber(cx, ms); /* step 5 */ double time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), milli); /* step 6 */ double v = TimeClip(MakeDate(Day(t), time)); /* step 7 */ ((DateObject) thisValue).setDateValue(v); /* step 8 */ return v; } /** * 20.3.4.32 Date.prototype.setUTCMinutes (min [, sec [, ms ] ] ) * * @param cx * the execution context * @param thisValue * the function this-value * @param min * the new minutes value * @param sec * the new seconds value * @param ms * the new milli-seconds value * @return the new date-time value */ @Function(name = "setUTCMinutes", arity = 3) public static Object setUTCMinutes(ExecutionContext cx, Object thisValue, Object min, @Optional(Optional.Default.NONE) Object sec, @Optional(Optional.Default.NONE) Object ms) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* steps 3-4 */ double m = ToNumber(cx, min); /* steps 5-6 */ double s = (sec == null ? SecFromTime(t) : ToNumber(cx, sec)); /* steps 7-8 */ double milli = (ms == null ? msFromTime(t) : ToNumber(cx, ms)); /* step 9 */ double date = MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli)); /* step 10 */ double v = TimeClip(date); /* step 11 */ ((DateObject) thisValue).setDateValue(v); /* step 12 */ return v; } /** * 20.3.4.33 Date.prototype.setUTCMonth (month [, date ] ) * * @param cx * the execution context * @param thisValue * the function this-value * @param month * the new month value * @param date * the new date value * @return the new date-time value */ @Function(name = "setUTCMonth", arity = 2) public static Object setUTCMonth(ExecutionContext cx, Object thisValue, Object month, @Optional(Optional.Default.NONE) Object date) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* steps 3-4 */ double m = ToNumber(cx, month); /* steps 5-6 */ double dt = (date == null ? DateFromTime(t) : ToNumber(cx, date)); /* step 7 */ double newDate = MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t)); /* step 8 */ double v = TimeClip(newDate); /* step 9 */ ((DateObject) thisValue).setDateValue(v); /* step 10 */ return v; } /** * 20.3.4.34 Date.prototype.setUTCSeconds (sec [, ms ] ) * * @param cx * the execution context * @param thisValue * the function this-value * @param sec * the new seconds value * @param ms * the new milli-seconds value * @return the new date-time value */ @Function(name = "setUTCSeconds", arity = 2) public static Object setUTCSeconds(ExecutionContext cx, Object thisValue, Object sec, @Optional(Optional.Default.NONE) Object ms) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* steps 3-4 */ double s = ToNumber(cx, sec); /* steps 5-6 */ double milli = (ms == null ? msFromTime(t) : ToNumber(cx, ms)); /* step 7 */ double date = MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli)); /* step 8 */ double v = TimeClip(date); /* step 9 */ ((DateObject) thisValue).setDateValue(v); /* step 10 */ return v; } /** * 20.3.4.35 Date.prototype.toDateString ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the date string representation */ @Function(name = "toDateString", arity = 0) public static Object toDateString(ExecutionContext cx, Object thisValue) { double tv = thisTimeValue(cx, thisValue); return ToDateString(cx.getRealm(), tv, DateString.Date); } /** * 20.3.4.36 Date.prototype.toISOString ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the date-time string in the ISO date-time format */ @Function(name = "toISOString", arity = 0) public static Object toISOString(ExecutionContext cx, Object thisValue) { double dateValue = thisTimeValue(cx, thisValue); if (!isFinite(dateValue)) { throw newRangeError(cx, Messages.Key.InvalidDateValue); } return DatePrototype.toISOString(dateValue); } /** * 20.3.4.37 Date.prototype.toJSON ( key ) * * @param cx * the execution context * @param thisValue * the function this-value * @param key * the key argument (unused) * @return the JSON string for this date object */ @Function(name = "toJSON", arity = 1) public static Object toJSON(ExecutionContext cx, Object thisValue, Object key) { /* step 1 */ ScriptObject o = ToObject(cx, thisValue); /* steps 2-3 */ Object tv = AbstractOperations.ToPrimitive(cx, o, ToPrimitiveHint.Number); /* step 4 */ if (Type.isNumber(tv) && !isFinite(Type.numberValue(tv))) { return NULL; } /* step 5 */ return Invoke(cx, o, "toISOString"); } /** * 20.3.4.38 Date.prototype.toLocaleDateString ( [ reserved1 [ , reserved2 ] ] )<br> * 13.3.2 Date.prototype.toLocaleDateString ([locales [, options ]]) * * @param cx * the execution context * @param thisValue * the function this-value * @param locales * the locales array * @param options * the options object * @return the locale date string representation */ @Function(name = "toLocaleDateString", arity = 0) public static Object toLocaleDateString(ExecutionContext cx, Object thisValue, Object locales, Object options) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return "Invalid Date"; } /* steps 4-5 */ options = ToDateTimeOptions(cx, options, "date", "date"); /* steps 6-7 */ DateTimeFormatConstructor ctor = (DateTimeFormatConstructor) cx .getIntrinsic(Intrinsics.Intl_DateTimeFormat); DateTimeFormatObject dateTimeFormat = ctor.construct(cx, ctor, locales, options); /* step 8 */ return FormatDateTime(cx, dateTimeFormat, t); } /** * 20.3.4.39 Date.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )<br> * 13.3.1 Date.prototype.toLocaleString ([locales [, options ]]) * * @param cx * the execution context * @param thisValue * the function this-value * @param locales * the locales array * @param options * the options object * @return the locale string representation */ @Function(name = "toLocaleString", arity = 0) public static Object toLocaleString(ExecutionContext cx, Object thisValue, Object locales, Object options) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return "Invalid Date"; } /* steps 4-5 */ options = ToDateTimeOptions(cx, options, "any", "all"); /* steps 6-7 */ DateTimeFormatConstructor ctor = (DateTimeFormatConstructor) cx .getIntrinsic(Intrinsics.Intl_DateTimeFormat); DateTimeFormatObject dateTimeFormat = ctor.construct(cx, ctor, locales, options); /* step 8 */ return FormatDateTime(cx, dateTimeFormat, t); } /** * 20.3.4.40 Date.prototype.toLocaleTimeString ( [ reserved1 [ , reserved2 ] ] )<br> * 13.3.3 Date.prototype.toLocaleTimeString ([locales [, options ]]) * * @param cx * the execution context * @param thisValue * the function this-value * @param locales * the locales array * @param options * the options object * @return the locale time string representation */ @Function(name = "toLocaleTimeString", arity = 0) public static Object toLocaleTimeString(ExecutionContext cx, Object thisValue, Object locales, Object options) { /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 2 */ if (Double.isNaN(t)) { return "Invalid Date"; } /* steps 4-5 */ options = ToDateTimeOptions(cx, options, "time", "time"); /* steps 6-7 */ DateTimeFormatConstructor ctor = (DateTimeFormatConstructor) cx .getIntrinsic(Intrinsics.Intl_DateTimeFormat); DateTimeFormatObject dateTimeFormat = ctor.construct(cx, ctor, locales, options); /* step 8 */ return FormatDateTime(cx, dateTimeFormat, t); } /** * 20.3.4.41 Date.prototype.toString ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the string representation */ @Function(name = "toString", arity = 0) public static Object toString(ExecutionContext cx, Object thisValue) { /* steps 1-3 */ double tv; if (Type.isObject(thisValue) && !(thisValue instanceof DateObject)) { tv = Double.NaN; } else { tv = thisTimeValue(cx, thisValue); } /* step 4 */ return ToDateString(cx.getRealm(), tv, DateString.DateTime); } /** * 20.3.4.42 Date.prototype.toTimeString ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the time string representation */ @Function(name = "toTimeString", arity = 0) public static Object toTimeString(ExecutionContext cx, Object thisValue) { double tv = thisTimeValue(cx, thisValue); return ToDateString(cx.getRealm(), tv, DateString.Time); } /** * 20.3.4.43 Date.prototype.toUTCString ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the date-time string in the UTC time zone */ @Function(name = "toUTCString", arity = 0) public static Object toUTCString(ExecutionContext cx, Object thisValue) { double dateValue = thisTimeValue(cx, thisValue); if (Double.isNaN(dateValue)) { return "Invalid Date"; } return DatePrototype.toUTCString(dateValue); } /** * 20.3.4.44 Date.prototype.valueOf ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the date-time value of this date object */ @Function(name = "valueOf", arity = 0) public static Object valueOf(ExecutionContext cx, Object thisValue) { return thisTimeValue(cx, thisValue); } /** * 20.3.4.45 Date.prototype[@@toPrimitive] ( hint ) * * @param cx * the execution context * @param thisValue * the function this-value * @param hint * the ToPrimitive hint string * @return the primitive value for this date object */ @Function(name = "[Symbol.toPrimitive]", arity = 1, symbol = BuiltinSymbol.toPrimitive, attributes = @Attributes(writable = false, enumerable = false, configurable = true)) public static Object toPrimitive(ExecutionContext cx, Object thisValue, Object hint) { /* steps 1-2 */ if (!Type.isObject(thisValue)) { throw newTypeError(cx, Messages.Key.NotObjectType); } /* step 5 */ if (!Type.isString(hint)) { throw newTypeError(cx, Messages.Key.NotString); } /* steps 3-5 */ ToPrimitiveHint tryFirst; String _hint = Type.stringValue(hint).toString(); if ("string".equals(_hint) || "default".equals(_hint)) { tryFirst = ToPrimitiveHint.String; } else if ("number".equals(_hint)) { tryFirst = ToPrimitiveHint.Number; } else { throw newTypeError(cx, Messages.Key.InvalidToPrimitiveHint, _hint); } /* step 6 */ return OrdinaryToPrimitive(cx, Type.objectValue(thisValue), tryFirst); } } /** * B.2.4 Additional Properties of the Date.prototype Object */ @CompatibilityExtension(CompatibilityOption.DatePrototype) public enum AdditionalProperties { ; /** * Abstract operation thisTimeValue(value) * * @param cx * the execution context * @param object * the date object * @return the date-time value */ private static double thisTimeValue(ExecutionContext cx, Object object) { if (object instanceof DateObject) { return ((DateObject) object).getDateValue(); } throw newTypeError(cx, Messages.Key.IncompatibleObject); } /** * B.2.4.1 Date.prototype.getYear ( ) * * @param cx * the execution context * @param thisValue * the function this-value * @return the year of this date object */ @Function(name = "getYear", arity = 0) public static Object getYear(ExecutionContext cx, Object thisValue) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ if (Double.isNaN(t)) { return Double.NaN; } /* step 4 */ return YearFromTime(LocalTime(realm, t)) - 1900; } /** * B.2.4.2 Date.prototype.setYear (year) * * @param cx * the execution context * @param thisValue * the function this-value * @param year * the new year value * @return the new date-time value */ @Function(name = "setYear", arity = 1) public static Object setYear(ExecutionContext cx, Object thisValue, Object year) { Realm realm = cx.getRealm(); /* steps 1-2 */ double t = thisTimeValue(cx, thisValue); /* step 3 */ t = Double.isNaN(t) ? +0 : LocalTime(realm, t); /* steps 4-5 */ double y = ToNumber(cx, year); /* step 6 */ if (Double.isNaN(y)) { ((DateObject) thisValue).setDateValue(Double.NaN); return Double.NaN; } /* steps 7-8 */ double intYear = ToInteger(y); double yyyy = (0 <= intYear && intYear <= 99 ? intYear + 1900 : y); /* step 9 */ double d = MakeDay(yyyy, MonthFromTime(t), DateFromTime(t)); /* step 10 */ double date = UTC(realm, MakeDate(d, TimeWithinDay(t))); /* step 11 */ ((DateObject) thisValue).setDateValue(TimeClip(date)); /* step 12 */ return ((DateObject) thisValue).getDateValue(); } /** * B.2.4.3 Date.prototype.toGMTString ( ) * * @param cx * the execution context * @return the date-time string in the UTC time zone */ @Value(name = "toGMTString") public static Object toGMTString(ExecutionContext cx) { return Get(cx, cx.getIntrinsic(Intrinsics.DatePrototype), "toUTCString"); } } }