mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 00:27:43 +00:00
LibJS: Support non-UTC time zones in Temporal :^)
We can now recognize & normalize all time zones from the IANA time zone
database and not just 'UTC', which makes the LibJS Temporal
implementation a lot more useful! Thanks to the newly added LibTimeZone,
this was incredibly easy to implement :^)
This already includes these recent editorial changes in the Temporal
spec: 27bffe1
This commit is contained in:
parent
205d63c3f0
commit
d527eb62da
5 changed files with 49 additions and 27 deletions
|
@ -16,6 +16,7 @@
|
|||
#include <LibJS/Runtime/Temporal/TimeZone.h>
|
||||
#include <LibJS/Runtime/Temporal/TimeZoneConstructor.h>
|
||||
#include <LibJS/Runtime/Temporal/ZonedDateTime.h>
|
||||
#include <LibTimeZone/TimeZone.h>
|
||||
|
||||
namespace JS::Temporal {
|
||||
|
||||
|
@ -27,35 +28,30 @@ TimeZone::TimeZone(String identifier, Object& prototype)
|
|||
}
|
||||
|
||||
// 11.1.1 IsValidTimeZoneName ( timeZone ), https://tc39.es/proposal-temporal/#sec-isvalidtimezonename
|
||||
// NOTE: This is the minimum implementation of IsValidTimeZoneName, supporting only the "UTC" time zone.
|
||||
// 15.1.1 IsValidTimeZoneName ( timeZone ), https://tc39.es/proposal-temporal/#sup-isvalidtimezonename
|
||||
bool is_valid_time_zone_name(String const& time_zone)
|
||||
{
|
||||
// 1. Assert: Type(timeZone) is String.
|
||||
|
||||
// 2. Let tzText be ! StringToCodePoints(timeZone).
|
||||
// 3. Let tzUpperText be the result of toUppercase(tzText), according to the Unicode Default Case Conversion algorithm.
|
||||
// 4. Let tzUpper be ! CodePointsToString(tzUpperText).
|
||||
auto tz_upper = time_zone.to_uppercase();
|
||||
|
||||
// 5. If tzUpper and "UTC" are the same sequence of code points, return true.
|
||||
if (tz_upper == "UTC")
|
||||
return true;
|
||||
|
||||
// 6. Return false.
|
||||
return false;
|
||||
// 1. If one of the Zone or Link names of the IANA Time Zone Database is an ASCII-case-insensitive match of timeZone as described in 6.1, return true.
|
||||
// 2. If timeZone is an ASCII-case-insensitive match of "UTC", return true.
|
||||
// 3. Return false.
|
||||
// NOTE: When LibTimeZone is built without ENABLE_TIME_ZONE_DATA, this only recognizes 'UTC',
|
||||
// which matches the minimum requirements of the Temporal spec.
|
||||
return ::TimeZone::time_zone_from_string(time_zone).has_value();
|
||||
}
|
||||
|
||||
// 11.1.2 CanonicalizeTimeZoneName ( timeZone ), https://tc39.es/proposal-temporal/#sec-canonicalizetimezonename
|
||||
// NOTE: This is the minimum implementation of CanonicalizeTimeZoneName, supporting only the "UTC" time zone.
|
||||
// 15.1.2 CanonicalizeTimeZoneName ( timeZone ), https://tc39.es/proposal-temporal/#sup-canonicalizetimezonename
|
||||
String canonicalize_time_zone_name(String const& time_zone)
|
||||
{
|
||||
// 1. Assert: Type(timeZone) is String.
|
||||
// 1. Let ianaTimeZone be the String value of the Zone or Link name of the IANA Time Zone Database that is an ASCII-case-insensitive match of timeZone as described in 6.1.
|
||||
// 2. If ianaTimeZone is a Link name, let ianaTimeZone be the String value of the corresponding Zone name as specified in the file backward of the IANA Time Zone Database.
|
||||
auto iana_time_zone = ::TimeZone::canonicalize_time_zone(time_zone);
|
||||
|
||||
// 2. Assert: ! IsValidTimeZoneName(timeZone) is true.
|
||||
VERIFY(is_valid_time_zone_name(time_zone));
|
||||
// 3. If ianaTimeZone is "Etc/UTC" or "Etc/GMT", return "UTC".
|
||||
// NOTE: This is already done in canonicalize_time_zone().
|
||||
|
||||
// 3. Return "UTC".
|
||||
return "UTC";
|
||||
// 4. Return ianaTimeZone.
|
||||
return *iana_time_zone;
|
||||
}
|
||||
|
||||
// 11.1.3 DefaultTimeZone ( ), https://tc39.es/proposal-temporal/#sec-defaulttimezone
|
||||
|
@ -160,12 +156,12 @@ ISODateTime get_iso_parts_from_epoch(BigInt const& epoch_nanoseconds)
|
|||
}
|
||||
|
||||
// 11.6.4 GetIANATimeZoneEpochValue ( timeZoneIdentifier, year, month, day, hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-getianatimezoneepochvalue
|
||||
MarkedValueList get_iana_time_zone_epoch_value(GlobalObject& global_object, StringView time_zone_identifier, i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond)
|
||||
MarkedValueList get_iana_time_zone_epoch_value(GlobalObject& global_object, [[maybe_unused]] StringView time_zone_identifier, i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond)
|
||||
{
|
||||
// The abstract operation GetIANATimeZoneEpochValue is an implementation-defined algorithm that returns a List of integers. Each integer in the List represents a number of nanoseconds since the Unix epoch in UTC that may correspond to the given calendar date and wall-clock time in the IANA time zone identified by timeZoneIdentifier.
|
||||
// When the input represents a local time repeating multiple times at a negative time zone transition (e.g. when the daylight saving time ends or the time zone offset is decreased due to a time zone rule change), the returned List will have more than one element. When the input represents a skipped local time at a positive time zone transition (e.g. when the daylight saving time starts or the time zone offset is increased due to a time zone rule change), the returned List will be empty. Otherwise, the returned List will have one element.
|
||||
|
||||
VERIFY(time_zone_identifier == "UTC"sv);
|
||||
// FIXME: Implement this properly for non-UTC timezones.
|
||||
// FIXME: MarkedValueList<T> for T != Value would still be nice.
|
||||
auto& vm = global_object.vm();
|
||||
auto list = MarkedValueList { vm.heap() };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue