diff --git a/Userland/Libraries/LibTimeZone/TimeZone.cpp b/Userland/Libraries/LibTimeZone/TimeZone.cpp index fae4ad50a8..175bf5fd0f 100644 --- a/Userland/Libraries/LibTimeZone/TimeZone.cpp +++ b/Userland/Libraries/LibTimeZone/TimeZone.cpp @@ -4,10 +4,15 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include +#include #include +#include +#include #include +#include namespace TimeZone { @@ -72,17 +77,52 @@ private: StringView system_time_zone() { TimeZoneFile time_zone_file("r"); + auto time_zone = time_zone_file.read_time_zone(); // FIXME: Propagate the error to existing callers. - if (auto time_zone = time_zone_file.read_time_zone(); !time_zone.is_error()) - return canonicalize_time_zone(time_zone.value()).value_or("UTC"sv); + if (time_zone.is_error()) { + dbgln_if(TIME_ZONE_DEBUG, "{}", time_zone.error()); + return "UTC"sv; + } - return "UTC"sv; + return canonicalize_time_zone(time_zone.value()).value_or("UTC"sv); } StringView current_time_zone() { - return canonicalize_time_zone({ tzname[0], __builtin_strlen(tzname[0]) }).value_or("UTC"sv); + if (char* tz = getenv("TZ"); tz != nullptr) { + // FIXME: Actually parse the TZ environment variable, described here: + // https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08 + StringView time_zone { tz, strlen(tz) }; + + if (auto maybe_time_zone = canonicalize_time_zone(time_zone); maybe_time_zone.has_value()) + return *maybe_time_zone; + + dbgln_if(TIME_ZONE_DEBUG, "Could not determine time zone from TZ environment: {}", time_zone); + } + +#ifdef __serenity__ + return system_time_zone(); +#else + static constexpr auto zoneinfo = "/zoneinfo/"sv; + char buffer[PATH_MAX]; + + if (auto size = readlink("/etc/localtime", buffer, sizeof(buffer)); size > 0) { + StringView time_zone { buffer, static_cast(size) }; + + if (auto index = time_zone.find(zoneinfo); index.has_value()) + time_zone = time_zone.substring_view(*index + zoneinfo.length()); + + if (auto maybe_time_zone = canonicalize_time_zone(time_zone); maybe_time_zone.has_value()) + return *maybe_time_zone; + + dbgln_if(TIME_ZONE_DEBUG, "Could not determine time zone from /etc/localtime: {}", time_zone); + } else { + dbgln_if(TIME_ZONE_DEBUG, "Could not read the /etc/localtime link: {}", strerror(errno)); + } + + return "UTC"sv; +#endif } ErrorOr change_time_zone([[maybe_unused]] StringView time_zone)