Manually installing the tzdata2020d
files will not, in itself, fix this. However the following should (successfully tested with the golang:alpine
docker image):
mkdir tz
cd tz
wget https://www.iana.org/time-zones/repository/releases/tzdata2020d.tar.gz
tar -xvf tzdata2020d.tar.gz
zic -b fat -d zoneinfo/ europe
cp zoneinfo/Europe/Berlin /usr/share/zoneinfo/Europe/Berlin
Other workarounds include:
- Upgrade to Go 1.15.4 or 1.14.11.
- Use the
ZONEINFO
environmental variable to select a different zone file (e.g. export ZONEINFO=/usr/local/go/lib/time/zoneinfo.zip
; zoneinfo.zip
is in the go installation).
- Include the tzdata package in your app (and do not install tzdata in the container - the package is only used if the time package cannot find tzdata files on the system).
- Use a container built from scratch (in combination with one of the above options)
- Pin an earlier alpine version (i.e. alpine:3.8) that uses 2020a or earlier (note that version 3.8 is past its End of Support date).
Cause
This problem was caused by a change in the zic
application; prior to the version included with 2020b release this defaulted to fat
mode which go applications correctly processed. The default is now thin
and go does not support that format (without this patch). Unfortunately the LoadLocation
function fails silently (returning incorrect zone information).
The issue is likely to occur wherever 2020b or later timezone files are used (unless the package maintainer overrides the defaults when running zic
).
zic
details
iana distributes the timezone information as a series of text files along with a number of applications. One of these applications is zic
which processes the text files into the binary files (RFC 8536) which are deployed to /usr/share/zoneinfo
.
This commit changed the default output format from fat
to slim
. The upshot of this is that timezone files produced using the 2020b, or later, files will not be read correctly by Go (unless they are created using the -b fat
argument).
Go Fix
This is fixed in Go 1.15.4 and 1.14.11.
An issue has been raised and the issue is partly fixed by a recent commit (the main aim of that commit was to reduce the size of the time/tzdata
package but should also fix this). See this issue re the other part of the fix.
Testing
The following application demonstrates the issue:
package main
import (
"fmt"
"time"
)
func main() {
b, err := time.LoadLocation("Europe/Berlin")
if err != nil {
panic(err)
}
t := time.Date(2020, 10, 23, 11, 00, 00, 00, time.UTC)
fmt.Printf("1: %s %s\n", t, t.In(b))
t = time.Date(2020, 10, 31, 11, 00, 00, 00, time.UTC)
fmt.Printf("2: %s %s\n", t, t.In(b))
}
The output (Alpine 3.12 under Docker), as at 19th October, is:
1: 2020-10-23 11:00:00 +0000 UTC 2020-10-23 13:00:00 +0200 CEST
2: 2020-10-31 11:00:00 +0000 UTC 2020-10-31 13:00:00 +0200 CEST
This is incorrect because the 31st should be CET
(Alpine 3.8 generates the correct result).