Подтвердить что ты не робот

Как я могу получить "текущую" аббревиатуру часового пояса IANA в течение всего времени в ICU4J?

В настоящее время я пытаюсь написать набор программ проверки часовых поясов, чтобы узнать, интерпретируют ли различные платформы время IANA данные зоны.

Формат вывода, на который я нацелен, включает аббревиатуру, действующую в течение определенного времени - например, "BST" для "Британского летнего времени" или "PST" для "Тихоокеанского стандартного времени".

На большинстве платформ это легко - но ICU4J, похоже, не работает, как ни странно. Согласно документации SimpleDateFormat, я должен использовать шаблон "zzz", чтобы получить то, что я ищу, но это, похоже, возвращается к "O" в GMT + X в течение долгого времени. Для некоторых часовых поясов аббревиатуры вообще отсутствуют.

Короткий пример с использованием Нью-Йорка:

import java.util.Date;
import java.util.Locale;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.text.SimpleDateFormat;

public class Test {
    public static void main(String[] args) {
        TimeZone zone = TimeZone.getTimeZone("America/New_York");
        SimpleDateFormat format = new SimpleDateFormat("zzz", Locale.US);
        format.setTimeZone(zone);

        // One month before the unix epoch
        System.out.println(format.format(new Date(-2678400000L))); // GMT-5

        // At the unix epoch
        System.out.println(format.format(new Date(0L))); // EST
    }
}

(Я запускаю с помощью ICU4J 55.1, как загрузку запаса, так и после обновления с выпуском данных 2015e.)

Мне не ясно, получает ли ICU4J свои сокращения из данных tz или из CLDR - я подозреваю, что это последнее, учитывая, что в данных tz нет ничего, чтобы предложить здесь разницу.

На него, похоже, также влияет языковой стандарт, который, я полагаю, является разумным - с использованием американского языка я могу видеть EST/EDT для America/New_York, но ничего для Европы/Лондона; с британским языком я вижу GMT/BST для Европы/Лондона, но ничего для Америки /New _York: (

Есть ли способ убедить ICU4J вернуться к сокращениям tz? В моем конкретном случае, все, что я ищу.

Обновление

Благодаря комментариям RealSkeptic, похоже, что TimeZoneNames - более чистый способ получения этих данных без форматирования. Все это звучит так многообещающе - там даже TimeZoneNames.getTZDBInstance:

Возвращает экземпляр TimeZoneNames, содержащий только короткие имена определенных зон (TimeZoneNames.NameType.SHORT_STANDARD и TimeZoneNames.NameType.SHORT_DAYLIGHT), совместимые с аббревиатурами зоны базы данных IANA tz (не локализованные).

Это в значительной степени то, что я хочу - но это не происходит в 1970 году в большинстве случаев и не включает в себя все соответствующие данные:

import static com.ibm.icu.text.TimeZoneNames.NameType.SHORT_STANDARD;

import com.ibm.icu.text.TimeZoneNames;
import com.ibm.icu.text.TimeZoneNames.NameType;
import com.ibm.icu.util.ULocale;

public class Test {
    public static void main(String[] args) {
        TimeZoneNames names = TimeZoneNames.getTZDBInstance(ULocale.ROOT);

        long december1969 = -2678400000L;
        // 24 hours into the Unix epoch...
        long january1970 = 86400000L;

        // null
        System.out.println(
            names.getDisplayName("America/New_York",  SHORT_STANDARD, december1969));
        // EST
        System.out.println(
            names.getDisplayName("America/New_York",  SHORT_STANDARD, january1970));

        // null
        System.out.println(
            names.getDisplayName("Europe/London",  SHORT_STANDARD, december1969));
        // null
        System.out.println(
            names.getDisplayName("Europe/London",  NameType.SHORT_STANDARD, january1970));
    }
}

Учитывая, что на данный момент на самом деле очень мало косвенности - я говорю ICU4J точно, что хочу, - мое подозрение в том, что информация просто недоступна: (

4b9b3361

Ответ 1

Прослеживая источники, чтобы узнать, как это работает, выясняется, что для поиска отображаемого имени он получает имя мета зоны от имени зоны и даты, а затем из мета зоны и типа, отображаемое имя.

com.ibm.icu.impl.TZDBTimeZoneNames, который является классом, возвращаемым из TimeZoneNames.getTZDBInstance(ULocale), реализует getMetaZoneID(String,Long), вызывая com.ibm.icu.impl.TimeZoneNamesImpl._getMetaZoneID(String,long), который извлекает сопоставления из данного имени часового пояса в имена метазоны и затем проверяет, находится ли дата между параметры from и to в любом из этих сопоставлений.

Отображение считывается вложенным классом, например:

for (int idx = 0; idx < zoneBundle.getSize(); idx++) {
    UResourceBundle mz = zoneBundle.get(idx);
    String mzid = mz.getString(0);
    String fromStr = "1970-01-01 00:00";
    String toStr = "9999-12-31 23:59";
    if (mz.getSize() == 3) {
        fromStr = mz.getString(1);
        toStr = mz.getString(2);
    }
    long from, to;
    from = parseDate(fromStr);
    to = parseDate(toStr);
    mzMaps.add(new MZMapEntry(mzid, from, to));
}

(источник)

Как вы можете видеть, он имеет жестко заданные значения для значений to и from, которые он вернет (хотя он читает to и from из самого ресурсного пакета, когда запись метазоны имеет три элемента, большинство из них - нет - как можно видеть в фактическом файле мета-зоны, из которого построен пакет, и тех, кто это делает, также не имеют "от" дат до января 1970 года.)

Таким образом, идентификатор метазоны будет null для любой даты до января 1970 года, и, в свою очередь, так будет отображаемое имя.