Перевод часов в России 26 октября и Java

Всем привет!

Многие знакомые программисты считают, что для того, чтобы перевести часы в Java на новую Московскую таймзону (которая наступит уже 26 октября, таймзона Europe/Moscow станет равна GMT+3, а не GMT+4, как сейчас — и все остальные русские таймзоны тоже), достаточно поставить на Windows обновления, а на Unix — JDK версии 1.7.0_72 (в статье речь про JDK7, однако информация актуальна для любой ветки, это касается и 5, и 6, и 8).

Так вот, это заблуждение — просто апгрейд JDK на Unix до 1.7.0_72 не годится.
Внутри JDK пакетов есть файлики таймзон (пакет tzdata), вот здесь указано, какой пакет в какой дистрибутив входит и указан контент tzdata пакетов: www.oracle.com/technetwork/java/javase/tzdata-versions-138805.html

Как видно, чтобы получить апдейт к русским таймзонам, нужен пакет как минимум tzdata2014f.
При этом в последних версиях JDK присутствует только tzdata2014c.

Как это решить?

Предположим, что у вас уже настроено:

user@host:/home/user$ echo $JAVA_HOME
/usr/lib/jvm/java-7-oracle


Тогда вам достаточно поставить отдельно пакет tzdata-java:

user@host:/home/host$ sudo apt-get install tzdata-java


Затем указать используемой Java (например, той, которая связана с переменной JAVA_HOME) брать файлики таймзон из пакета tzdata-java. Для этого имеет смысл стереть или переименовать каталог с файликами таймзон внутри JDK и поставить символическую ссылку на /usr/share/javazi:

mv $JAVA_HOME/jre/lib/zi $JAVA_HOME/jre/lib/zi-default
ln –s /usr/share/javazi/  $JAVA_HOME/jre/lib/zi

Проверить можно следующим кодом на Java:

import java.util.*;
import java.text.DateFormat;

public class TestMSK {
    public static void main(String[] args) {

        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Europe/Moscow"));
        DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.US);
        df.setCalendar(c);

        c.setTimeInMillis(1413769091L * 1000L);
        if (!df.format(c.getTime()).equals("Monday, October 20, 2014 5:38:11 AM MSK")) {
            System.out.println("FAIL1 - 20 Oct is not in sync ");
            System.out.println(df.format(c.getTime()));
            System.exit(1);
        }

        c.setTimeInMillis(1414633091L * 1000L);

        if (!df.format(c.getTime()).equals("Thursday, October 30, 2014 4:38:11 AM MSK")) {
            System.out.println("FAIL2 - 30 Oct is not in sync");
            System.out.println(df.format(c.getTime()));
            System.exit(2);
        }

        System.out.println("OK");
        System.exit(0);
    }
}

Проверка:
user@host:/home/user$ javac -cp . TestMSK.java
user@host:/home/user$
user@host:/home/user$ java -cp . TestMSK
OK


Update: спасибо всем за ценные комментарии. Для Windows тоже нужны ручные действия.

В данном случае апдейтом занимается tzupdater tool — качаем отсюда:
www.oracle.com/technetwork/java/javase/downloads/tzupdater-download-513681.html

Запускаем из каждой версии JDK, которые хотим проапдейтить:
C:\jdk1.7.0_60\bin>.\java.exe -cp . -jar tzupdater.jar -u


