Java База данных часовых поясов против данных IANA - PullRequest
4 голосов
/ 31 января 2020

Существует несоответствие летнего времени между базой данных IANA и базой данных Java tzdb.dat 2019 c в часовом поясе Африка / Кассабланка, что меня очень смущает. Могут быть и другие, но я нашел это. Из того, что я могу сказать, база данных часовых поясов IANA ясно показывает, что DST поддерживается в Марокко (Африка / Касабланка), к сожалению, база данных Java tzdb.dat часового пояса в выпуске 2019 c не согласна. Это принесет мне бесконечное горе. Чего мне здесь не хватает, или другие видели такие вещи

Таблица IANA 2019 c для Африки / Касабланки

Примечание: часть таблицы ниже показывает, что нормальное время - UTC + 1, а время перехода на летнее время - UT C a sla sh (/) разделяет стандартные сокращения и сокращения дневного света

ФОРМАТ ПРАВИЛ ИМЕНИ STDOFF зоны [UNTIL]

Зона Африка / Касабланка -0: 30: 20 - LMT 1913 окт. 26

         0:00   Morocco +00/+01 1984 Mar 16
         1:00   -   +01 1986
         0:00   Morocco +00/+01 2018 Oct 28  3:00    
         1:00   Morocco +01/+00

С 28 октября 2018 года по настоящее время смещение составляет +1 для стандарта и +0 для перехода на летнее время (sla * 1039). * (/) разделяет стандартные сокращения и сокращения дневного света.) STDOFF 1:00, т. е. количество времени, добавляемое к UT для получения стандартного времени, без каких-либо поправок на летнее время. Это соответствует UT C +1, то есть текущему времени в Марокко. , Поэтому мы берем Зону Африка / Касабланка (UT C) и добавляем смещения + 01 / + 00 в зависимости от Рамадана. '

Тест

Я написал простой Java класс для проверьте 2019 c TZDB. Этот класс (показан ниже) показывает, что что-то не так с последним файлом tzdb.dat файла данных Java о часовых поясах. Этот тест был выполнен с использованием IBM SR5FP40 с файлом данных часового пояса 2019 c. У меня были те же результаты с OpenJDK с использованием файла данных 2019 c.

Первая строка из tzdb.dat показывает 2019c TZDB 2019cX Африка / Абиджан Африка / Аккра Африка / Аддис_Абаба Африка / Алжир

Тест которая показывает проблему

Часовой пояс = Африка / Касабланка Поддерживает Дневной свет Экономия времени = false Дата Пн 20 мая 00:00:00 WET 2019 в настоящее время в DST false Название часового пояса Западноевропейский идентификатор часового пояса Африка / Касабланка

Был также проведен базовый тест, чтобы показать, поддерживается ли летнее время, и покажет код.

Часовой пояс = Европа / Рим Поддерживает дневной свет Экономия времени = true Дата пн 20 мая 00: 00:00 CEST 2019 в настоящее время в летнее время истинное название часового пояса Центрально-европейский идентификатор часового пояса Европа / Рим

Код здесь для справки

import java.util.*; 
import java.text.SimpleDateFormat;
import java.text.ParseException;

public class checkdaylight{ 

    public static void main(String[] args) 
    { 

        // Create TimeZone object
        //Europe/Rome
        //Pacific/Pago_Pago
        //Africa/Casablanca
        String TimezoneToTest = "Africa/Casablanca";
        System.out.println("Time Zone = " + TimezoneToTest);
        TimeZone obj = TimeZone.getTimeZone(TimezoneToTest); 
        TimeZone.setDefault(TimeZone.getTimeZone(TimezoneToTest)); //to avoid confusion

        // Checking day light time 
        // and displaying the result 
        System.out.println("Supports Day light Savings time  = "
                        + obj.useDaylightTime()); 
        String pattern = "yyyy-MM-dd";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        try{
            simpleDateFormat.setTimeZone(TimeZone.getTimeZone(TimezoneToTest));
            Date checkdate = simpleDateFormat.parse("2019-05-20");
            System.out.println("Date " + checkdate.toString()+ " is currently in DST "+ obj.inDaylightTime(checkdate));
         } catch (ParseException e) {
            e.printStackTrace();
        }

        System.out.println("Time zone name " +obj.getDisplayName());
        System.out.println("Time zone ID " + obj.getID());

    } 
} 

1 Ответ

10 голосов
/ 01 февраля 2020

Марокко теперь на DST постоянно

По состоянию на 26 октября 2018 года Марокко перешло на DST навсегда .

