LibJS: Introduce Time Zone Identifier Parse Records to Temporal

This is an editorial change in the Temporal proposal. See:
https://github.com/tc39/proposal-temporal/commit/96bb9b0

Note that we already had a struct for this, but now that it has a proper
name and spec link, this renames it to match other Parse Records and
places it alongside them.
This commit is contained in:
Timothy Flynn
2025-11-12 15:10:32 -05:00
committed by Tim Flynn
parent ae73280178
commit 462e7b0c87
Notes: github-actions[bot] 2025-11-12 21:21:24 +00:00
6 changed files with 30 additions and 29 deletions

View File

@@ -314,7 +314,6 @@ struct ISOYearMonth;
struct ParseResult;
struct PartialDuration;
struct Time;
struct TimeZone;
struct TimeZoneOffset;
};

View File

@@ -1117,7 +1117,7 @@ Crypto::SignedBigInteger round_number_to_increment_as_if_positive(Crypto::Signed
return rounded.multiplied_by(increment);
}
// 13.34 ParseISODateTime ( isoString, allowedFormats ), https://tc39.es/proposal-temporal/#sec-temporal-parseisodatetime
// 13.35 ParseISODateTime ( isoString, allowedFormats ), https://tc39.es/proposal-temporal/#sec-temporal-parseisodatetime
ThrowCompletionOr<ParsedISODateTime> parse_iso_date_time(VM& vm, StringView iso_string, ReadonlySpan<Production> allowed_formats)
{
// 1. Let parseResult be EMPTY.
@@ -1333,7 +1333,7 @@ ThrowCompletionOr<ParsedISODateTime> parse_iso_date_time(VM& vm, StringView iso_
return ParsedISODateTime { .year = year_return, .month = static_cast<u8>(month_value), .day = static_cast<u8>(day_value), .time = move(time), .time_zone = move(time_zone_result), .calendar = move(calendar) };
}
// 13.35 ParseTemporalCalendarString ( string ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporalcalendarstring
// 13.36 ParseTemporalCalendarString ( string ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporalcalendarstring
ThrowCompletionOr<String> parse_temporal_calendar_string(VM& vm, String const& string)
{
// 1. Let parseResult be Completion(ParseISODateTime(string, « TemporalDateTimeString[+Zoned], TemporalDateTimeString[~Zoned],
@@ -1370,7 +1370,7 @@ ThrowCompletionOr<String> parse_temporal_calendar_string(VM& vm, String const& s
return string;
}
// 13.36 ParseTemporalDurationString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaldurationstring
// 13.37 ParseTemporalDurationString ( isoString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaldurationstring
ThrowCompletionOr<GC::Ref<Duration>> parse_temporal_duration_string(VM& vm, StringView iso_string)
{
// 1. Let duration be ParseText(StringToCodePoints(isoString), TemporalDurationString).
@@ -1590,8 +1590,8 @@ ThrowCompletionOr<GC::Ref<Duration>> parse_temporal_duration_string(VM& vm, Stri
return TRY(create_temporal_duration(vm, years_value, months_value, weeks_value, days_value, hours_value, factored_minutes_value, factored_seconds_value, factored_milliseconds_value, factored_microseconds_value, factored_nanoseconds_value));
}
// 13.37 ParseTemporalTimeZoneString ( timeZoneString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaltimezonestring
ThrowCompletionOr<TimeZone> parse_temporal_time_zone_string(VM& vm, StringView time_zone_string)
// 13.38 ParseTemporalTimeZoneString ( timeZoneString ), https://tc39.es/proposal-temporal/#sec-temporal-parsetemporaltimezonestring
ThrowCompletionOr<ParsedTimeZoneIdentifier> parse_temporal_time_zone_string(VM& vm, StringView time_zone_string)
{
// 1. Let parseResult be ParseText(StringToCodePoints(timeZoneString), TimeZoneIdentifier).
auto parse_result = parse_iso8601(Production::TimeZoneIdentifier, time_zone_string);
@@ -1640,7 +1640,7 @@ ThrowCompletionOr<TimeZone> parse_temporal_time_zone_string(VM& vm, StringView t
return vm.throw_completion<RangeError>(ErrorType::TemporalInvalidTimeZoneString, time_zone_string);
}
// 13.40 ToOffsetString ( argument ), https://tc39.es/proposal-temporal/#sec-temporal-tooffsetstring
// 13.41 ToOffsetString ( argument ), https://tc39.es/proposal-temporal/#sec-temporal-tooffsetstring
ThrowCompletionOr<String> to_offset_string(VM& vm, Value argument)
{
// 1. Let offset be ? ToPrimitive(argument, STRING).
@@ -1657,7 +1657,7 @@ ThrowCompletionOr<String> to_offset_string(VM& vm, Value argument)
return offset.as_string().utf8_string();
}
// 13.41 ISODateToFields ( calendar, isoDate, type ), https://tc39.es/proposal-temporal/#sec-temporal-isodatetofields
// 13.42 ISODateToFields ( calendar, isoDate, type ), https://tc39.es/proposal-temporal/#sec-temporal-isodatetofields
CalendarFields iso_date_to_fields(StringView calendar, ISODate iso_date, DateType type)
{
// 1. Let fields be an empty Calendar Fields Record with all fields set to unset.
@@ -1685,7 +1685,7 @@ CalendarFields iso_date_to_fields(StringView calendar, ISODate iso_date, DateTyp
return fields;
}
// 13.42 GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits, fallbackSmallestUnit, smallestLargestDefaultUnit ), https://tc39.es/proposal-temporal/#sec-temporal-getdifferencesettings
// 13.43 GetDifferenceSettings ( operation, options, unitGroup, disallowedUnits, fallbackSmallestUnit, smallestLargestDefaultUnit ), https://tc39.es/proposal-temporal/#sec-temporal-getdifferencesettings
ThrowCompletionOr<DifferenceSettings> get_difference_settings(VM& vm, DurationOperation operation, Object const& options, UnitGroup unit_group, ReadonlySpan<Unit> disallowed_units, Unit fallback_smallest_unit, Unit smallest_largest_default_unit)
{
// 1. NOTE: The following steps read options and perform independent validation in alphabetical order.

View File

@@ -194,12 +194,12 @@ Crypto::SignedBigInteger round_number_to_increment_as_if_positive(Crypto::Signed
ThrowCompletionOr<ParsedISODateTime> parse_iso_date_time(VM&, StringView iso_string, ReadonlySpan<Production> allowed_formats);
ThrowCompletionOr<String> parse_temporal_calendar_string(VM&, String const&);
ThrowCompletionOr<GC::Ref<Duration>> parse_temporal_duration_string(VM&, StringView iso_string);
ThrowCompletionOr<TimeZone> parse_temporal_time_zone_string(VM&, StringView time_zone_string);
ThrowCompletionOr<ParsedTimeZoneIdentifier> parse_temporal_time_zone_string(VM&, StringView time_zone_string);
ThrowCompletionOr<String> to_offset_string(VM&, Value argument);
CalendarFields iso_date_to_fields(StringView calendar, ISODate, DateType);
ThrowCompletionOr<DifferenceSettings> get_difference_settings(VM&, DurationOperation, Object const& options, UnitGroup, ReadonlySpan<Unit> disallowed_units, Unit fallback_smallest_unit, Unit smallest_largest_default_unit);
// 13.39 ToIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-tointegerwithtruncation
// 13.40 ToIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-tointegerwithtruncation
template<typename... Args>
ThrowCompletionOr<double> to_integer_with_truncation(VM& vm, Value argument, ErrorType const& error_type, Args&&... args)
{
@@ -214,7 +214,7 @@ ThrowCompletionOr<double> to_integer_with_truncation(VM& vm, Value argument, Err
return trunc(number.as_double());
}
// 13.39 ToIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-tointegerwithtruncation
// 13.40 ToIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-tointegerwithtruncation
// AD-HOC: We often need to use this AO when we have a parsed StringView. This overload allows callers to avoid creating
// a PrimitiveString for the primary definition.
template<typename... Args>
@@ -231,7 +231,7 @@ ThrowCompletionOr<double> to_integer_with_truncation(VM& vm, StringView argument
return trunc(number);
}
// 13.38 ToPositiveIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-topositiveintegerwithtruncation
// 13.39 ToPositiveIntegerWithTruncation ( argument ), https://tc39.es/proposal-temporal/#sec-topositiveintegerwithtruncation
template<typename... Args>
ThrowCompletionOr<double> to_positive_integer_with_truncation(VM& vm, Value argument, ErrorType const& error_type, Args&&... args)
{

View File

@@ -57,7 +57,13 @@ struct ParsedISOTimeZone {
Optional<String> time_zone_annotation;
};
// 13.33 ISO Date-Time Parse Records, https://tc39.es/proposal-temporal/#sec-temporal-iso-date-time-parse-records
// 13.33 Time Zone Identifier Parse Records, https://tc39.es/proposal-temporal/#sec-temporal-time-zone-identifier-parse-records
struct ParsedTimeZoneIdentifier {
Optional<String> name;
Optional<i64> offset_minutes;
};
// 13.34 ISO Date-Time Parse Records, https://tc39.es/proposal-temporal/#sec-temporal-iso-date-time-parse-records
struct ParsedISODateTime {
struct StartOfDay { };

View File

@@ -403,7 +403,7 @@ bool time_zone_equals(StringView one, StringView two)
}
// 11.1.16 ParseTimeZoneIdentifier ( identifier ), https://tc39.es/proposal-temporal/#sec-parsetimezoneidentifier
ThrowCompletionOr<TimeZone> parse_time_zone_identifier(VM& vm, StringView identifier)
ThrowCompletionOr<ParsedTimeZoneIdentifier> parse_time_zone_identifier(VM& vm, StringView identifier)
{
// 1. Let parseResult be ParseText(StringToCodePoints(identifier), TimeZoneIdentifier).
auto parse_result = parse_iso8601(Production::TimeZoneIdentifier, identifier);
@@ -416,7 +416,7 @@ ThrowCompletionOr<TimeZone> parse_time_zone_identifier(VM& vm, StringView identi
}
// 11.1.16 ParseTimeZoneIdentifier ( identifier ), https://tc39.es/proposal-temporal/#sec-parsetimezoneidentifier
TimeZone parse_time_zone_identifier(StringView identifier)
ParsedTimeZoneIdentifier parse_time_zone_identifier(StringView identifier)
{
// OPTIMIZATION: Some callers can assume that parsing will succeed.
@@ -428,7 +428,7 @@ TimeZone parse_time_zone_identifier(StringView identifier)
}
// 11.1.16 ParseTimeZoneIdentifier ( identifier ), https://tc39.es/proposal-temporal/#sec-parsetimezoneidentifier
TimeZone parse_time_zone_identifier(ParseResult const& parse_result)
ParsedTimeZoneIdentifier parse_time_zone_identifier(ParseResult const& parse_result)
{
// OPTIMIZATION: Some callers will have already parsed and validated the time zone identifier.
@@ -437,8 +437,8 @@ TimeZone parse_time_zone_identifier(ParseResult const& parse_result)
// a. Let name be the source text matched by the TimeZoneIANAName Parse Node contained within parseResult.
// b. NOTE: name is syntactically valid, but does not necessarily conform to IANA Time Zone Database naming
// guidelines or correspond with an available named time zone identifier.
// c. Return the Record { [[Name]]: CodePointsToString(name), [[OffsetMinutes]]: empty }.
return TimeZone { .name = String::from_utf8_without_validation(parse_result.time_zone_iana_name->bytes()), .offset_minutes = {} };
// c. Return Time Zone Identifier Parse Record { [[Name]]: CodePointsToString(name), [[OffsetMinutes]]: EMPTY }.
return ParsedTimeZoneIdentifier { .name = String::from_utf8_without_validation(parse_result.time_zone_iana_name->bytes()), .offset_minutes = {} };
}
// 4. Else,
else {
@@ -455,8 +455,8 @@ TimeZone parse_time_zone_identifier(ParseResult const& parse_result)
// e. Assert: offsetMinutes is an integer.
VERIFY(trunc(offset_minutes) == offset_minutes);
// f. Return the Record { [[Name]]: empty, [[OffsetMinutes]]: offsetMinutes }.
return TimeZone { .name = {}, .offset_minutes = static_cast<i64>(offset_minutes) };
// f. Return Time Zone Identifier Parse Record { [[Name]]: EMPTY, [[OffsetMinutes]]: offsetMinutes }.
return ParsedTimeZoneIdentifier { .name = {}, .offset_minutes = static_cast<i64>(offset_minutes) };
}
}

View File

@@ -12,15 +12,11 @@
#include <LibCrypto/BigInt/SignedBigInteger.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/Temporal/AbstractOperations.h>
#include <LibJS/Runtime/Temporal/ISORecords.h>
#include <LibJS/Runtime/Value.h>
namespace JS::Temporal {
struct TimeZone {
Optional<String> name;
Optional<i64> offset_minutes;
};
ISODateTime get_iso_parts_from_epoch(Crypto::SignedBigInteger const& epoch_nanoseconds);
Optional<Crypto::SignedBigInteger> get_named_time_zone_next_transition(StringView time_zone, Crypto::SignedBigInteger const& epoch_nanoseconds);
Optional<Crypto::SignedBigInteger> get_named_time_zone_previous_transition(StringView time_zone, Crypto::SignedBigInteger const& epoch_nanoseconds);
@@ -36,8 +32,8 @@ ThrowCompletionOr<Crypto::SignedBigInteger> disambiguate_possible_epoch_nanoseco
ThrowCompletionOr<Vector<Crypto::SignedBigInteger>> get_possible_epoch_nanoseconds(VM&, StringView time_zone, ISODateTime const&);
ThrowCompletionOr<Crypto::SignedBigInteger> get_start_of_day(VM&, StringView time_zone, ISODate);
bool time_zone_equals(StringView one, StringView two);
ThrowCompletionOr<TimeZone> parse_time_zone_identifier(VM&, StringView identifier);
TimeZone parse_time_zone_identifier(StringView identifier);
TimeZone parse_time_zone_identifier(ParseResult const&);
ThrowCompletionOr<ParsedTimeZoneIdentifier> parse_time_zone_identifier(VM&, StringView identifier);
ParsedTimeZoneIdentifier parse_time_zone_identifier(StringView identifier);
ParsedTimeZoneIdentifier parse_time_zone_identifier(ParseResult const&);
}