DatePrototype.cpp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333
  1. /*
  2. * Copyright (c) 2020-2023, Linus Groh <linusg@serenityos.org>
  3. * Copyright (c) 2021, Petróczi Zoltán <petroczizoltan@tutanota.com>
  4. * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
  5. * Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
  6. *
  7. * SPDX-License-Identifier: BSD-2-Clause
  8. */
  9. #include <AK/ByteString.h>
  10. #include <AK/DateConstants.h>
  11. #include <AK/Function.h>
  12. #include <AK/TypeCasts.h>
  13. #include <LibCore/DateTime.h>
  14. #include <LibCrypto/BigInt/UnsignedBigInteger.h>
  15. #include <LibJS/Runtime/AbstractOperations.h>
  16. #include <LibJS/Runtime/BigInt.h>
  17. #include <LibJS/Runtime/Date.h>
  18. #include <LibJS/Runtime/DatePrototype.h>
  19. #include <LibJS/Runtime/Error.h>
  20. #include <LibJS/Runtime/GlobalObject.h>
  21. #include <LibJS/Runtime/Intl/DateTimeFormat.h>
  22. #include <LibJS/Runtime/Intl/DateTimeFormatConstructor.h>
  23. #include <LibJS/Runtime/Temporal/Instant.h>
  24. #include <LibJS/Runtime/Value.h>
  25. #include <LibJS/Runtime/ValueInlines.h>
  26. #include <LibUnicode/DisplayNames.h>
  27. #include <LibUnicode/Locale.h>
  28. #include <LibUnicode/TimeZone.h>
  29. namespace JS {
  30. GC_DEFINE_ALLOCATOR(DatePrototype);
  31. DatePrototype::DatePrototype(Realm& realm)
  32. : PrototypeObject(realm.intrinsics().object_prototype())
  33. {
  34. }
  35. void DatePrototype::initialize(Realm& realm)
  36. {
  37. auto& vm = this->vm();
  38. Base::initialize(realm);
  39. u8 attr = Attribute::Writable | Attribute::Configurable;
  40. define_native_function(realm, vm.names.getDate, get_date, 0, attr);
  41. define_native_function(realm, vm.names.getDay, get_day, 0, attr);
  42. define_native_function(realm, vm.names.getFullYear, get_full_year, 0, attr);
  43. define_native_function(realm, vm.names.getHours, get_hours, 0, attr);
  44. define_native_function(realm, vm.names.getMilliseconds, get_milliseconds, 0, attr);
  45. define_native_function(realm, vm.names.getMinutes, get_minutes, 0, attr);
  46. define_native_function(realm, vm.names.getMonth, get_month, 0, attr);
  47. define_native_function(realm, vm.names.getSeconds, get_seconds, 0, attr);
  48. define_native_function(realm, vm.names.getTime, get_time, 0, attr);
  49. define_native_function(realm, vm.names.getTimezoneOffset, get_timezone_offset, 0, attr);
  50. define_native_function(realm, vm.names.getUTCDate, get_utc_date, 0, attr);
  51. define_native_function(realm, vm.names.getUTCDay, get_utc_day, 0, attr);
  52. define_native_function(realm, vm.names.getUTCFullYear, get_utc_full_year, 0, attr);
  53. define_native_function(realm, vm.names.getUTCHours, get_utc_hours, 0, attr);
  54. define_native_function(realm, vm.names.getUTCMilliseconds, get_utc_milliseconds, 0, attr);
  55. define_native_function(realm, vm.names.getUTCMinutes, get_utc_minutes, 0, attr);
  56. define_native_function(realm, vm.names.getUTCMonth, get_utc_month, 0, attr);
  57. define_native_function(realm, vm.names.getUTCSeconds, get_utc_seconds, 0, attr);
  58. define_native_function(realm, vm.names.setDate, set_date, 1, attr);
  59. define_native_function(realm, vm.names.setFullYear, set_full_year, 3, attr);
  60. define_native_function(realm, vm.names.setHours, set_hours, 4, attr);
  61. define_native_function(realm, vm.names.setMilliseconds, set_milliseconds, 1, attr);
  62. define_native_function(realm, vm.names.setMinutes, set_minutes, 3, attr);
  63. define_native_function(realm, vm.names.setMonth, set_month, 2, attr);
  64. define_native_function(realm, vm.names.setSeconds, set_seconds, 2, attr);
  65. define_native_function(realm, vm.names.setTime, set_time, 1, attr);
  66. define_native_function(realm, vm.names.setUTCDate, set_utc_date, 1, attr);
  67. define_native_function(realm, vm.names.setUTCFullYear, set_utc_full_year, 3, attr);
  68. define_native_function(realm, vm.names.setUTCHours, set_utc_hours, 4, attr);
  69. define_native_function(realm, vm.names.setUTCMilliseconds, set_utc_milliseconds, 1, attr);
  70. define_native_function(realm, vm.names.setUTCMinutes, set_utc_minutes, 3, attr);
  71. define_native_function(realm, vm.names.setUTCMonth, set_utc_month, 2, attr);
  72. define_native_function(realm, vm.names.setUTCSeconds, set_utc_seconds, 2, attr);
  73. define_native_function(realm, vm.names.toDateString, to_date_string, 0, attr);
  74. define_native_function(realm, vm.names.toISOString, to_iso_string, 0, attr);
  75. define_native_function(realm, vm.names.toJSON, to_json, 1, attr);
  76. define_native_function(realm, vm.names.toLocaleDateString, to_locale_date_string, 0, attr);
  77. define_native_function(realm, vm.names.toLocaleString, to_locale_string, 0, attr);
  78. define_native_function(realm, vm.names.toLocaleTimeString, to_locale_time_string, 0, attr);
  79. define_native_function(realm, vm.names.toString, to_string, 0, attr);
  80. define_native_function(realm, vm.names.toTemporalInstant, to_temporal_instant, 0, attr);
  81. define_native_function(realm, vm.names.toTimeString, to_time_string, 0, attr);
  82. define_native_function(realm, vm.names.toUTCString, to_utc_string, 0, attr);
  83. define_native_function(realm, vm.names.getYear, get_year, 0, attr);
  84. define_native_function(realm, vm.names.setYear, set_year, 1, attr);
  85. // 21.4.4.45 Date.prototype [ @@toPrimitive ] ( hint ), https://tc39.es/ecma262/#sec-date.prototype-@@toprimitive
  86. define_native_function(realm, vm.well_known_symbol_to_primitive(), symbol_to_primitive, 1, Attribute::Configurable);
  87. // Aliases.
  88. define_native_function(realm, vm.names.valueOf, get_time, 0, attr);
  89. // B.2.4.3 Date.prototype.toGMTString ( ), https://tc39.es/ecma262/#sec-date.prototype.togmtstring
  90. // The initial value of the "toGMTString" property is %Date.prototype.toUTCString%, defined in 21.4.4.43.
  91. define_direct_property(vm.names.toGMTString, get_without_side_effects(vm.names.toUTCString), attr);
  92. }
  93. // thisTimeValue ( value ), https://tc39.es/ecma262/#thistimevalue
  94. ThrowCompletionOr<double> this_time_value(VM& vm, Value value)
  95. {
  96. // 1. If Type(value) is Object and value has a [[DateValue]] internal slot, then
  97. if (value.is_object() && is<Date>(value.as_object())) {
  98. // a. Return value.[[DateValue]].
  99. return static_cast<Date&>(value.as_object()).date_value();
  100. }
  101. // 2. Throw a TypeError exception.
  102. return vm.throw_completion<TypeError>(ErrorType::NotAnObjectOfType, "Date");
  103. }
  104. // 21.4.4.2 Date.prototype.getDate ( ), https://tc39.es/ecma262/#sec-date.prototype.getdate
  105. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_date)
  106. {
  107. // 1. Let t be ? thisTimeValue(this value).
  108. auto time = TRY(this_time_value(vm, vm.this_value()));
  109. // 2. If t is NaN, return NaN.
  110. if (isnan(time))
  111. return js_nan();
  112. // 3. Return DateFromTime(LocalTime(t)).
  113. return Value(date_from_time(local_time(time)));
  114. }
  115. // 21.4.4.3 Date.prototype.getDay ( ), https://tc39.es/ecma262/#sec-date.prototype.getday
  116. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_day)
  117. {
  118. // 1. Let t be ? thisTimeValue(this value).
  119. auto time = TRY(this_time_value(vm, vm.this_value()));
  120. // 2. If t is NaN, return NaN.
  121. if (isnan(time))
  122. return js_nan();
  123. // 3. Return WeekDay(LocalTime(t)).
  124. return Value(week_day(local_time(time)));
  125. }
  126. // 21.4.4.4 Date.prototype.getFullYear ( ), https://tc39.es/ecma262/#sec-date.prototype.getfullyear
  127. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_full_year)
  128. {
  129. // 1. Let t be ? thisTimeValue(this value).
  130. auto time = TRY(this_time_value(vm, vm.this_value()));
  131. // 2. If t is NaN, return NaN.
  132. if (isnan(time))
  133. return js_nan();
  134. // 3. Return YearFromTime(LocalTime(t)).
  135. return Value(year_from_time(local_time(time)));
  136. }
  137. // 21.4.4.5 Date.prototype.getHours ( ), https://tc39.es/ecma262/#sec-date.prototype.gethours
  138. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_hours)
  139. {
  140. // 1. Let t be ? thisTimeValue(this value).
  141. auto time = TRY(this_time_value(vm, vm.this_value()));
  142. // 2. If t is NaN, return NaN.
  143. if (isnan(time))
  144. return js_nan();
  145. // 3. Return HourFromTime(LocalTime(t)).
  146. return Value(hour_from_time(local_time(time)));
  147. }
  148. // 21.4.4.6 Date.prototype.getMilliseconds ( ), https://tc39.es/ecma262/#sec-date.prototype.getmilliseconds
  149. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_milliseconds)
  150. {
  151. // 1. Let t be ? thisTimeValue(this value).
  152. auto time = TRY(this_time_value(vm, vm.this_value()));
  153. // 2. If t is NaN, return NaN.
  154. if (isnan(time))
  155. return js_nan();
  156. // 3. Return msFromTime(LocalTime(t)).
  157. return Value(ms_from_time(local_time(time)));
  158. }
  159. // 21.4.4.7 Date.prototype.getMinutes ( ), https://tc39.es/ecma262/#sec-date.prototype.getminutes
  160. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_minutes)
  161. {
  162. // 1. Let t be ? thisTimeValue(this value).
  163. auto time = TRY(this_time_value(vm, vm.this_value()));
  164. // 2. If t is NaN, return NaN.
  165. if (isnan(time))
  166. return js_nan();
  167. // 3. Return MinFromTime(LocalTime(t)).
  168. return Value(min_from_time(local_time(time)));
  169. }
  170. // 21.4.4.8 Date.prototype.getMonth ( ), https://tc39.es/ecma262/#sec-date.prototype.getmonth
  171. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_month)
  172. {
  173. // 1. Let t be ? thisTimeValue(this value).
  174. auto time = TRY(this_time_value(vm, vm.this_value()));
  175. // 2. If t is NaN, return NaN.
  176. if (isnan(time))
  177. return js_nan();
  178. // 3. Return MonthFromTime(LocalTime(t)).
  179. return Value(month_from_time(local_time(time)));
  180. }
  181. // 21.4.4.9 Date.prototype.getSeconds ( ), https://tc39.es/ecma262/#sec-date.prototype.getseconds
  182. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_seconds)
  183. {
  184. // 1. Let t be ? thisTimeValue(this value).
  185. auto time = TRY(this_time_value(vm, vm.this_value()));
  186. // 2. If t is NaN, return NaN.
  187. if (isnan(time))
  188. return js_nan();
  189. // 3. Return SecFromTime(LocalTime(t)).
  190. return Value(sec_from_time(local_time(time)));
  191. }
  192. // 21.4.4.10 Date.prototype.getTime ( ), https://tc39.es/ecma262/#sec-date.prototype.gettime
  193. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_time)
  194. {
  195. // 1. Return ? thisTimeValue(this value).
  196. return Value(TRY(this_time_value(vm, vm.this_value())));
  197. }
  198. // 21.4.4.11 Date.prototype.getTimezoneOffset ( ), https://tc39.es/ecma262/#sec-date.prototype.gettimezoneoffset
  199. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_timezone_offset)
  200. {
  201. // 1. Let t be ? thisTimeValue(this value).
  202. auto time = TRY(this_time_value(vm, vm.this_value()));
  203. // 2. If t is NaN, return NaN.
  204. if (isnan(time))
  205. return js_nan();
  206. // 3. Return (t - LocalTime(t)) / msPerMinute.
  207. return Value((time - local_time(time)) / ms_per_minute);
  208. }
  209. // 21.4.4.12 Date.prototype.getUTCDate ( ), https://tc39.es/ecma262/#sec-date.prototype.getutcdate
  210. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_date)
  211. {
  212. // 1. Let t be ? thisTimeValue(this value).
  213. auto time = TRY(this_time_value(vm, vm.this_value()));
  214. // 2. If t is NaN, return NaN.
  215. if (isnan(time))
  216. return js_nan();
  217. // 3. Return DateFromTime(t).
  218. return Value(date_from_time(time));
  219. }
  220. // 21.4.4.13 Date.prototype.getUTCDay ( ), https://tc39.es/ecma262/#sec-date.prototype.getutcday
  221. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_day)
  222. {
  223. // 1. Let t be ? thisTimeValue(this value).
  224. auto time = TRY(this_time_value(vm, vm.this_value()));
  225. // 2. If t is NaN, return NaN.
  226. if (isnan(time))
  227. return js_nan();
  228. // 3. Return WeekDay(t).
  229. return Value(week_day(time));
  230. }
  231. // 21.4.4.14 Date.prototype.getUTCFullYear ( ), https://tc39.es/ecma262/#sec-date.prototype.getutcfullyear
  232. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_full_year)
  233. {
  234. // 1. Let t be ? thisTimeValue(this value).
  235. auto time = TRY(this_time_value(vm, vm.this_value()));
  236. // 2. If t is NaN, return NaN.
  237. if (isnan(time))
  238. return js_nan();
  239. // 3. Return YearFromTime(t).
  240. return Value(year_from_time(time));
  241. }
  242. // 21.4.4.15 Date.prototype.getUTCHours ( ), https://tc39.es/ecma262/#sec-date.prototype.getutchours
  243. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_hours)
  244. {
  245. // 1. Let t be ? thisTimeValue(this value).
  246. auto time = TRY(this_time_value(vm, vm.this_value()));
  247. // 2. If t is NaN, return NaN.
  248. if (isnan(time))
  249. return js_nan();
  250. // 3. Return HourFromTime(t).
  251. return Value(hour_from_time(time));
  252. }
  253. // 21.4.4.16 Date.prototype.getUTCMilliseconds ( ), https://tc39.es/ecma262/#sec-date.prototype.getutcmilliseconds
  254. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_milliseconds)
  255. {
  256. // 1. Let t be ? thisTimeValue(this value).
  257. auto time = TRY(this_time_value(vm, vm.this_value()));
  258. // 2. If t is NaN, return NaN.
  259. if (isnan(time))
  260. return js_nan();
  261. // 3. Return msFromTime(t).
  262. return Value(ms_from_time(time));
  263. }
  264. // 21.4.4.17 Date.prototype.getUTCMinutes ( ), https://tc39.es/ecma262/#sec-date.prototype.getutcminutes
  265. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_minutes)
  266. {
  267. // 1. Let t be ? thisTimeValue(this value).
  268. auto time = TRY(this_time_value(vm, vm.this_value()));
  269. // 2. If t is NaN, return NaN.
  270. if (isnan(time))
  271. return js_nan();
  272. // 3. Return MinFromTime(t).
  273. return Value(min_from_time(time));
  274. }
  275. // 21.4.4.18 Date.prototype.getUTCMonth ( ), https://tc39.es/ecma262/#sec-date.prototype.getutcmonth
  276. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_month)
  277. {
  278. // 1. Let t be ? thisTimeValue(this value).
  279. auto time = TRY(this_time_value(vm, vm.this_value()));
  280. // 2. If t is NaN, return NaN.
  281. if (isnan(time))
  282. return js_nan();
  283. // 3. Return MonthFromTime(t).
  284. return month_from_time(time);
  285. }
  286. // 21.4.4.19 Date.prototype.getUTCSeconds ( ), https://tc39.es/ecma262/#sec-date.prototype.getutcseconds
  287. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_utc_seconds)
  288. {
  289. // 1. Let t be ? thisTimeValue(this value).
  290. auto time = TRY(this_time_value(vm, vm.this_value()));
  291. // 2. If t is NaN, return NaN.
  292. if (isnan(time))
  293. return js_nan();
  294. // 3. Return SecFromTime(t).
  295. return Value(sec_from_time(time));
  296. }
  297. static ThrowCompletionOr<double> argument_or_number(VM& vm, size_t index, double fallback)
  298. {
  299. if (vm.argument_count() > index)
  300. return TRY(vm.argument(index).to_number(vm)).as_double();
  301. return fallback;
  302. }
  303. static ThrowCompletionOr<Optional<double>> argument_or_empty(VM& vm, size_t index)
  304. {
  305. if (vm.argument_count() > index)
  306. return TRY(vm.argument(index).to_number(vm)).as_double();
  307. return Optional<double> {};
  308. }
  309. // 21.4.4.20 Date.prototype.setDate ( date ), https://tc39.es/ecma262/#sec-date.prototype.setdate
  310. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_date)
  311. {
  312. // 1. Let t be ? thisTimeValue(this value).
  313. auto this_time = TRY(this_time_value(vm, vm.this_value()));
  314. // 2. Let dt be ? ToNumber(date).
  315. auto date = TRY(vm.argument(0).to_number(vm)).as_double();
  316. // 3. If t is NaN, return NaN.
  317. if (isnan(this_time))
  318. return js_nan();
  319. // 4. Set t to LocalTime(t).
  320. auto time = local_time(this_time);
  321. // 5. Let newDate be MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t)).
  322. auto year = year_from_time(time);
  323. auto month = month_from_time(time);
  324. auto day = make_day(year, month, date);
  325. auto new_date = make_date(day, time_within_day(time));
  326. // 6. Let u be TimeClip(UTC(newDate)).
  327. new_date = time_clip(utc_time(new_date));
  328. // 7. Set the [[DateValue]] internal slot of this Date object to u.
  329. auto this_object = MUST(typed_this_object(vm));
  330. this_object->set_date_value(new_date);
  331. // 8. Return u.
  332. return Value(new_date);
  333. }
  334. // 21.4.4.21 Date.prototype.setFullYear ( year [ , month [ , date ] ] ), https://tc39.es/ecma262/#sec-date.prototype.setfullyear
  335. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_full_year)
  336. {
  337. // 1. Let t be ? thisTimeValue(this value).
  338. auto this_time = TRY(this_time_value(vm, vm.this_value()));
  339. // 2. Let y be ? ToNumber(year).
  340. auto year = TRY(vm.argument(0).to_number(vm)).as_double();
  341. // 3. If t is NaN, set t to +0𝔽; otherwise, set t to LocalTime(t).
  342. double time = 0;
  343. if (!isnan(this_time))
  344. time = local_time(this_time);
  345. // 4. If month is not present, let m be MonthFromTime(t); otherwise, let m be ? ToNumber(month).
  346. auto month = TRY(argument_or_number(vm, 1, month_from_time(time)));
  347. // 5. If date is not present, let dt be DateFromTime(t); otherwise, let dt be ? ToNumber(date).
  348. auto date = TRY(argument_or_number(vm, 2, date_from_time(time)));
  349. // 6. Let newDate be MakeDate(MakeDay(y, m, dt), TimeWithinDay(t)).
  350. auto day = make_day(year, month, date);
  351. auto new_date = make_date(day, time_within_day(time));
  352. // 7. Let u be TimeClip(UTC(newDate)).
  353. new_date = time_clip(utc_time(new_date));
  354. // 8. Set the [[DateValue]] internal slot of this Date object to u.
  355. auto this_object = MUST(typed_this_object(vm));
  356. this_object->set_date_value(new_date);
  357. // 9. Return u.
  358. return Value(new_date);
  359. }
  360. // 21.4.4.22 Date.prototype.setHours ( hour [ , min [ , sec [ , ms ] ] ] ), https://tc39.es/ecma262/#sec-date.prototype.sethours
  361. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_hours)
  362. {
  363. // 1. Let t be LocalTime(? thisTimeValue(this value)).
  364. auto this_time = TRY(this_time_value(vm, vm.this_value()));
  365. // 2. Let h be ? ToNumber(hour).
  366. auto hour = TRY(vm.argument(0).to_number(vm)).as_double();
  367. // 3. If min is present, let m be ? ToNumber(min).
  368. auto minute = TRY(argument_or_empty(vm, 1));
  369. // 4. If sec is present, let s be ? ToNumber(sec).
  370. auto second = TRY(argument_or_empty(vm, 2));
  371. // 5. If ms is present, let milli be ? ToNumber(ms).
  372. auto millisecond = TRY(argument_or_empty(vm, 3));
  373. // 6. If t is NaN, return NaN.
  374. if (isnan(this_time))
  375. return js_nan();
  376. // 7. Set t to LocalTime(t).
  377. auto time = local_time(this_time);
  378. // 8. If min is not present, let m be MinFromTime(t).
  379. if (!minute.has_value())
  380. minute = min_from_time(time);
  381. // 9. If sec is not present, let s be SecFromTime(t).
  382. if (!second.has_value())
  383. second = sec_from_time(time);
  384. // 10. If ms is not present, let milli be msFromTime(t).
  385. if (!millisecond.has_value())
  386. millisecond = ms_from_time(time);
  387. // 11. Let date be MakeDate(Day(t), MakeTime(h, m, s, milli)).
  388. auto new_time = make_time(hour, *minute, *second, *millisecond);
  389. auto date = make_date(day(time), new_time);
  390. // 12. Let u be TimeClip(UTC(date)).
  391. date = time_clip(utc_time(date));
  392. // 13. Set the [[DateValue]] internal slot of this Date object to u.
  393. auto this_object = MUST(typed_this_object(vm));
  394. this_object->set_date_value(date);
  395. // 14. Return u.
  396. return Value(date);
  397. }
  398. // 21.4.4.23 Date.prototype.setMilliseconds ( ms ), https://tc39.es/ecma262/#sec-date.prototype.setmilliseconds
  399. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_milliseconds)
  400. {
  401. // 1. Let t be ? thisTimeValue(this value).
  402. auto this_time = TRY(this_time_value(vm, vm.this_value()));
  403. // 2. Set ms to ? ToNumber(ms).
  404. auto millisecond = TRY(vm.argument(0).to_number(vm)).as_double();
  405. // 3. If t is NaN, return NaN.
  406. if (isnan(this_time))
  407. return js_nan();
  408. // 4. Set t to LocalTime(t).
  409. auto time = local_time(this_time);
  410. // 5. Let time be MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms).
  411. auto hour = hour_from_time(time);
  412. auto minute = min_from_time(time);
  413. auto second = sec_from_time(time);
  414. auto new_time = make_time(hour, minute, second, millisecond);
  415. // 6. Let u be TimeClip(UTC(MakeDate(Day(t), time))).
  416. auto date = make_date(day(time), new_time);
  417. date = time_clip(utc_time(date));
  418. // 7. Set the [[DateValue]] internal slot of this Date object to u.
  419. auto this_object = MUST(typed_this_object(vm));
  420. this_object->set_date_value(date);
  421. // 8. Return u.
  422. return Value(date);
  423. }
  424. // 21.4.4.24 Date.prototype.setMinutes ( min [ , sec [ , ms ] ] ), https://tc39.es/ecma262/#sec-date.prototype.setminutes
  425. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_minutes)
  426. {
  427. // 1. Let t be ? thisTimeValue(this value).
  428. auto this_time = TRY(this_time_value(vm, vm.this_value()));
  429. // 2. Let m be ? ToNumber(min).
  430. auto minute = TRY(vm.argument(0).to_number(vm)).as_double();
  431. // 3. If sec is present, let s be ? ToNumber(sec).
  432. auto second = TRY(argument_or_empty(vm, 1));
  433. // 4. If ms is present, let milli be ? ToNumber(ms).
  434. auto millisecond = TRY(argument_or_empty(vm, 2));
  435. // 5. If t is NaN, return NaN.
  436. if (isnan(this_time))
  437. return js_nan();
  438. // 6. Set t to LocalTime(t).
  439. auto time = local_time(this_time);
  440. // 7. If sec is not present, let s be SecFromTime(t).
  441. if (!second.has_value())
  442. second = sec_from_time(time);
  443. // 8. If ms is not present, let milli be msFromTime(t).
  444. if (!millisecond.has_value())
  445. millisecond = ms_from_time(time);
  446. // 9. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli)).
  447. auto hour = hour_from_time(time);
  448. auto new_time = make_time(hour, minute, *second, *millisecond);
  449. auto date = make_date(day(time), new_time);
  450. // 10. Let u be TimeClip(UTC(date)).
  451. date = time_clip(utc_time(date));
  452. // 11. Set the [[DateValue]] internal slot of this Date object to u.
  453. auto this_object = MUST(typed_this_object(vm));
  454. this_object->set_date_value(date);
  455. // 12. Return u.
  456. return Value(date);
  457. }
  458. // 21.4.4.25 Date.prototype.setMonth ( month [ , date ] ), https://tc39.es/ecma262/#sec-date.prototype.setmonth
  459. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_month)
  460. {
  461. // 1. Let t be ? thisTimeValue(this value).
  462. auto this_time = TRY(this_time_value(vm, vm.this_value()));
  463. // 2. Let m be ? ToNumber(month).
  464. auto month = TRY(vm.argument(0).to_number(vm)).as_double();
  465. // 3. If date is present, let dt be ? ToNumber(date).
  466. auto date = TRY(argument_or_empty(vm, 1));
  467. // 4. If t is NaN, return NaN.
  468. if (isnan(this_time))
  469. return js_nan();
  470. // 5. Set t to LocalTime(t).
  471. auto time = local_time(this_time);
  472. // 6. If date is not present, let dt be DateFromTime(t).
  473. if (!date.has_value())
  474. date = date_from_time(time);
  475. // 7. Let newDate be MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t)).
  476. auto year = year_from_time(time);
  477. auto day = make_day(year, month, *date);
  478. auto new_date = make_date(day, time_within_day(time));
  479. // 8. Let u be TimeClip(UTC(newDate)).
  480. new_date = time_clip(utc_time(new_date));
  481. // 9. Set the [[DateValue]] internal slot of this Date object to u.
  482. auto this_object = MUST(typed_this_object(vm));
  483. this_object->set_date_value(new_date);
  484. // 10. Return u.
  485. return Value(new_date);
  486. }
  487. // 21.4.4.26 Date.prototype.setSeconds ( sec [ , ms ] ), https://tc39.es/ecma262/#sec-date.prototype.setseconds
  488. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_seconds)
  489. {
  490. // 1. Let t be ? thisTimeValue(this value).
  491. auto this_time = TRY(this_time_value(vm, vm.this_value()));
  492. // 2. Let s be ? ToNumber(sec).
  493. auto second = TRY(vm.argument(0).to_number(vm)).as_double();
  494. // 3. If ms is present, let milli be ? ToNumber(ms).
  495. auto millisecond = TRY(argument_or_empty(vm, 1));
  496. // 4. If t is NaN, return NaN.
  497. if (isnan(this_time))
  498. return js_nan();
  499. // 5. Set t to LocalTime(t).
  500. auto time = local_time(this_time);
  501. // 6. If ms is not present, let milli be msFromTime(t).
  502. if (!millisecond.has_value())
  503. millisecond = ms_from_time(time);
  504. // 7. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli)).
  505. auto hour = hour_from_time(time);
  506. auto minute = min_from_time(time);
  507. auto new_time = make_time(hour, minute, second, *millisecond);
  508. auto new_date = make_date(day(time), new_time);
  509. // 8. Let u be TimeClip(UTC(date)).
  510. new_date = time_clip(utc_time(new_date));
  511. // 9. Set the [[DateValue]] internal slot of this Date object to u.
  512. auto this_object = MUST(typed_this_object(vm));
  513. this_object->set_date_value(new_date);
  514. // 10. Return u.
  515. return Value(new_date);
  516. }
  517. // 21.4.4.27 Date.prototype.setTime ( time ), https://tc39.es/ecma262/#sec-date.prototype.settime
  518. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_time)
  519. {
  520. // 1. Perform ? thisTimeValue(this value).
  521. TRY(this_time_value(vm, vm.this_value()));
  522. // 2. Let t be ? ToNumber(time).
  523. auto time = TRY(vm.argument(0).to_number(vm)).as_double();
  524. // 3. Let v be TimeClip(t).
  525. time = time_clip(time);
  526. // 4. Set the [[DateValue]] internal slot of this Date object to v.
  527. auto this_object = MUST(typed_this_object(vm));
  528. this_object->set_date_value(time);
  529. // 5. Return v.
  530. return Value(time);
  531. }
  532. // 21.4.4.28 Date.prototype.setUTCDate ( date ), https://tc39.es/ecma262/#sec-date.prototype.setutcdate
  533. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_utc_date)
  534. {
  535. // 1. Let t be ? thisTimeValue(this value).
  536. auto time = TRY(this_time_value(vm, vm.this_value()));
  537. // 2. Let dt be ? ToNumber(date).
  538. auto date = TRY(vm.argument(0).to_number(vm)).as_double();
  539. // 3. If t is NaN, return NaN.
  540. if (isnan(time))
  541. return js_nan();
  542. // 4. Let newDate be MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t)).
  543. auto year = year_from_time(time);
  544. auto month = month_from_time(time);
  545. auto day = make_day(year, month, date);
  546. auto new_date = make_date(day, time_within_day(time));
  547. // 5. Let v be TimeClip(newDate).
  548. new_date = time_clip(new_date);
  549. // 6. Set the [[DateValue]] internal slot of this Date object to v.
  550. auto this_object = MUST(typed_this_object(vm));
  551. this_object->set_date_value(new_date);
  552. // 7. Return v.
  553. return Value(new_date);
  554. }
  555. // 21.4.4.29 Date.prototype.setUTCFullYear ( year [ , month [ , date ] ] ), https://tc39.es/ecma262/#sec-date.prototype.setutcfullyear
  556. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_utc_full_year)
  557. {
  558. // 1. Let t be ? thisTimeValue(this value).
  559. auto this_time = TRY(this_time_value(vm, vm.this_value()));
  560. // 2. If t is NaN, set t to +0𝔽.
  561. double time = 0;
  562. if (!isnan(this_time))
  563. time = this_time;
  564. // 3. Let y be ? ToNumber(year).
  565. auto year = TRY(vm.argument(0).to_number(vm)).as_double();
  566. // 4. If month is not present, let m be MonthFromTime(t); otherwise, let m be ? ToNumber(month).
  567. auto month = TRY(argument_or_number(vm, 1, month_from_time(time)));
  568. // 5. If date is not present, let dt be DateFromTime(t); otherwise, let dt be ? ToNumber(date).
  569. auto date = TRY(argument_or_number(vm, 2, date_from_time(time)));
  570. // 6. Let newDate be MakeDate(MakeDay(y, m, dt), TimeWithinDay(t)).
  571. auto day = make_day(year, month, date);
  572. auto new_date = make_date(day, time_within_day(time));
  573. // 7. Let v be TimeClip(newDate).
  574. new_date = time_clip(new_date);
  575. // 8. Set the [[DateValue]] internal slot of this Date object to v.
  576. auto this_object = MUST(typed_this_object(vm));
  577. this_object->set_date_value(new_date);
  578. // 9. Return v.
  579. return Value(new_date);
  580. }
  581. // 21.4.4.30 Date.prototype.setUTCHours ( hour [ , min [ , sec [ , ms ] ] ] ), https://tc39.es/ecma262/#sec-date.prototype.setutchours
  582. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_utc_hours)
  583. {
  584. // 1. Let t be ? thisTimeValue(this value).
  585. auto time = TRY(this_time_value(vm, vm.this_value()));
  586. // 2. Let h be ? ToNumber(hour).
  587. auto hour = TRY(vm.argument(0).to_number(vm)).as_double();
  588. // 3. If min is present, let m be ? ToNumber(min).
  589. auto minute = TRY(argument_or_empty(vm, 1));
  590. // 4. If sec is present, let s be ? ToNumber(sec).
  591. auto second = TRY(argument_or_empty(vm, 2));
  592. // 5. If ms is present, let milli be ? ToNumber(ms).
  593. auto millisecond = TRY(argument_or_empty(vm, 3));
  594. // 6. If t is NaN, return NaN.
  595. if (isnan(time))
  596. return js_nan();
  597. // 7. If min is not present, let m be MinFromTime(t).
  598. if (!minute.has_value())
  599. minute = min_from_time(time);
  600. // 8. If sec is not present, let s be SecFromTime(t).
  601. if (!second.has_value())
  602. second = sec_from_time(time);
  603. // 9. If ms is not present, let milli be msFromTime(t).
  604. if (!millisecond.has_value())
  605. millisecond = ms_from_time(time);
  606. // 10. Let date be MakeDate(Day(t), MakeTime(h, m, s, milli)).
  607. auto new_time = make_time(hour, *minute, *second, *millisecond);
  608. auto date = make_date(day(time), new_time);
  609. // 11. Let v be TimeClip(date).
  610. date = time_clip(date);
  611. // 12. Set the [[DateValue]] internal slot of this Date object to v.
  612. auto this_object = MUST(typed_this_object(vm));
  613. this_object->set_date_value(date);
  614. // 13. Return v.
  615. return Value(date);
  616. }
  617. // 21.4.4.31 Date.prototype.setUTCMilliseconds ( ms ), https://tc39.es/ecma262/#sec-date.prototype.setutcmilliseconds
  618. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_utc_milliseconds)
  619. {
  620. // 1. Let t be ? thisTimeValue(this value).
  621. auto time = TRY(this_time_value(vm, vm.this_value()));
  622. // 2. Set ms to ? ToNumber(ms).
  623. auto millisecond = TRY(vm.argument(0).to_number(vm)).as_double();
  624. // 3. If t is NaN, return NaN.
  625. if (isnan(time))
  626. return js_nan();
  627. // 4. Let time be MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms).
  628. auto hour = hour_from_time(time);
  629. auto minute = min_from_time(time);
  630. auto second = sec_from_time(time);
  631. auto new_time = make_time(hour, minute, second, millisecond);
  632. // 5. Let v be TimeClip(MakeDate(Day(t), time)).
  633. auto date = make_date(day(time), new_time);
  634. date = time_clip(date);
  635. // 6. Set the [[DateValue]] internal slot of this Date object to v.
  636. auto this_object = MUST(typed_this_object(vm));
  637. this_object->set_date_value(date);
  638. // 7. Return v.
  639. return Value(date);
  640. }
  641. // 21.4.4.32 Date.prototype.setUTCMinutes ( min [ , sec [ , ms ] ] ), https://tc39.es/ecma262/#sec-date.prototype.setutcminutes
  642. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_utc_minutes)
  643. {
  644. // 1. Let t be ? thisTimeValue(this value).
  645. auto time = TRY(this_time_value(vm, vm.this_value()));
  646. // 2. Let m be ? ToNumber(min).
  647. auto minute = TRY(vm.argument(0).to_number(vm)).as_double();
  648. // 3. If sec is present, let s be ? ToNumber(sec).
  649. auto second = TRY(argument_or_empty(vm, 1));
  650. // 4. If ms is present, let milli be ? ToNumber(ms).
  651. auto millisecond = TRY(argument_or_empty(vm, 2));
  652. // 5. If t is NaN, return NaN.
  653. if (isnan(time))
  654. return js_nan();
  655. // 6. If sec is not present, let s be SecFromTime(t).
  656. if (!second.has_value())
  657. second = sec_from_time(time);
  658. // 7. If ms is not present, let milli be msFromTime(t).
  659. if (!millisecond.has_value())
  660. millisecond = ms_from_time(time);
  661. // 8. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli)).
  662. auto hour = hour_from_time(time);
  663. auto new_time = make_time(hour, minute, *second, *millisecond);
  664. auto date = make_date(day(time), new_time);
  665. // 9. Let v be TimeClip(date).
  666. date = time_clip(date);
  667. // 10. Set the [[DateValue]] internal slot of this Date object to v.
  668. auto this_object = MUST(typed_this_object(vm));
  669. this_object->set_date_value(date);
  670. // 11. Return v.
  671. return Value(date);
  672. }
  673. // 21.4.4.33 Date.prototype.setUTCMonth ( month [ , date ] ), https://tc39.es/ecma262/#sec-date.prototype.setutcmonth
  674. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_utc_month)
  675. {
  676. // 1. Let t be ? thisTimeValue(this value).
  677. auto time = TRY(this_time_value(vm, vm.this_value()));
  678. // 2. Let m be ? ToNumber(month).
  679. auto month = TRY(vm.argument(0).to_number(vm)).as_double();
  680. // 3. If date is present, let dt be ? ToNumber(date).
  681. auto date = TRY(argument_or_empty(vm, 1));
  682. // 4. If t is NaN, return NaN.
  683. if (isnan(time))
  684. return js_nan();
  685. // 5. If date is not present, let dt be DateFromTime(t).
  686. if (!date.has_value())
  687. date = date_from_time(time);
  688. // 6. Let newDate be MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t)).
  689. auto year = year_from_time(time);
  690. auto day = make_day(year, month, *date);
  691. auto new_date = make_date(day, time_within_day(time));
  692. // 7. Let v be TimeClip(newDate).
  693. new_date = time_clip(new_date);
  694. // 8. Set the [[DateValue]] internal slot of this Date object to v.
  695. auto this_object = MUST(typed_this_object(vm));
  696. this_object->set_date_value(new_date);
  697. // 9. Return v.
  698. return Value(new_date);
  699. }
  700. // 21.4.4.34 Date.prototype.setUTCSeconds ( sec [ , ms ] ), https://tc39.es/ecma262/#sec-date.prototype.setutcseconds
  701. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_utc_seconds)
  702. {
  703. // 1. Let t be ? thisTimeValue(this value).
  704. auto time = TRY(this_time_value(vm, vm.this_value()));
  705. // 2. Let s be ? ToNumber(sec).
  706. auto second = TRY(vm.argument(0).to_number(vm)).as_double();
  707. // 3. If ms is present, let milli be ? ToNumber(ms).
  708. auto millisecond = TRY(argument_or_empty(vm, 1));
  709. // 4. If t is NaN, return NaN.
  710. if (isnan(time))
  711. return js_nan();
  712. // 5. If ms is not present, let milli be msFromTime(t).
  713. if (!millisecond.has_value())
  714. millisecond = ms_from_time(time);
  715. // 6. Let date be MakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli)).
  716. auto hour = hour_from_time(time);
  717. auto minute = min_from_time(time);
  718. auto new_time = make_time(hour, minute, second, *millisecond);
  719. auto new_date = make_date(day(time), new_time);
  720. // 7. Let v be TimeClip(date).
  721. new_date = time_clip(new_date);
  722. // 8. Set the [[DateValue]] internal slot of this Date object to v.
  723. auto this_object = MUST(typed_this_object(vm));
  724. this_object->set_date_value(new_date);
  725. // 9. Return v.
  726. return Value(new_date);
  727. }
  728. // 21.4.4.35 Date.prototype.toDateString ( ), https://tc39.es/ecma262/#sec-date.prototype.todatestring
  729. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_date_string)
  730. {
  731. // 1. Let O be this Date object.
  732. // 2. Let tv be ? thisTimeValue(O).
  733. auto time = TRY(this_time_value(vm, vm.this_value()));
  734. // 3. If tv is NaN, return "Invalid Date".
  735. if (isnan(time))
  736. return PrimitiveString::create(vm, "Invalid Date"_string);
  737. // 4. Let t be LocalTime(tv).
  738. // 5. Return DateString(t).
  739. return PrimitiveString::create(vm, date_string(local_time(time)));
  740. }
  741. // 21.4.4.36 Date.prototype.toISOString ( ), https://tc39.es/ecma262/#sec-date.prototype.toisostring
  742. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_iso_string)
  743. {
  744. auto this_object = TRY(typed_this_object(vm));
  745. if (!Value(this_object->date_value()).is_finite_number())
  746. return vm.throw_completion<RangeError>(ErrorType::InvalidTimeValue);
  747. auto string = TRY_OR_THROW_OOM(vm, this_object->iso_date_string());
  748. return PrimitiveString::create(vm, move(string));
  749. }
  750. // 21.4.4.37 Date.prototype.toJSON ( key ), https://tc39.es/ecma262/#sec-date.prototype.tojson
  751. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_json)
  752. {
  753. auto this_value = vm.this_value();
  754. auto time_value = TRY(this_value.to_primitive(vm, Value::PreferredType::Number));
  755. if (time_value.is_number() && !time_value.is_finite_number())
  756. return js_null();
  757. return TRY(this_value.invoke(vm, vm.names.toISOString));
  758. }
  759. // 21.4.4.38 Date.prototype.toLocaleDateString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-date.prototype.tolocaledatestring
  760. // 19.4.2 Date.prototype.toLocaleDateString ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sup-date.prototype.tolocaledatestring
  761. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_locale_date_string)
  762. {
  763. auto& realm = *vm.current_realm();
  764. auto locales = vm.argument(0);
  765. auto options = vm.argument(1);
  766. // 1. Let x be ? thisTimeValue(this value).
  767. auto time = TRY(this_time_value(vm, vm.this_value()));
  768. // 2. If x is NaN, return "Invalid Date".
  769. if (isnan(time))
  770. return PrimitiveString::create(vm, "Invalid Date"_string);
  771. // 3. Let dateFormat be ? CreateDateTimeFormat(%DateTimeFormat%, locales, options, "date", "date").
  772. auto date_format = TRY(Intl::create_date_time_format(vm, realm.intrinsics().intl_date_time_format_constructor(), locales, options, Intl::OptionRequired::Date, Intl::OptionDefaults::Date));
  773. // 4. Return ? FormatDateTime(dateFormat, x).
  774. auto formatted = TRY(Intl::format_date_time(vm, date_format, time));
  775. return PrimitiveString::create(vm, move(formatted));
  776. }
  777. // 21.4.4.39 Date.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-date.prototype.tolocalestring
  778. // 19.4.1 Date.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sup-date.prototype.tolocalestring
  779. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_locale_string)
  780. {
  781. auto& realm = *vm.current_realm();
  782. auto locales = vm.argument(0);
  783. auto options = vm.argument(1);
  784. // 1. Let x be ? thisTimeValue(this value).
  785. auto time = TRY(this_time_value(vm, vm.this_value()));
  786. // 2. If x is NaN, return "Invalid Date".
  787. if (isnan(time))
  788. return PrimitiveString::create(vm, "Invalid Date"_string);
  789. // 3. Let dateFormat be ? CreateDateTimeFormat(%DateTimeFormat%, locales, options, "any", "all").
  790. auto date_format = TRY(Intl::create_date_time_format(vm, realm.intrinsics().intl_date_time_format_constructor(), locales, options, Intl::OptionRequired::Any, Intl::OptionDefaults::All));
  791. // 4. Return ? FormatDateTime(dateFormat, x).
  792. auto formatted = TRY(Intl::format_date_time(vm, date_format, time));
  793. return PrimitiveString::create(vm, move(formatted));
  794. }
  795. // 21.4.4.40 Date.prototype.toLocaleTimeString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-date.prototype.tolocaletimestring
  796. // 19.4.3 Date.prototype.toLocaleTimeString ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sup-date.prototype.tolocaletimestring
  797. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_locale_time_string)
  798. {
  799. auto& realm = *vm.current_realm();
  800. auto locales = vm.argument(0);
  801. auto options = vm.argument(1);
  802. // 1. Let x be ? thisTimeValue(this value).
  803. auto time = TRY(this_time_value(vm, vm.this_value()));
  804. // 2. If x is NaN, return "Invalid Date".
  805. if (isnan(time))
  806. return PrimitiveString::create(vm, "Invalid Date"_string);
  807. // 3. Let timeFormat be ? CreateDateTimeFormat(%DateTimeFormat%, locales, options, "time", "time").
  808. auto time_format = TRY(Intl::create_date_time_format(vm, realm.intrinsics().intl_date_time_format_constructor(), locales, options, Intl::OptionRequired::Time, Intl::OptionDefaults::Time));
  809. // 4. Return ? FormatDateTime(timeFormat, x).
  810. auto formatted = TRY(Intl::format_date_time(vm, time_format, time));
  811. return PrimitiveString::create(vm, move(formatted));
  812. }
  813. // 21.4.4.41 Date.prototype.toString ( ), https://tc39.es/ecma262/#sec-date.prototype.tostring
  814. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_string)
  815. {
  816. // 1. Let tv be ? thisTimeValue(this value).
  817. auto time = TRY(this_time_value(vm, vm.this_value()));
  818. // 2. Return ToDateString(tv).
  819. return PrimitiveString::create(vm, JS::to_date_string(time));
  820. }
  821. // 21.4.4.41.1 TimeString ( tv ), https://tc39.es/ecma262/#sec-timestring
  822. ByteString time_string(double time)
  823. {
  824. // 1. Let hour be ToZeroPaddedDecimalString(ℝ(HourFromTime(tv)), 2).
  825. auto hour = hour_from_time(time);
  826. // 2. Let minute be ToZeroPaddedDecimalString(ℝ(MinFromTime(tv)), 2).
  827. auto minute = min_from_time(time);
  828. // 3. Let second be ToZeroPaddedDecimalString(ℝ(SecFromTime(tv)), 2).
  829. auto second = sec_from_time(time);
  830. // 4. Return the string-concatenation of hour, ":", minute, ":", second, the code unit 0x0020 (SPACE), and "GMT".
  831. return ByteString::formatted("{:02}:{:02}:{:02} GMT", hour, minute, second);
  832. }
  833. // 21.4.4.41.2 DateString ( tv ), https://tc39.es/ecma262/#sec-datestring
  834. ByteString date_string(double time)
  835. {
  836. // 1. Let weekday be the Name of the entry in Table 62 with the Number WeekDay(tv).
  837. auto weekday = short_day_names[week_day(time)];
  838. // 2. Let month be the Name of the entry in Table 63 with the Number MonthFromTime(tv).
  839. auto month = short_month_names[month_from_time(time)];
  840. // 3. Let day be ToZeroPaddedDecimalString(ℝ(DateFromTime(tv)), 2).
  841. auto day = date_from_time(time);
  842. // 4. Let yv be YearFromTime(tv).
  843. auto year = year_from_time(time);
  844. // 5. If yv is +0𝔽 or yv > +0𝔽, let yearSign be the empty String; otherwise, let yearSign be "-".
  845. auto year_sign = year >= 0 ? ""sv : "-"sv;
  846. // 6. Let paddedYear be ToZeroPaddedDecimalString(abs(ℝ(yv)), 4).
  847. // 7. Return the string-concatenation of weekday, the code unit 0x0020 (SPACE), month, the code unit 0x0020 (SPACE), day, the code unit 0x0020 (SPACE), yearSign, and paddedYear.
  848. return ByteString::formatted("{} {} {:02} {}{:04}", weekday, month, day, year_sign, abs(year));
  849. }
  850. // 21.4.4.41.3 TimeZoneString ( tv ), https://tc39.es/ecma262/#sec-timezoneestring
  851. ByteString time_zone_string(double time)
  852. {
  853. // 1. Let systemTimeZoneIdentifier be SystemTimeZoneIdentifier().
  854. auto system_time_zone_identifier = JS::system_time_zone_identifier();
  855. double offset_nanoseconds { 0 };
  856. auto in_dst = Unicode::TimeZoneOffset::InDST::No;
  857. // 2. If IsTimeZoneOffsetString(systemTimeZoneIdentifier) is true, then
  858. if (is_time_zone_offset_string(system_time_zone_identifier)) {
  859. // a. Let offsetNs be ParseTimeZoneOffsetString(systemTimeZoneIdentifier).
  860. offset_nanoseconds = parse_time_zone_offset_string(system_time_zone_identifier);
  861. }
  862. // 3. Else,
  863. else {
  864. // a. Let offsetNs be GetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ℤ(ℝ(tv) × 10^6)).
  865. auto offset = get_named_time_zone_offset_milliseconds(system_time_zone_identifier, time);
  866. offset_nanoseconds = static_cast<double>(offset.offset.to_nanoseconds());
  867. in_dst = offset.in_dst;
  868. }
  869. // 4. Let offset be 𝔽(truncate(offsetNs / 106)).
  870. auto offset = trunc(offset_nanoseconds / 1e6);
  871. StringView offset_sign;
  872. // 5. If offset is +0𝔽 or offset > +0𝔽, then
  873. if (offset >= 0) {
  874. // a. Let offsetSign be "+".
  875. offset_sign = "+"sv;
  876. // b. Let absOffset be offset.
  877. }
  878. // 6. Else,
  879. else {
  880. // a. Let offsetSign be "-".
  881. offset_sign = "-"sv;
  882. // b. Let absOffset be -offset.
  883. offset *= -1;
  884. }
  885. // 7. Let offsetMin be ToZeroPaddedDecimalString(ℝ(MinFromTime(absOffset)), 2).
  886. auto offset_min = min_from_time(offset);
  887. // 8. Let offsetHour be ToZeroPaddedDecimalString(ℝ(HourFromTime(absOffset)), 2).
  888. auto offset_hour = hour_from_time(offset);
  889. // 9. Let tzName be an implementation-defined string that is either the empty String or the string-concatenation of the code unit 0x0020 (SPACE), the code unit 0x0028 (LEFT PARENTHESIS), an implementation-defined timezone name, and the code unit 0x0029 (RIGHT PARENTHESIS).
  890. auto tz_name = Unicode::current_time_zone();
  891. // Most implementations seem to prefer the long-form display name of the time zone. Not super important, but we may as well match that behavior.
  892. if (auto name = Unicode::time_zone_display_name(Unicode::default_locale(), tz_name, in_dst, time); name.has_value())
  893. tz_name = name.release_value();
  894. // 10. Return the string-concatenation of offsetSign, offsetHour, offsetMin, and tzName.
  895. return ByteString::formatted("{}{:02}{:02} ({})", offset_sign, offset_hour, offset_min, tz_name);
  896. }
  897. // 21.4.4.41.4 ToDateString ( tv ), https://tc39.es/ecma262/#sec-todatestring
  898. ByteString to_date_string(double time)
  899. {
  900. // 1. If tv is NaN, return "Invalid Date".
  901. if (Value(time).is_nan())
  902. return "Invalid Date"sv;
  903. // 2. Let t be LocalTime(tv).
  904. time = local_time(time);
  905. // 3. Return the string-concatenation of DateString(t), the code unit 0x0020 (SPACE), TimeString(t), and TimeZoneString(tv).
  906. return ByteString::formatted("{} {}{}", date_string(time), time_string(time), time_zone_string(time));
  907. }
  908. // 14.1.1 Date.prototype.toTemporalInstant ( ), https://tc39.es/proposal-temporal/#sec-date.prototype.totemporalinstant
  909. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_temporal_instant)
  910. {
  911. // 1. Let t be ? thisTimeValue(this value).
  912. auto t = TRY(this_time_value(vm, vm.this_value()));
  913. // 2. Let ns be ? NumberToBigInt(t) × ℤ(10^6).
  914. auto* ns = TRY(number_to_bigint(vm, Value(t)));
  915. ns = BigInt::create(vm, ns->big_integer().multiplied_by(Crypto::UnsignedBigInteger { 1'000'000 }));
  916. // 3. Return ! CreateTemporalInstant(ns).
  917. return MUST(Temporal::create_temporal_instant(vm, *ns));
  918. }
  919. // 21.4.4.42 Date.prototype.toTimeString ( ), https://tc39.es/ecma262/#sec-date.prototype.totimestring
  920. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_time_string)
  921. {
  922. // 1. Let O be this Date object.
  923. // 2. Let tv be ? thisTimeValue(O).
  924. auto time = TRY(this_time_value(vm, vm.this_value()));
  925. // 3. If tv is NaN, return "Invalid Date".
  926. if (isnan(time))
  927. return PrimitiveString::create(vm, "Invalid Date"_string);
  928. // 4. Let t be LocalTime(tv).
  929. // 5. Return the string-concatenation of TimeString(t) and TimeZoneString(tv).
  930. auto string = ByteString::formatted("{}{}", time_string(local_time(time)), time_zone_string(time));
  931. return PrimitiveString::create(vm, move(string));
  932. }
  933. // 21.4.4.43 Date.prototype.toUTCString ( ), https://tc39.es/ecma262/#sec-date.prototype.toutcstring
  934. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_utc_string)
  935. {
  936. // 1. Let O be this Date object.
  937. // 2. Let tv be ? thisTimeValue(O).
  938. auto time = TRY(this_time_value(vm, vm.this_value()));
  939. // 3. If tv is NaN, return "Invalid Date".
  940. if (isnan(time))
  941. return PrimitiveString::create(vm, "Invalid Date"_string);
  942. // 4. Let weekday be the Name of the entry in Table 62 with the Number WeekDay(tv).
  943. auto weekday = short_day_names[week_day(time)];
  944. // 5. Let month be the Name of the entry in Table 63 with the Number MonthFromTime(tv).
  945. auto month = short_month_names[month_from_time(time)];
  946. // 6. Let day be ToZeroPaddedDecimalString(ℝ(DateFromTime(tv)), 2).
  947. auto day = date_from_time(time);
  948. // 7. Let yv be YearFromTime(tv).
  949. auto year = year_from_time(time);
  950. // 8. If yv is +0𝔽 or yv > +0𝔽, let yearSign be the empty String; otherwise, let yearSign be "-".
  951. auto year_sign = year >= 0 ? ""sv : "-"sv;
  952. // 9. Let paddedYear be ToZeroPaddedDecimalString(abs(ℝ(yv)), 4).
  953. // 10. Return the string-concatenation of weekday, ",", the code unit 0x0020 (SPACE), day, the code unit 0x0020 (SPACE), month, the code unit 0x0020 (SPACE), yearSign, paddedYear, the code unit 0x0020 (SPACE), and TimeString(tv).
  954. auto string = ByteString::formatted("{}, {:02} {} {}{:04} {}", weekday, day, month, year_sign, abs(year), time_string(time));
  955. return PrimitiveString::create(vm, move(string));
  956. }
  957. // 21.4.4.45 Date.prototype [ @@toPrimitive ] ( hint ), https://tc39.es/ecma262/#sec-date.prototype-@@toprimitive
  958. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::symbol_to_primitive)
  959. {
  960. auto this_value = vm.this_value();
  961. if (!this_value.is_object())
  962. return vm.throw_completion<TypeError>(ErrorType::NotAnObject, this_value.to_string_without_side_effects());
  963. auto hint_value = vm.argument(0);
  964. if (!hint_value.is_string())
  965. return vm.throw_completion<TypeError>(ErrorType::InvalidHint, hint_value.to_string_without_side_effects());
  966. auto hint = hint_value.as_string().byte_string();
  967. Value::PreferredType try_first;
  968. if (hint == "string" || hint == "default")
  969. try_first = Value::PreferredType::String;
  970. else if (hint == "number")
  971. try_first = Value::PreferredType::Number;
  972. else
  973. return vm.throw_completion<TypeError>(ErrorType::InvalidHint, hint);
  974. return TRY(this_value.as_object().ordinary_to_primitive(try_first));
  975. }
  976. // B.2.4.1 Date.prototype.getYear ( ), https://tc39.es/ecma262/#sec-date.prototype.getyear
  977. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::get_year)
  978. {
  979. // 1. Let t be ? thisTimeValue(this value).
  980. auto time = TRY(this_time_value(vm, vm.this_value()));
  981. // 2. If t is NaN, return NaN.
  982. if (isnan(time))
  983. return js_nan();
  984. // 3. Return YearFromTime(LocalTime(t)) - 1900𝔽.
  985. return Value(year_from_time(local_time(time)) - 1900);
  986. }
  987. // B.2.4.2 Date.prototype.setYear ( year ), https://tc39.es/ecma262/#sec-date.prototype.setyear
  988. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::set_year)
  989. {
  990. // 1. Let t be ? thisTimeValue(this value).
  991. auto this_time = TRY(this_time_value(vm, vm.this_value()));
  992. // 2. If t is NaN, set t to +0𝔽; otherwise, set t to LocalTime(t).
  993. double time = 0;
  994. if (!isnan(this_time))
  995. time = local_time(this_time);
  996. // 3. Let y be ? ToNumber(year).
  997. auto year = TRY(vm.argument(0).to_number(vm)).as_double();
  998. auto this_object = MUST(typed_this_object(vm));
  999. // 4. If y is NaN, then
  1000. if (isnan(year)) {
  1001. // a. Set the [[DateValue]] internal slot of this Date object to NaN.
  1002. this_object->set_date_value(NAN);
  1003. // b. Return NaN.
  1004. return js_nan();
  1005. }
  1006. // 5. Let yi be ! ToIntegerOrInfinity(y).
  1007. auto year_integer = to_integer_or_infinity(year);
  1008. // 6. If 0 ≤ yi ≤ 99, let yyyy be 1900𝔽 + 𝔽(yi).
  1009. if (0 <= year_integer && year_integer <= 99)
  1010. year = 1900 + year_integer;
  1011. // 7. Else, let yyyy be y.
  1012. // 8. Let d be MakeDay(yyyy, MonthFromTime(t), DateFromTime(t)).
  1013. auto day = make_day(year, month_from_time(time), date_from_time(time));
  1014. // 9. Let date be UTC(MakeDate(d, TimeWithinDay(t))).
  1015. auto date = utc_time(make_date(day, time_within_day(time)));
  1016. // 10. Set the [[DateValue]] internal slot of this Date object to TimeClip(date).
  1017. auto new_date = time_clip(date);
  1018. this_object->set_date_value(new_date);
  1019. // 11. Return the value of the [[DateValue]] internal slot of this Date object.
  1020. return Value(new_date);
  1021. }
  1022. // B.2.4.3 Date.prototype.toGMTString ( ), https://tc39.es/ecma262/#sec-date.prototype.togmtstring
  1023. JS_DEFINE_NATIVE_FUNCTION(DatePrototype::to_gmt_string)
  1024. {
  1025. // NOTE: The toUTCString method is preferred. The toGMTString method is provided principally for compatibility with old code.
  1026. return to_utc_string(vm);
  1027. }
  1028. }