Как исправить сломанную базу данных часовых поясов tzdata2020c для alpine?

#go #alpine #tzdata

#Вперед #alpine-linux #tzdata

Вопрос:

Я только что наткнулся на ошибку с пакетом tzdata2020c для alpine. Он не вычисляет правильное время для Европы / Берлина после запланированного перехода на летнее время в следующее воскресенье 25 октября 2020 года. Версия tzdata2020c использует CEST, например, для 31 октября 2020 года и часового пояса Европа / Берлин, тогда как CET будет правильным.

Кто-нибудь знает, как вручную добавить новую версию базы данных tzdata2020d, доступную здесь .

Мое приложение, написанное на Go, неправильно использует CEST для Европы / Берлина 31 октября 2020 года с использованием tzdata2020c: tzdata2020c

То же приложение корректно использует CET для Европы / Берлина 31 октября 2020 года с использованием tzdata2020a: tzdata2020a

Комментарии:

1. Я повторил эту проблему; игровая площадка работает так, как ожидалось, как и изображения docker golang:latest и golang:alpine . Однако, если я установлю данные часового пояса в alpine image ( apk add tzdata ), результаты будут неверными (все время CEST ). Запуск export ZONEINFO=/usr/local/go/lib/time/zoneinfo.zip исправляет это (поэтому быстрым решением было бы использовать этот подход).

Ответ №1:

Ручная установка tzdata2020d файлов сама по себе не исправит это. Однако следующее должно (успешно протестировано с golang:alpine помощью образа docker):

 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
  

Другие обходные пути включают:

  • Обновитесь до Go 1.15.4 или 1.14.11.
  • Используйте ZONEINFO переменную среды, чтобы выбрать другой файл зоны (например export ZONEINFO=/usr/local/go/lib/time/zoneinfo.zip ; zoneinfo.zip находится в установке go).
  • Включите пакет tzdata в свое приложение (и не устанавливайте tzdata в контейнер — пакет используется только в том случае, если пакет time не может найти файлы tzdata в системе).
  • Используйте контейнер, созданный с нуля (в сочетании с одним из вышеуказанных вариантов)
  • Закрепите более раннюю версию alpine (например, alpine: 3.8), которая использует 2020a или более раннюю (обратите внимание, что версия 3.8 истекла с датой окончания поддержки).

Причина

Эта проблема была вызвана изменением в zic приложении; до версии, включенной в выпуск 2020b, по умолчанию fat использовался режим, в котором приложения go обрабатывались правильно. По умолчанию используется now thin , и go не поддерживает этот формат (без этого исправления). К сожалению LoadLocation , функция автоматически завершается сбоем (возвращает неверную информацию о зоне).

Проблема, вероятно, возникнет везде, где используются файлы часовых поясов 2020b или более поздних версий (если только сопровождающий пакета не переопределяет значения по умолчанию при запуске zic ).

zic Подробные сведения

iana распространяет информацию о часовых поясах в виде серии текстовых файлов вместе с рядом приложений. Одно из таких приложений zic обрабатывает текстовые файлы в двоичные файлы (RFC 8536), в которые они развернуты /usr/share/zoneinfo .

Этот коммит изменил формат вывода по умолчанию с fat на slim . Результатом этого является то, что файлы часовых поясов, созданные с использованием 2020b или более поздних версий, не будут правильно считываться Go (если они не созданы с использованием -b fat аргумента).

Исправьте

Это исправлено в Go 1.15.4 и 1.14.11.

Возникла проблема, и проблема частично устранена недавним коммитом (основной целью этого коммита было уменьшить размер time/tzdata пакета, но это также должно быть исправлено). Смотрите Эту проблему в другой части исправления.

Тестирование

Следующее приложение демонстрирует проблему:

 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 %sn", t, t.In(b))
    t = time.Date(2020, 10, 31, 11, 00, 00, 00, time.UTC)
    fmt.Printf("2: %s %sn", t, t.In(b))
}
  

Выходные данные (Alpine 3.12 в Docker) по состоянию на 19 октября:

 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
  

Это неверно, потому что должно быть 31 CET -е число (Alpine 3.8 генерирует правильный результат).

Комментарии:

1. Исправлено с Go 1.15.4: проблема # 42138 находится на этапе 1.15.4 или см. Примечания к выпуску .

Ответ №2:

Возникла та же проблема с изображением alpine: 3.9, и ее удалось исправить на основе ответа Brit. Спасибо.