Skip to content

Bug when converting local time to UTC, near transition to/from daylight saving time #67

@bakketun

Description

@bakketun

This is a clarification of the issue reported in #47.

CL-USER> (defun utc-string (timestamp)  (local-time:format-timestring nil timestamp :timezone local-time:+utc-zone+))
UTC-STRING
CL-USER> (defparameter *cet* (local-time:find-timezone-by-location-name "Europe/Stockholm"))
*CET*
CL-USER> (utc-string (local-time:encode-timestamp 0 0 0 0 30 3 2014 :timezone *cet*))
"2014-03-29T23:00:00.000000Z"  ; correct, CET is 1 hour ahead of UTC
CL-USER> (utc-string (local-time:encode-timestamp 0 0 0 4 30 3 2014 :timezone *cet*))
"2014-03-30T02:00:00.000000Z"  ; correct, CET with dayligth saving time is 2 hours head of UTC
CL-USER> (utc-string (local-time:encode-timestamp 0 0 0 1 30 3 2014 :timezone *cet*))
"2014-03-29T23:00:00.000000Z"  ; incorrect, dayligth saving time transititon is not until 2.

The root cause of this bug is that the internal function %guess-offset finds the wrong subtimezone when the local time is near the transition to/from daylight saving time. Converting from UTC to local time is always correct, but going the other way is not as easy because the transition times in are in UTC. To complicate thing even further, when the local time is adjusted backwards, there is a period where the same local time correspond to two different UTC time stamps.

Not sure how to best solve this problem. The code in glibc for doing this conversion is quite tricky to understand: https://github.com/lattera/glibc/blob/master/time/mktime.c

One obvious solution would be to simple call mktime, but this doesn't work since mktime doesn't take a time zone parameter.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions