musl: time-util: introduce get_tzname() helper function

musl leaves the DST timezone name unset if there is no DST.
The helper function maps that back to no DST.
This commit is contained in:
Yu Watanabe
2025-11-12 03:35:45 +09:00
parent 3ac4d68498
commit 6431f2e072
6 changed files with 24 additions and 16 deletions

View File

@@ -625,6 +625,14 @@ char* format_timespan(char *buf, size_t l, usec_t t, usec_t accuracy) {
return buf;
}
const char* get_tzname(bool dst) {
/* musl leaves the DST timezone name unset if there is no DST, map this back to no DST */
if (dst && isempty(tzname[1]))
dst = false;
return empty_to_null(tzname[dst]);
}
int parse_gmtoff(const char *t, long *ret) {
int r;
@@ -1078,10 +1086,7 @@ int parse_timestamp(const char *t, usec_t *ret) {
* not follow the timezone change in the current area. */
tzset();
for (int j = 0; j <= 1; j++) {
if (isempty(tzname[j]))
continue;
if (!streq(tz, tzname[j]))
if (!streq_ptr(tz, get_tzname(j)))
continue;
/* The specified timezone matches tzname[] of the local timezone. */

View File

@@ -149,6 +149,7 @@ static inline char* format_timestamp(char *buf, size_t l, usec_t t) {
#define FORMAT_TIMESTAMP_STYLE(t, style) \
format_timestamp_style((char[FORMAT_TIMESTAMP_MAX]){}, FORMAT_TIMESTAMP_MAX, t, style)
const char* get_tzname(bool dst);
int parse_gmtoff(const char *t, long *ret);
int parse_timestamp(const char *t, usec_t *ret);

View File

@@ -3208,7 +3208,7 @@ static int manager_dispatch_timezone_change(
/* Read the new timezone */
tzset();
log_debug("Timezone has been changed (now: %s).", tzname[daylight]);
log_debug("Timezone has been changed (now: %s).", get_tzname(daylight));
HASHMAP_FOREACH(u, m->units)
if (UNIT_VTABLE(u)->timezone_change)

View File

@@ -370,9 +370,10 @@ int calendar_spec_to_string(const CalendarSpec *c, char **ret) {
tzset();
if (!isempty(tzname[c->dst])) {
const char *z = get_tzname(c->dst);
if (z) {
fputc(' ', f);
fputs(tzname[c->dst], f);
fputs(z, f);
}
}
@@ -897,10 +898,11 @@ int calendar_spec_from_string(const char *p, CalendarSpec **ret) {
/* Check if the local timezone was specified? */
for (j = 0; j <= 1; j++) {
if (isempty(tzname[j]))
const char *z = get_tzname(j);
if (!z)
continue;
e = endswith_no_case(p, tzname[j]);
e = endswith_no_case(p, z);
if (!e)
continue;
if (e == p)

View File

@@ -15,7 +15,7 @@
static void set_timezone(const char *tz) {
ASSERT_OK(set_unset_env("TZ", tz, /* overwrite = */ true));
tzset();
log_info("TZ=%s, tzname[0]=%s, tzname[1]=%s", strna(getenv("TZ")), strempty(tzname[0]), strempty(tzname[1]));
log_info("TZ=%s, tzname[0]=%s, tzname[1]=%s", strna(getenv("TZ")), strempty(get_tzname(/* dst= */ false)), strempty(get_tzname(/* dst= */ true)));
}
TEST(parse_sec) {
@@ -1109,15 +1109,15 @@ TEST(in_utc_timezone) {
assert_se(setenv("TZ", "UTC", 1) >= 0);
assert_se(in_utc_timezone());
ASSERT_STREQ(tzname[0], "UTC");
ASSERT_STREQ(tzname[1], "UTC");
ASSERT_STREQ(get_tzname(/* dst= */ false), "UTC");
ASSERT_STREQ(get_tzname(/* dst= */ true), "UTC");
assert_se(timezone == 0);
assert_se(daylight == 0);
assert_se(setenv("TZ", "Europe/Berlin", 1) >= 0);
assert_se(!in_utc_timezone());
ASSERT_STREQ(tzname[0], "CET");
ASSERT_STREQ(tzname[1], "CEST");
ASSERT_STREQ(get_tzname(/* dst= */ false), "CET");
ASSERT_STREQ(get_tzname(/* dst= */ true), "CEST");
}
TEST(map_clock_usec) {

View File

@@ -733,9 +733,9 @@ static int method_set_timezone(sd_bus_message *m, void *userdata, sd_bus_error *
log_struct(LOG_INFO,
LOG_MESSAGE_ID(SD_MESSAGE_TIMEZONE_CHANGE_STR),
LOG_ITEM("TIMEZONE=%s", c->zone),
LOG_ITEM("TIMEZONE_SHORTNAME=%s", tzname[daylight]),
LOG_ITEM("TIMEZONE_SHORTNAME=%s", get_tzname(daylight)),
LOG_ITEM("DAYLIGHT=%i", daylight),
LOG_MESSAGE("Changed time zone to '%s' (%s).", c->zone, tzname[daylight]));
LOG_MESSAGE("Changed time zone to '%s' (%s).", c->zone, get_tzname(daylight)));
(void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m),
"/org/freedesktop/timedate1", "org.freedesktop.timedate1", "Timezone",