Skip to content

SunOS/Solaris fallback in utc_minutes_offset returns meaningless wrong number of minutes #3351

Open
@toh-ableton

Description

@toh-ableton

spdlog uses the function utc_minutes_offset in the z_formatter to format the '%z' part of a format string (UTC-offset) when logging time. The function has three implementations, one of which is chosen at compile time via marcro defines (Windows, SunOS/Solaris, default).

The SunOS/Solaris implementation, however, returns the difference of the given tm and gmtime(now) instead, which can be an arbitrary value. If a unit test for a logging subsystem logs a message at a defined point in time to get identical output in every test run, for instance, the difference could amount to years.

The function returns the correct value only in case tm is at most the fractional part of a second before localtime(now) or roughly a minute after, otherwise the truncation in the return statement will produce wrong values.

auto offset_seconds = helper::calculate_gmt_offset(tm);

A better solution could look like this:

    const auto now = std::time(nullptr);
    const auto local_now = localtime(now);
    auto offset_seconds = helper::calculate_gmt_offset(local_now, gmtime(now));
    if (tm.tm_isdst >= 0 && local_now.tm_isdst >=0) {
        offset_seconds += (tm.tm_isdst > 0) ? 3600 : 0;
        offset_seconds -= (local_now.tm_isdst > 0) ? 3600 : 0;
    }

This assumes that tm has the same timezone as the local time, which seems like the only reasonable assumption on platforms missing the tm_gmtoff-field.

It also assumes that daylight savings time advances the clock by 1h, which is not universally true, e.g. in parts of Australia.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions