PlainTime.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /*
  2. * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
  3. * Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <LibJS/Runtime/AbstractOperations.h>
  8. #include <LibJS/Runtime/GlobalObject.h>
  9. #include <LibJS/Runtime/Object.h>
  10. #include <LibJS/Runtime/Temporal/Calendar.h>
  11. #include <LibJS/Runtime/Temporal/PlainTime.h>
  12. #include <LibJS/Runtime/Temporal/PlainTimeConstructor.h>
  13. namespace JS::Temporal {
  14. // 4 Temporal.PlainTime Objects, https://tc39.es/proposal-temporal/#sec-temporal-plaintime-objects
  15. PlainTime::PlainTime(u8 iso_hour, u8 iso_minute, u8 iso_second, u16 iso_millisecond, u16 iso_microsecond, u16 iso_nanosecond, Calendar& calendar, Object& prototype)
  16. : Object(prototype)
  17. , m_iso_hour(iso_hour)
  18. , m_iso_minute(iso_minute)
  19. , m_iso_second(iso_second)
  20. , m_iso_millisecond(iso_millisecond)
  21. , m_iso_microsecond(iso_microsecond)
  22. , m_iso_nanosecond(iso_nanosecond)
  23. , m_calendar(calendar)
  24. {
  25. }
  26. void PlainTime::visit_edges(Visitor& visitor)
  27. {
  28. visitor.visit(&m_calendar);
  29. }
  30. // 4.5.5 IsValidTime ( hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-isvalidtime
  31. bool is_valid_time(u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond)
  32. {
  33. // 1. Assert: hour, minute, second, millisecond, microsecond, and nanosecond are integers.
  34. // 2. If hour < 0 or hour > 23, then
  35. if (hour > 23) {
  36. // a. Return false.
  37. return false;
  38. }
  39. // 3. If minute < 0 or minute > 59, then
  40. if (minute > 59) {
  41. // a. Return false.
  42. return false;
  43. }
  44. // 4. If second < 0 or second > 59, then
  45. if (second > 59) {
  46. // a. Return false.
  47. return false;
  48. }
  49. // 5. If millisecond < 0 or millisecond > 999, then
  50. if (millisecond > 999) {
  51. // a. Return false.
  52. return false;
  53. }
  54. // 6. If microsecond < 0 or microsecond > 999, then
  55. if (microsecond > 999) {
  56. // a. Return false.
  57. return false;
  58. }
  59. // 7. If nanosecond < 0 or nanosecond > 999, then
  60. if (nanosecond > 999) {
  61. // a. Return false.
  62. return false;
  63. }
  64. // 8. Return true.
  65. return true;
  66. }
  67. // 4.5.6 BalanceTime ( hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-balancetime
  68. DaysAndTime balance_time(i64 hour, i64 minute, i64 second, i64 millisecond, i64 microsecond, i64 nanosecond)
  69. {
  70. // 1. Assert: hour, minute, second, millisecond, microsecond, and nanosecond are integers.
  71. // 2. Set microsecond to microsecond + floor(nanosecond / 1000).
  72. microsecond += nanosecond / 1000;
  73. // 3. Set nanosecond to nanosecond modulo 1000.
  74. nanosecond %= 1000;
  75. // 4. Set millisecond to millisecond + floor(microsecond / 1000).
  76. millisecond += microsecond / 1000;
  77. // 5. Set microsecond to microsecond modulo 1000.
  78. microsecond %= 1000;
  79. // 6. Set second to second + floor(millisecond / 1000).
  80. second += millisecond / 1000;
  81. // 7. Set millisecond to millisecond modulo 1000.
  82. millisecond %= 1000;
  83. // 8. Set minute to minute + floor(second / 60).
  84. minute += second / 60;
  85. // 9. Set second to second modulo 60.
  86. second %= 60;
  87. // 10. Set hour to hour + floor(minute / 60).
  88. hour += minute / 60;
  89. // 11. Set minute to minute modulo 60.
  90. minute %= 60;
  91. // 12. Let days be floor(hour / 24).
  92. u8 days = hour / 24;
  93. // 13. Set hour to hour modulo 24.
  94. hour %= 24;
  95. // 14. Return the new Record { [[Days]]: days, [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond }.
  96. return DaysAndTime {
  97. .days = static_cast<i32>(days),
  98. .hour = static_cast<u8>(hour),
  99. .minute = static_cast<u8>(minute),
  100. .second = static_cast<u8>(second),
  101. .millisecond = static_cast<u16>(millisecond),
  102. .microsecond = static_cast<u16>(microsecond),
  103. .nanosecond = static_cast<u16>(nanosecond),
  104. };
  105. }
  106. // 4.5.8 CreateTemporalTime ( hour, minute, second, millisecond, microsecond, nanosecond [ , newTarget ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtemporaltime
  107. PlainTime* create_temporal_time(GlobalObject& global_object, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond, FunctionObject* new_target)
  108. {
  109. auto& vm = global_object.vm();
  110. // 1. Assert: hour, minute, second, millisecond, microsecond and nanosecond are integers.
  111. // 2. If ! IsValidTime(hour, minute, second, millisecond, microsecond, nanosecond) is false, throw a RangeError exception.
  112. if (!is_valid_time(hour, minute, second, millisecond, microsecond, nanosecond)) {
  113. vm.throw_exception<RangeError>(global_object, ErrorType::TemporalInvalidPlainTime);
  114. return {};
  115. }
  116. // 3. If newTarget is not present, set it to %Temporal.PlainTime%.
  117. if (!new_target)
  118. new_target = global_object.temporal_plain_time_constructor();
  119. // 4. Let object be ? OrdinaryCreateFromConstructor(newTarget, "%Temporal.PlainTime.prototype%", « [[InitializedTemporalTime]], [[ISOHour]], [[ISOMinute]], [[ISOSecond]], [[ISOMillisecond]], [[ISOMicrosecond]], [[ISONanosecond]], [[Calendar]] »).
  120. // 5. Set object.[[ISOHour]] to hour.
  121. // 6. Set object.[[ISOMinute]] to minute.
  122. // 7. Set object.[[ISOSecond]] to second.
  123. // 8. Set object.[[ISOMillisecond]] to millisecond.
  124. // 9. Set object.[[ISOMicrosecond]] to microsecond.
  125. // 10. Set object.[[ISONanosecond]] to nanosecond.
  126. // 11. Set object.[[Calendar]] to ! GetISO8601Calendar().
  127. auto* object = ordinary_create_from_constructor<PlainTime>(global_object, *new_target, &GlobalObject::temporal_plain_time_prototype, hour, minute, second, millisecond, microsecond, nanosecond, *get_iso8601_calendar(global_object));
  128. if (vm.exception())
  129. return {};
  130. // 12. Return object.
  131. return object;
  132. }
  133. }