Правительство Марокко дало уведомление только за 2 дня (!) В Указе 2.18.855 . По-видимому, правительство намерено прекратить все переключения часов без изменений ни для DST , ни для Рамадан . Этот указ означает смещение +01:00 круглогодично .

Этот указ также означает, что Марокко больше не «на летнее время». Новый нормальный является смещением на один час впереди UT C, тогда как в старые времена смещение обычно составляло UT C (смещение ноль часов-минут-секунд). Обратите внимание, что в приведенном ниже коде вызов ZoneRules::isDaylightSavings возвращает false в настоящее время (начало 2020 г.).

Подробнее см. В Википедии: Летнее время время в Марокко .

Когда я говорю «навсегда», принимайте это с зерном соли . Политики всего мира проявляют склонность к частым изменениям смещения их часовых поясов. Это «постоянно на летнее время» является лишь последней модой, которая полюбилась политикам. Всегда ожидайте дальнейших изменений.

Избегайте устаревших классов даты и времени

Вы используете ужасные классы даты и времени, которые были заменены годами go современным java .time классов, определенных в JSR 310. Больше нет причин использовать эти ужасные унаследованные классы.

Table of all date-time types in Java, both modern and legacy

java. время

Укажите предполагаемый часовой пояс.

ZoneId zCasablanca = ZoneId.of( "Africa/Casablanca" ) ;

Извлечение правил зоны.

ZoneRules rulesCasablanca = zCasablanca.getRules() ;

Опрос правил, применимых к конкретному c моменту в этой зоне.

ZoneOffset offset = rulesCasablanca.getOffset( Instant.now() ) ;
boolean isDst = rules.isDaylightSavings( instant ) ;

Или свертывание в одну строку.

ZoneOffset offset = ZoneId.of( "Africa/Casablanca" ).getRules().getOffset( Instant.now() ) ;

Проверьте свою версию Java.

System.out.println( "Java vendor and version:" ) ;
System.out.println( "    " + System.getProperty("java.vendor") ) ;
System.out.println( "    " + Runtime.version() ) ;

String tzdataVersion = 
    java.time.zone.ZoneRulesProvider
              .getVersions("UTC")
              .lastEntry()
              .getKey() 
;
System.out.println( "tzdata: " + tzdataVersion ) ;
System.out.println( "" ) ;

См. этот код Запустите Live на IdeOne.com .

Java поставщик и версия:

Oracle Corporation

12.0.1 + 12

tzdata: 2018g

offset.toString (): +01: 00

isDst: false

Specifi c date

Давайте попробуем указать ваши c date.

    LocalDate localDate = LocalDate.parse( "2019-05-20" ) ;
    ZonedDateTime zdt = localDate.atStartOfDay( z ) ;
    System.out.println( "zdt.toString(): " + zdt ) ;
    System.out.println(
        "offset: " + rules.getOffset( zdt.toInstant() ) + 
        "  |  is in DST: " + rules.isDaylightSavings( zdt.toInstant() ) 
    );

zdt.toString (): 2019-05-20T00: 00 + 01: 00 [Африка / Касабланка]

смещение: +01: 00 | находится в летнее время: false

tzdata

Oracle списки tzdata файлы, встроенные в Java среды выполнения.

Этот список показывает, что переход Марокко на постоянное летнее время был учтен в tzdata2018g. Этот файл tzdata был связан с Java версиями 11.0.2, 8u201 и 7u211. По крайней мере, Oracle связал его, в то время как я предполагаю, что проект OpenJDK сделал то же самое (я не проверял).

Марокко переходит на постоянный +01 на 2018-10-27.

Марокко переходит с + 00 / + 01 на постоянный +01, действующий на 2018-10-27, поэтому его часы не откатятся на 2018-10-28, как планировалось ранее .

Чтобы получить версию файла данных tzdata, используемого вашей JVM, см. этот ответ на вопрос, Java - найти tzdata Используемая версия независимо от версии JRE .


О java .time

* 1297 Фреймворк * .time встроен в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Чтобы узнать больше, см. Учебник Oracle . И поиск переполнения стека для многих примеров и объяснений. Спецификация: JSR 310 .

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на java .time классов.

Вы можете обмениваться java .time объектами напрямую с вашей базой данных. Используйте JDB C драйвер , совместимый с JDB C 4.2 или более поздней версией. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где взять классы java .time?

  • Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 и более поздних версий - часть стандартного API Java со связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большинство функций java .time перенесено на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии Android связывают реализации классов java .time .
    • Для более ранних Android (<26) <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP проект адаптируется ThreeTen-Backport (упомянуто выше). См. Как использовать ThreeTenABP… .

ThreeTen-Extra Проект расширяет java .time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java .time. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и more .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...