Надеюсь, все вовремя обновятся и у нас не будет остановки половины софта в воскресенье/понедельник.
Share post
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 21

    +3
    Есть такая замечательная штука от Oracle: tzupdater.jar — www.oracle.com/technetwork/java/javase/downloads/tzupdater-download-513681.html
    Только с openjdk не работает :-(
      0
      Чтобы использовать данный апдейтер нужно для каждой java в системе запустить
      java -jar tzupdater.jar -u
      
        0
        Ага, и то же самое на Windows — помогает:
        C:\jdk1.7.0_60\bin>.\java.exe -cp . -jar tzupdater.jar -u
        


          +3
          Ещё у них есть rss www.oracle.com/ocom/groups/public/@otn/documents/webcontent/163246.xml, где сообщается о всех изменениях в tzupdater'е.

          Чтобы не париться с переключением, проще всего указывать абсолютный путь к бинарнику java. Кроме того, java -jar tzupdater.jar -V расскажет какая версия tzdata зашита в текущем tzupdater, и какая установлена в той яве, через которую он запущен.
          0
          Он еще отдельно обновляется, поэтому лучше смотреть последнюю версию тут www.oracle.com/technetwork/java/javase/tzdata-versions-138805.html
          0
          странно что в tzdata-java лежит 2014i, а на сайте оракла — только 2014h.

          но не об этом хотел сказать. хочу напомнить, если кто-то имеет дело с joda-time — то там никакого автоматического апдейта зон не будет, потому что они «сами с усами». поэтому лучше библиотечку-то обновить в проектах, если этого ещё не произошло.
          если используете spring webmvc, то считайте, что joda тоже используется.
            0
            Если вдруг нет возможности обновить joda-time, то можно в classpath подкинуть jar-ку с руками собранной tzdata
            see github.com/JodaOrg/joda-time/blob/master/src/main/java/org/joda/time/tz/ZoneInfoCompiler.java и кастомным ZoneInfoProvider
            и подсунуть руками через system property -Dorg.joda.time.DateTimeZone.Provider=my.foo.CustomZoneInfoProvider
              0
              Как подсказывают коллеги, которые прямо сейчас это правят, версия joda-time 2.5 уже содержит нужные фиксы.
                0
                Если вдруг нет возможности обновить joda-time
                  0
                  Да, извиняюсь, не туда reply пристроил. А нет ли у вас рецепта для joda-time без замены jar-ников? Это было бы веселее. А то jar-ники это такое дело, приезжают часто с пакетами — зависимостями и авто-обновляться любят.
                    0
                    Всё как написано выше.
                    Руками собрать свою jar-ку в которой будет свой кастомный ZoneInfoProvider и скомпилированная tzdata в ресурсах, положить куда-нибудь рядом с приложением, добавить её в classpath и добавить ключик JVM -Dorg.joda.time.DateTimeZone.Provider
                    Никто за вас вашу jarку автоматически не обновит.
            0
            Есть предположение что указанный метод не работает с openjdk, т.к. на сайте oracle tzdata собрана для обычного jdk. Для openjdk надо собирать вручную из исходников.
              0
              Как пишут в соседнем посте: habrahabr.ru/post/240915/, для Debian борьба с OpenJDK — это установка свежего пакета tzdata-java.
              Проверил на своей Ubuntu — поставил OpenJDK7, всё работает (tzdata-java уже обновлён по рецепту статьи):

              user@host:~$ java -version
              java version "1.7.0_65"
              OpenJDK Runtime Environment (IcedTea 2.5.3) (7u71-2.5.3-0ubuntu0.12.04.1)
              OpenJDK Server VM (build 24.65-b04, mixed mode)
              
              user@host:/home/user$ javac -version
              javac 1.7.0_65
              
              user@host:/home/user$ javac -cp . TestMSK.java
              user@host:/home/user$
              
              user@host:/home/user$ java -cp . TestMSK
              OK
              
              0
              Под IBM есть такая штука как JTZU, делает в принципе тоже самое. Но сама сканирует весь диск и патчит
                0
                tzupdater под 7 и 8ую версии. Что делать с 1.5 и 1.6?
                  0
                  На 6ой прекрасно работает. Про 1.5 не скажу не проверял, кмк тоже должно.
                    0
                    работает
                    0
                    А для JRE тоже нужно выполнять описанную магию?
                      0
                      Она, собственно, для jre и выполняется.
                      0
                      нужно еще помнить про tzmappings — файл соответствия часовых зон винды и явы. В частности — в 6й версии там нет описания зоны asia\magadan. У меня от этого много проблем было.
                        +1
                        может кому пригодится, apple java на mac os x тоже можно этой утилитой обновить
                        решение нашел здесь lists.apple.com/archives/java-dev/2007/Jan/msg00060.html, только параметр с тех пор иначе выглядит java.vendor=«Oracle Corporation»

                        Only users with full accounts can post comments. Log in, please.