Calendar.h (12949B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef builtin_temporal_Calendar_h 8 #define builtin_temporal_Calendar_h 9 10 #include "mozilla/Assertions.h" 11 #include "mozilla/Attributes.h" 12 13 #include <stdint.h> 14 #include <string_view> 15 16 #include "js/RootingAPI.h" 17 #include "js/TypeDecls.h" 18 #include "js/Value.h" 19 #include "vm/NativeObject.h" 20 21 class JS_PUBLIC_API JSTracer; 22 23 namespace js { 24 struct ClassSpec; 25 } // namespace js 26 27 namespace js::temporal { 28 29 enum class CalendarId : int32_t { 30 ISO8601, 31 32 // Thai Buddhist solar calendar. 33 Buddhist, 34 35 // Chinese lunisolar calendar. 36 Chinese, 37 38 // Coptic calendar. 39 Coptic, 40 41 // Korean lunisolar calendar. 42 Dangi, 43 44 // Ethiopian Amete Mihret calendar. 45 Ethiopian, 46 47 // Ethiopian Amete Alem calendar. 48 EthiopianAmeteAlem, 49 50 // Gregorian calendar. 51 Gregorian, 52 53 // Hebrew lunisolar calendar. 54 Hebrew, 55 56 // Indian national calendar. 57 Indian, 58 59 // Islamic lunar calendars. 60 IslamicCivil, 61 IslamicTabular, 62 IslamicUmmAlQura, 63 64 // Japanese calendar. 65 Japanese, 66 67 // Persian solar Hijri calendar. 68 Persian, 69 70 // Republic of China (ROC) calendar. 71 ROC, 72 }; 73 74 inline constexpr auto availableCalendars = { 75 CalendarId::ISO8601, 76 CalendarId::Buddhist, 77 CalendarId::Chinese, 78 CalendarId::Coptic, 79 CalendarId::Dangi, 80 CalendarId::Ethiopian, 81 CalendarId::EthiopianAmeteAlem, 82 CalendarId::Gregorian, 83 CalendarId::Hebrew, 84 CalendarId::Indian, 85 CalendarId::IslamicCivil, 86 CalendarId::IslamicTabular, 87 // See Bug 1950425, this calendar is only available on Nightly due to 88 // inconsistencies between ICU4X and ICU4C. 89 #ifdef NIGHTLY_BUILD 90 CalendarId::IslamicUmmAlQura, 91 #endif 92 CalendarId::Japanese, 93 CalendarId::Persian, 94 CalendarId::ROC, 95 }; 96 97 /** 98 * AvailableCalendars ( ) 99 */ 100 constexpr auto& AvailableCalendars() { return availableCalendars; } 101 102 class CalendarObject : public NativeObject { 103 public: 104 static const JSClass class_; 105 static const JSClass& protoClass_; 106 107 static constexpr uint32_t IDENTIFIER_SLOT = 0; 108 static constexpr uint32_t SLOT_COUNT = 1; 109 110 CalendarId identifier() const { 111 return static_cast<CalendarId>(getFixedSlot(IDENTIFIER_SLOT).toInt32()); 112 } 113 114 private: 115 static const ClassSpec classSpec_; 116 }; 117 118 /** 119 * Calendar value, which is a string containing a canonical calendar identifier. 120 */ 121 class MOZ_STACK_CLASS CalendarValue final { 122 JS::Value value_{}; 123 124 public: 125 /** 126 * Default initialize this CalendarValue. 127 */ 128 CalendarValue() = default; 129 130 /** 131 * Default initialize this CalendarValue. 132 */ 133 explicit CalendarValue(const JS::Value& value) : value_(value) { 134 MOZ_ASSERT(value.isInt32()); 135 } 136 137 /** 138 * Initialize this CalendarValue with a canonical calendar identifier. 139 */ 140 explicit CalendarValue(CalendarId calendarId) 141 : value_(JS::Int32Value(static_cast<int32_t>(calendarId))) {} 142 143 /** 144 * Return true iff this CalendarValue is initialized with either a canonical 145 * calendar identifier or a calendar object. 146 */ 147 explicit operator bool() const { return !value_.isUndefined(); } 148 149 /** 150 * Return the slot Value representation of this CalendarValue. 151 */ 152 JS::Value toSlotValue() const { return value_; } 153 154 /** 155 * Return the calendar identifier. 156 */ 157 CalendarId identifier() const { 158 return static_cast<CalendarId>(value_.toInt32()); 159 } 160 161 void trace(JSTracer* trc); 162 163 JS::Value* valueDoNotUse() { return &value_; } 164 JS::Value const* valueDoNotUse() const { return &value_; } 165 }; 166 167 struct DateDuration; 168 struct ISODate; 169 struct ISODateTime; 170 class PlainDate; 171 class PlainMonthDayObject; 172 class PlainMonthDay; 173 class PlainYearMonthObject; 174 class PlainYearMonth; 175 class CalendarFields; 176 enum class TemporalOverflow; 177 enum class TemporalUnit; 178 179 /** 180 * ISODaysInMonth ( year, month ) 181 */ 182 int32_t ISODaysInMonth(int32_t year, int32_t month); 183 184 /** 185 * 21.4.1.12 MakeDay ( year, month, date ) 186 */ 187 int32_t MakeDay(const ISODate& date); 188 189 /** 190 * 21.4.1.13 MakeDate ( day, time ) 191 */ 192 int64_t MakeDate(const ISODateTime& dateTime); 193 194 /** 195 * Return the BCP 47 identifier of the calendar. 196 */ 197 std::string_view CalendarIdentifier(CalendarId calendarId); 198 199 /** 200 * Return the BCP 47 identifier of the calendar. 201 */ 202 inline std::string_view CalendarIdentifier(const CalendarValue& calendar) { 203 return CalendarIdentifier(calendar.identifier()); 204 } 205 206 /** 207 * CanonicalizeCalendar ( id ) 208 * 209 * Return the case-normalized calendar identifier if |id| is a built-in calendar 210 * identifier. Otherwise throws a RangeError. 211 */ 212 bool CanonicalizeCalendar(JSContext* cx, JS::Handle<JSString*> id, 213 JS::MutableHandle<CalendarValue> result); 214 215 /** 216 * ToTemporalCalendarSlotValue ( temporalCalendarLike ) 217 */ 218 bool ToTemporalCalendar(JSContext* cx, 219 JS::Handle<JS::Value> temporalCalendarLike, 220 JS::MutableHandle<CalendarValue> result); 221 222 /** 223 * GetTemporalCalendarWithISODefault ( item ) 224 */ 225 bool GetTemporalCalendarWithISODefault(JSContext* cx, 226 JS::Handle<JSObject*> item, 227 JS::MutableHandle<CalendarValue> result); 228 229 /** 230 * CalendarDateAdd ( calendar, isoDate, duration, overflow ) 231 */ 232 bool CalendarDateAdd(JSContext* cx, JS::Handle<CalendarValue> calendar, 233 const ISODate& isoDate, const DateDuration& duration, 234 TemporalOverflow overflow, ISODate* result); 235 236 /** 237 * CalendarDateUntil ( calendar, one, two, largestUnit ) 238 */ 239 bool CalendarDateUntil(JSContext* cx, JS::Handle<CalendarValue> calendar, 240 const ISODate& one, const ISODate& two, 241 TemporalUnit largestUnit, DateDuration* result); 242 243 /** 244 * CalendarISOToDate ( calendar, isoDate ) 245 * 246 * When accessing the [[Era]] of the returned Calendar Date Record. 247 */ 248 bool CalendarEra(JSContext* cx, JS::Handle<CalendarValue> calendar, 249 const ISODate& date, JS::MutableHandle<JS::Value> result); 250 251 /** 252 * CalendarISOToDate ( calendar, isoDate ) 253 * 254 * When accessing the [[EraYear]] of the returned Calendar Date Record. 255 */ 256 bool CalendarEraYear(JSContext* cx, JS::Handle<CalendarValue> calendar, 257 const ISODate& date, JS::MutableHandle<JS::Value> result); 258 /** 259 * CalendarISOToDate ( calendar, isoDate ) 260 * 261 * When accessing the [[Year]] of the returned Calendar Date Record. 262 */ 263 bool CalendarYear(JSContext* cx, JS::Handle<CalendarValue> calendar, 264 const ISODate& date, JS::MutableHandle<JS::Value> result); 265 266 /** 267 * CalendarISOToDate ( calendar, isoDate ) 268 * 269 * When accessing the [[Month]] of the returned Calendar Date Record. 270 */ 271 bool CalendarMonth(JSContext* cx, JS::Handle<CalendarValue> calendar, 272 const ISODate& date, JS::MutableHandle<JS::Value> result); 273 274 /** 275 * CalendarISOToDate ( calendar, isoDate ) 276 * 277 * When accessing the [[MonthCode]] of the returned Calendar Date Record. 278 */ 279 bool CalendarMonthCode(JSContext* cx, JS::Handle<CalendarValue> calendar, 280 const ISODate& date, 281 JS::MutableHandle<JS::Value> result); 282 283 /** 284 * CalendarISOToDate ( calendar, isoDate ) 285 * 286 * When accessing the [[Day]] of the returned Calendar Date Record. 287 */ 288 bool CalendarDay(JSContext* cx, JS::Handle<CalendarValue> calendar, 289 const ISODate& date, JS::MutableHandle<JS::Value> result); 290 291 /** 292 * CalendarISOToDate ( calendar, isoDate ) 293 * 294 * When accessing the [[DayOfWeek]] of the returned Calendar Date Record. 295 */ 296 bool CalendarDayOfWeek(JSContext* cx, JS::Handle<CalendarValue> calendar, 297 const ISODate& date, 298 JS::MutableHandle<JS::Value> result); 299 300 /** 301 * CalendarISOToDate ( calendar, isoDate ) 302 * 303 * When accessing the [[DayOfYear]] of the returned Calendar Date Record. 304 */ 305 bool CalendarDayOfYear(JSContext* cx, JS::Handle<CalendarValue> calendar, 306 const ISODate& date, 307 JS::MutableHandle<JS::Value> result); 308 309 /** 310 * CalendarISOToDate ( calendar, isoDate ) 311 * 312 * When accessing the [[Week]] field of the [[WeekOfYear]] of the returned 313 * Calendar Date Record. 314 */ 315 bool CalendarWeekOfYear(JSContext* cx, JS::Handle<CalendarValue> calendar, 316 const ISODate& date, 317 JS::MutableHandle<JS::Value> result); 318 319 /** 320 * CalendarISOToDate ( calendar, isoDate ) 321 * 322 * When accessing the [[Year]] field of the [[WeekOfYear]] of the returned 323 * Calendar Date Record. 324 */ 325 bool CalendarYearOfWeek(JSContext* cx, JS::Handle<CalendarValue> calendar, 326 const ISODate& date, 327 JS::MutableHandle<JS::Value> result); 328 329 /** 330 * * CalendarISOToDate ( calendar, isoDate ) 331 * 332 * When accessing the [[DaysInWeek]] of the returned Calendar Date Record. 333 */ 334 bool CalendarDaysInWeek(JSContext* cx, JS::Handle<CalendarValue> calendar, 335 const ISODate& date, 336 JS::MutableHandle<JS::Value> result); 337 338 /** 339 * * CalendarISOToDate ( calendar, isoDate ) 340 * 341 * When accessing the [[DaysInMonth]] of the returned Calendar Date Record. 342 */ 343 bool CalendarDaysInMonth(JSContext* cx, JS::Handle<CalendarValue> calendar, 344 const ISODate& date, 345 JS::MutableHandle<JS::Value> result); 346 347 /** 348 * CalendarISOToDate ( calendar, isoDate ) 349 * 350 * When accessing the [[DaysInYear]] of the returned Calendar Date Record. 351 */ 352 bool CalendarDaysInYear(JSContext* cx, JS::Handle<CalendarValue> calendar, 353 const ISODate& date, 354 JS::MutableHandle<JS::Value> result); 355 356 /** 357 * * CalendarISOToDate ( calendar, isoDate ) 358 * 359 * When accessing the [[MonthsInYear]] of the returned Calendar Date Record. 360 */ 361 bool CalendarMonthsInYear(JSContext* cx, JS::Handle<CalendarValue> calendar, 362 const ISODate& date, 363 JS::MutableHandle<JS::Value> result); 364 365 /** 366 * CalendarISOToDate ( calendar, isoDate ) 367 * 368 * When accessing the [[InLeapYear]] of the returned Calendar Date Record. 369 */ 370 bool CalendarInLeapYear(JSContext* cx, JS::Handle<CalendarValue> calendar, 371 const ISODate& date, 372 JS::MutableHandle<JS::Value> result); 373 374 /** 375 * CalendarDateFromFields ( calendar, fields, overflow ) 376 */ 377 bool CalendarDateFromFields(JSContext* cx, JS::Handle<CalendarValue> calendar, 378 JS::Handle<CalendarFields> fields, 379 TemporalOverflow overflow, 380 MutableHandle<PlainDate> result); 381 382 /** 383 * CalendarYearMonthFromFields ( calendar, fields, overflow ) 384 */ 385 bool CalendarYearMonthFromFields(JSContext* cx, 386 JS::Handle<CalendarValue> calendar, 387 JS::Handle<CalendarFields> fields, 388 TemporalOverflow overflow, 389 JS::MutableHandle<PlainYearMonth> result); 390 391 /** 392 * CalendarMonthDayFromFields ( calendar, fields, overflow ) 393 */ 394 bool CalendarMonthDayFromFields(JSContext* cx, 395 JS::Handle<CalendarValue> calendar, 396 JS::Handle<CalendarFields> fields, 397 TemporalOverflow overflow, 398 JS::MutableHandle<PlainMonthDay> result); 399 400 /** 401 * CalendarEquals ( one, two ) 402 */ 403 inline bool CalendarEquals(const CalendarValue& one, const CalendarValue& two) { 404 // Steps 1-2. 405 return one.identifier() == two.identifier(); 406 } 407 408 // Helper for MutableWrappedPtrOperations. 409 bool WrapCalendarValue(JSContext* cx, JS::MutableHandle<JS::Value> calendar); 410 411 } /* namespace js::temporal */ 412 413 namespace js { 414 415 template <typename Wrapper> 416 class WrappedPtrOperations<temporal::CalendarValue, Wrapper> { 417 const auto& container() const { 418 return static_cast<const Wrapper*>(this)->get(); 419 } 420 421 public: 422 explicit operator bool() const { return bool(container()); } 423 424 JS::Handle<JS::Value> toSlotValue() const { 425 return JS::Handle<JS::Value>::fromMarkedLocation( 426 container().valueDoNotUse()); 427 } 428 429 temporal::CalendarId identifier() const { return container().identifier(); } 430 }; 431 432 template <typename Wrapper> 433 class MutableWrappedPtrOperations<temporal::CalendarValue, Wrapper> 434 : public WrappedPtrOperations<temporal::CalendarValue, Wrapper> { 435 auto& container() { return static_cast<Wrapper*>(this)->get(); } 436 437 JS::MutableHandle<JS::Value> toMutableValue() { 438 return JS::MutableHandle<JS::Value>::fromMarkedLocation( 439 container().valueDoNotUse()); 440 } 441 442 public: 443 bool wrap(JSContext* cx) { 444 return temporal::WrapCalendarValue(cx, toMutableValue()); 445 } 446 }; 447 448 } /* namespace js */ 449 450 #endif /* builtin_temporal_Calendar_h */