LibTimeZone+Userland: Change timezone functions to use UnixDateTime

This incurs a whole host of changes in, among others, JavaScript Intl
and Date.
This commit is contained in:
kleines Filmröllchen 2023-03-13 22:28:08 +01:00 committed by Jelle Raaijmakers
parent 939600d2d4
commit 82c681e44b
Notes: sideshowbarker 2024-07-17 01:10:58 +09:00
13 changed files with 43 additions and 43 deletions

View file

@ -110,7 +110,7 @@ struct AK::Formatter<DaylightSavingsOffset> : Formatter<FormatString> {
ErrorOr<void> format(FormatBuilder& builder, DaylightSavingsOffset const& dst_offset)
{
auto format_time = [&](auto year) {
return DeprecatedString::formatted("AK::Duration::from_timestamp({}, 1, 1, 0, 0, 0, 0)", year);
return DeprecatedString::formatted("AK::UnixDateTime::from_unix_time_parts({}, 1, 1, 0, 0, 0, 0)", year);
};
static DeprecatedString max_year_as_time("max_year_as_time"sv);
@ -494,13 +494,13 @@ static ErrorOr<void> generate_time_zone_data_implementation(Core::InputBufferedF
namespace TimeZone {
static constexpr auto max_year_as_time = AK::Duration::from_timestamp(NumericLimits<u16>::max(), 1, 1, 0, 0, 0, 0);
static constexpr auto max_year_as_time = AK::UnixDateTime::from_unix_time_parts(NumericLimits<u16>::max(), 1, 1, 0, 0, 0, 0);
struct DateTime {
AK::Duration time_since_epoch() const
AK::UnixDateTime time_since_epoch() const
{
// FIXME: This implementation does not take last_weekday, after_weekday, or before_weekday into account.
return AK::Duration::from_timestamp(year, month, day, hour, minute, second, 0);
return AK::UnixDateTime::from_unix_time_parts(year, month, day, hour, minute, second, 0);
}
u16 year { 0 };
@ -530,17 +530,17 @@ struct TimeZoneOffset {
};
struct DaylightSavingsOffset {
AK::Duration time_in_effect(AK::Duration time) const
AK::UnixDateTime time_in_effect(AK::UnixDateTime time) const
{
auto in_effect = this->in_effect;
in_effect.year = seconds_since_epoch_to_year(time.to_seconds());
in_effect.year = seconds_since_epoch_to_year(time.seconds_since_epoch());
return in_effect.time_since_epoch();
}
i64 offset { 0 };
AK::Duration year_from {};
AK::Duration year_to {};
AK::UnixDateTime year_from {};
AK::UnixDateTime year_to {};
DateTime in_effect {};
@string_index_type@ format { 0 };
@ -635,7 +635,7 @@ static constexpr Array<Location, @size@> s_time_zone_locations { {
TRY(append_string_conversions("Region"sv, "region"sv, time_zone_data.time_zone_region_names));
generator.append(R"~~~(
static Array<DaylightSavingsOffset const*, 2> find_dst_offsets(TimeZoneOffset const& time_zone_offset, AK::Duration time)
static Array<DaylightSavingsOffset const*, 2> find_dst_offsets(TimeZoneOffset const& time_zone_offset, AK::UnixDateTime time)
{
auto const& dst_rules = s_dst_offsets[time_zone_offset.dst_rule];
@ -677,7 +677,7 @@ static Array<DaylightSavingsOffset const*, 2> find_dst_offsets(TimeZoneOffset co
return { standard_offset, daylight_offset ? daylight_offset : standard_offset };
}
static Offset get_active_dst_offset(TimeZoneOffset const& time_zone_offset, AK::Duration time)
static Offset get_active_dst_offset(TimeZoneOffset const& time_zone_offset, AK::UnixDateTime time)
{
auto offsets = find_dst_offsets(time_zone_offset, time);
if (offsets[0] == offsets[1])
@ -697,7 +697,7 @@ static Offset get_active_dst_offset(TimeZoneOffset const& time_zone_offset, AK::
return { offsets[1]->offset, InDST::Yes };
}
static TimeZoneOffset const& find_time_zone_offset(TimeZone time_zone, AK::Duration time)
static TimeZoneOffset const& find_time_zone_offset(TimeZone time_zone, AK::UnixDateTime time)
{
auto const& time_zone_offsets = s_time_zone_offsets[to_underlying(time_zone)];
@ -713,7 +713,7 @@ static TimeZoneOffset const& find_time_zone_offset(TimeZone time_zone, AK::Durat
return time_zone_offsets[index];
}
Optional<Offset> get_time_zone_offset(TimeZone time_zone, AK::Duration time)
Optional<Offset> get_time_zone_offset(TimeZone time_zone, AK::UnixDateTime time)
{
auto const& time_zone_offset = find_time_zone_offset(time_zone, time);
@ -729,7 +729,7 @@ Optional<Offset> get_time_zone_offset(TimeZone time_zone, AK::Duration time)
return dst_offset;
}
Optional<Array<NamedOffset, 2>> get_named_time_zone_offsets(TimeZone time_zone, AK::Duration time)
Optional<Array<NamedOffset, 2>> get_named_time_zone_offsets(TimeZone time_zone, AK::UnixDateTime time)
{
auto const& time_zone_offset = find_time_zone_offset(time_zone, time);
Array<NamedOffset, 2> named_offsets;

View file

@ -72,7 +72,7 @@ TEST_CASE(time_zone_name)
TestData { "ar"sv, Locale::CalendarPatternStyle::ShortGeneric, "Africa/Accra"sv, "غرينتش"sv },
};
constexpr auto jan_1_2022 = AK::Duration::from_seconds(1640995200); // Saturday, January 1, 2022 12:00:00 AM
constexpr auto jan_1_2022 = AK::UnixDateTime::from_seconds_since_epoch(1640995200); // Saturday, January 1, 2022 12:00:00 AM
for (auto const& test : test_data) {
auto time_zone = MUST(Locale::format_time_zone(test.locale, test.time_zone, test.style, jan_1_2022));
@ -122,7 +122,7 @@ TEST_CASE(time_zone_name_dst)
TestData { "ar"sv, Locale::CalendarPatternStyle::Short, "Africa/Accra"sv, "غرينتش"sv },
};
constexpr auto sep_19_2022 = AK::Duration::from_seconds(1663553728); // Monday, September 19, 2022 2:15:28 AM
constexpr auto sep_19_2022 = AK::UnixDateTime::from_seconds_since_epoch(1663553728); // Monday, September 19, 2022 2:15:28 AM
for (auto const& test : test_data) {
auto time_zone = MUST(Locale::format_time_zone(test.locale, test.time_zone, test.style, sep_19_2022));
@ -132,13 +132,13 @@ TEST_CASE(time_zone_name_dst)
TEST_CASE(format_time_zone_offset)
{
constexpr auto jan_1_1833 = AK::Duration::from_seconds(-4323283200); // Tuesday, January 1, 1833 12:00:00 AM
constexpr auto jan_1_2022 = AK::Duration::from_seconds(1640995200); // Saturday, January 1, 2022 12:00:00 AM
constexpr auto jan_1_1833 = AK::UnixDateTime::from_seconds_since_epoch(-4323283200); // Tuesday, January 1, 1833 12:00:00 AM
constexpr auto jan_1_2022 = AK::UnixDateTime::from_seconds_since_epoch(1640995200); // Saturday, January 1, 2022 12:00:00 AM
struct TestData {
StringView locale;
Locale::CalendarPatternStyle style;
AK::Duration time;
AK::UnixDateTime time;
StringView time_zone;
StringView expected_result;
};

View file

@ -14,7 +14,7 @@ using enum TimeZone::InDST;
static void test_offset(StringView time_zone, i64 time, i64 expected_offset, TimeZone::InDST expected_in_dst)
{
auto actual_offset = TimeZone::get_time_zone_offset(time_zone, AK::Duration::from_seconds(time));
auto actual_offset = TimeZone::get_time_zone_offset(time_zone, AK::UnixDateTime::from_seconds_since_epoch(time));
VERIFY(actual_offset.has_value());
EXPECT_EQ(actual_offset->seconds, expected_offset);
EXPECT_EQ(actual_offset->in_dst, expected_in_dst);
@ -183,7 +183,7 @@ TEST_CASE(get_time_zone_offset_with_dst)
TEST_CASE(get_named_time_zone_offsets)
{
auto test_named_offsets = [](auto time_zone, i64 time, i64 expected_standard_offset, i64 expected_daylight_offset, auto expected_standard_name, auto expected_daylight_name) {
auto actual_offsets = TimeZone::get_named_time_zone_offsets(time_zone, AK::Duration::from_seconds(time));
auto actual_offsets = TimeZone::get_named_time_zone_offsets(time_zone, AK::UnixDateTime::from_seconds_since_epoch(time));
VERIFY(actual_offsets.has_value());
EXPECT_EQ(actual_offsets->at(0).seconds, expected_standard_offset);

View file

@ -133,7 +133,7 @@ void TimeZoneSettingsWidget::set_time_zone_location()
m_time_zone_location = compute_time_zone_location();
auto locale = Locale::default_locale();
auto now = AK::Duration::now_realtime();
auto now = AK::UnixDateTime::now();
auto name = Locale::format_time_zone(locale, m_time_zone, Locale::CalendarPatternStyle::Long, now).release_value_but_fixme_should_propagate_errors();
auto offset = Locale::format_time_zone(locale, m_time_zone, Locale::CalendarPatternStyle::LongOffset, now).release_value_but_fixme_should_propagate_errors();

View file

@ -117,7 +117,7 @@ static struct tm* time_to_tm(struct tm* tm, time_t t, StringView time_zone)
return nullptr;
}
if (auto offset = TimeZone::get_time_zone_offset(time_zone, AK::Duration::from_seconds(t)); offset.has_value()) {
if (auto offset = TimeZone::get_time_zone_offset(time_zone, AK::UnixDateTime::from_seconds_since_epoch(t)); offset.has_value()) {
tm->tm_isdst = offset->in_dst == TimeZone::InDST::Yes;
t += offset->seconds;
}
@ -171,12 +171,12 @@ static time_t tm_to_time(struct tm* tm, StringView time_zone)
auto timestamp = ((days_since_epoch * 24 + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec;
if (tm->tm_isdst < 0) {
if (auto offset = TimeZone::get_time_zone_offset(time_zone, AK::Duration::from_seconds(timestamp)); offset.has_value())
if (auto offset = TimeZone::get_time_zone_offset(time_zone, AK::UnixDateTime::from_seconds_since_epoch(timestamp)); offset.has_value())
timestamp -= offset->seconds;
} else {
auto index = tm->tm_isdst == 0 ? 0 : 1;
if (auto offsets = TimeZone::get_named_time_zone_offsets(time_zone, AK::Duration::from_seconds(timestamp)); offsets.has_value())
if (auto offsets = TimeZone::get_named_time_zone_offsets(time_zone, AK::UnixDateTime::from_seconds_since_epoch(timestamp)); offsets.has_value())
timestamp -= offsets->at(index).seconds;
}
@ -407,7 +407,7 @@ void tzset()
tzname[1] = const_cast<char*>(__utc);
};
if (auto offsets = TimeZone::get_named_time_zone_offsets(__tzname, AK::Duration::now_realtime()); offsets.has_value()) {
if (auto offsets = TimeZone::get_named_time_zone_offsets(__tzname, AK::UnixDateTime::now()); offsets.has_value()) {
if (!offsets->at(0).name.copy_characters_to_buffer(__tzname_standard, TZNAME_MAX))
return set_default_values();
if (!offsets->at(1).name.copy_characters_to_buffer(__tzname_daylight, TZNAME_MAX))

View file

@ -314,7 +314,7 @@ static i64 clip_bigint_to_sane_time(Crypto::SignedBigInteger const& value)
Vector<Crypto::SignedBigInteger> get_named_time_zone_epoch_nanoseconds(StringView time_zone_identifier, i32 year, u8 month, u8 day, u8 hour, u8 minute, u8 second, u16 millisecond, u16 microsecond, u16 nanosecond)
{
auto local_nanoseconds = get_utc_epoch_nanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond);
auto local_time = Duration::from_nanoseconds(clip_bigint_to_sane_time(local_nanoseconds));
auto local_time = UnixDateTime::from_nanoseconds_since_epoch(clip_bigint_to_sane_time(local_nanoseconds));
// FIXME: LibTimeZone does not behave exactly as the spec expects. It does not consider repeated or skipped time points.
auto offset = TimeZone::get_time_zone_offset(time_zone_identifier, local_time);
@ -332,10 +332,10 @@ i64 get_named_time_zone_offset_nanoseconds(StringView time_zone_identifier, Cryp
auto time_zone = TimeZone::time_zone_from_string(time_zone_identifier);
VERIFY(time_zone.has_value());
// Since Duration::from_seconds() and Duration::from_nanoseconds() both take an i64, converting to
// Since UnixDateTime::from_seconds_since_epoch() and UnixDateTime::from_nanoseconds_since_epoch() both take an i64, converting to
// seconds first gives us a greater range. The TZDB doesn't have sub-second offsets.
auto seconds = epoch_nanoseconds.divided_by(s_one_billion_bigint).quotient;
auto time = Duration::from_seconds(clip_bigint_to_sane_time(seconds));
auto time = UnixDateTime::from_seconds_since_epoch(clip_bigint_to_sane_time(seconds));
auto offset = TimeZone::get_time_zone_offset(*time_zone, time);
VERIFY(offset.has_value());

View file

@ -1164,7 +1164,7 @@ DeprecatedString time_zone_string(double time)
auto tz_name = TimeZone::current_time_zone();
// 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.
if (auto maybe_offset = TimeZone::get_time_zone_offset(tz_name, AK::Duration::from_milliseconds(time)); maybe_offset.has_value()) {
if (auto maybe_offset = TimeZone::get_time_zone_offset(tz_name, AK::UnixDateTime::from_milliseconds_since_epoch(time)); maybe_offset.has_value()) {
if (auto long_name = Locale::get_time_zone_name(Locale::default_locale(), tz_name, Locale::CalendarPatternStyle::Long, maybe_offset->in_dst); long_name.has_value())
tz_name = long_name.release_value();
}

View file

@ -162,9 +162,9 @@ enum class OptionDefaults {
// Table 8: Record returned by ToLocalTime, https://tc39.es/ecma402/#table-datetimeformat-tolocaltime-record
// Note: [[InDST]] is not included here - it is handled by LibUnicode / LibTimeZone.
struct LocalTime {
AK::Duration time_since_epoch() const
AK::UnixDateTime time_since_epoch() const
{
return AK::Duration::from_timestamp(year, month + 1, day + 1, hour, minute, second, millisecond);
return AK::UnixDateTime::from_unix_time_parts(year, month + 1, day + 1, hour, minute, second, millisecond);
}
int weekday { 0 }; // [[Weekday]]

View file

@ -301,7 +301,7 @@ static ErrorOr<Optional<String>> format_time_zone_offset(StringView locale, Cale
}
// https://unicode.org/reports/tr35/tr35-dates.html#Time_Zone_Format_Terminology
ErrorOr<String> format_time_zone(StringView locale, StringView time_zone, CalendarPatternStyle style, AK::Duration time)
ErrorOr<String> format_time_zone(StringView locale, StringView time_zone, CalendarPatternStyle style, AK::UnixDateTime time)
{
auto offset = TimeZone::get_time_zone_offset(time_zone, time);
if (!offset.has_value())

View file

@ -226,7 +226,7 @@ ErrorOr<Optional<StringView>> get_calendar_weekday_symbol(StringView locale, Str
ErrorOr<Optional<StringView>> get_calendar_day_period_symbol(StringView locale, StringView calendar, CalendarPatternStyle style, DayPeriod value);
ErrorOr<Optional<StringView>> get_calendar_day_period_symbol_for_hour(StringView locale, StringView calendar, CalendarPatternStyle style, u8 hour);
ErrorOr<String> format_time_zone(StringView locale, StringView time_zone, CalendarPatternStyle style, AK::Duration time);
ErrorOr<String> format_time_zone(StringView locale, StringView time_zone, CalendarPatternStyle style, AK::UnixDateTime time);
Optional<StringView> get_time_zone_name(StringView locale, StringView time_zone, CalendarPatternStyle style, TimeZone::InDST in_dst);
Optional<TimeZoneFormat> get_time_zone_format(StringView locale);

View file

@ -186,7 +186,7 @@ Optional<StringView> canonicalize_time_zone(StringView time_zone)
Optional<DaylightSavingsRule> __attribute__((weak)) daylight_savings_rule_from_string(StringView) { return {}; }
StringView __attribute__((weak)) daylight_savings_rule_to_string(DaylightSavingsRule) { return {}; }
Optional<Offset> __attribute__((weak)) get_time_zone_offset([[maybe_unused]] TimeZone time_zone, AK::Duration)
Optional<Offset> __attribute__((weak)) get_time_zone_offset([[maybe_unused]] TimeZone time_zone, AK::UnixDateTime)
{
#if !ENABLE_TIME_ZONE_DATA
VERIFY(time_zone == TimeZone::UTC);
@ -196,14 +196,14 @@ Optional<Offset> __attribute__((weak)) get_time_zone_offset([[maybe_unused]] Tim
#endif
}
Optional<Offset> get_time_zone_offset(StringView time_zone, AK::Duration time)
Optional<Offset> get_time_zone_offset(StringView time_zone, AK::UnixDateTime time)
{
if (auto maybe_time_zone = time_zone_from_string(time_zone); maybe_time_zone.has_value())
return get_time_zone_offset(*maybe_time_zone, time);
return {};
}
Optional<Array<NamedOffset, 2>> __attribute__((weak)) get_named_time_zone_offsets([[maybe_unused]] TimeZone time_zone, AK::Duration)
Optional<Array<NamedOffset, 2>> __attribute__((weak)) get_named_time_zone_offsets([[maybe_unused]] TimeZone time_zone, AK::UnixDateTime)
{
#if !ENABLE_TIME_ZONE_DATA
VERIFY(time_zone == TimeZone::UTC);
@ -217,7 +217,7 @@ Optional<Array<NamedOffset, 2>> __attribute__((weak)) get_named_time_zone_offset
#endif
}
Optional<Array<NamedOffset, 2>> get_named_time_zone_offsets(StringView time_zone, AK::Duration time)
Optional<Array<NamedOffset, 2>> get_named_time_zone_offsets(StringView time_zone, AK::UnixDateTime time)
{
if (auto maybe_time_zone = time_zone_from_string(time_zone); maybe_time_zone.has_value())
return get_named_time_zone_offsets(*maybe_time_zone, time);

View file

@ -61,11 +61,11 @@ Optional<StringView> canonicalize_time_zone(StringView time_zone);
Optional<DaylightSavingsRule> daylight_savings_rule_from_string(StringView daylight_savings_rule);
StringView daylight_savings_rule_to_string(DaylightSavingsRule daylight_savings_rule);
Optional<Offset> get_time_zone_offset(TimeZone time_zone, AK::Duration time);
Optional<Offset> get_time_zone_offset(StringView time_zone, AK::Duration time);
Optional<Offset> get_time_zone_offset(TimeZone time_zone, AK::UnixDateTime time);
Optional<Offset> get_time_zone_offset(StringView time_zone, AK::UnixDateTime time);
Optional<Array<NamedOffset, 2>> get_named_time_zone_offsets(TimeZone time_zone, AK::Duration time);
Optional<Array<NamedOffset, 2>> get_named_time_zone_offsets(StringView time_zone, AK::Duration time);
Optional<Array<NamedOffset, 2>> get_named_time_zone_offsets(TimeZone time_zone, AK::UnixDateTime time);
Optional<Array<NamedOffset, 2>> get_named_time_zone_offsets(StringView time_zone, AK::UnixDateTime time);
Optional<Location> get_time_zone_location(TimeZone time_zone);
Optional<Location> get_time_zone_location(StringView time_zone);

View file

@ -88,7 +88,7 @@ static void parse_time(StringView input_time, timespec& atime, timespec& mtime)
month = parameters.take_last();
if (validate_timestamp(year, month, day, hour, minute, second))
atime = mtime = AK::Duration::from_timestamp(year, month, day, hour, minute, second, 0).to_timespec();
atime = mtime = AK::UnixDateTime::from_unix_time_parts(year, month, day, hour, minute, second, 0).to_timespec();
else
err("invalid time format '{}'", input_time);
}
@ -159,7 +159,7 @@ static void parse_datetime(StringView input_datetime, timespec& atime, timespec&
}
if (validate_timestamp(year, month, day, hour, minute, second)) {
auto timestamp = AK::Duration::from_timestamp(year, month, day, hour, minute, second, millisecond);
auto timestamp = AK::UnixDateTime::from_unix_time_parts(year, month, day, hour, minute, second, millisecond);
auto time = timestamp.to_timespec();
if (time_zone.is_empty() && TimeZone::system_time_zone() != "UTC") {
auto offset = TimeZone::get_time_zone_offset(TimeZone::system_time_zone(), timestamp);