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

Использование Joda-Time для получения UTC-коррекции для заданной даты и часового пояса

У меня есть даты в формате 20Jan2013, 08Aug2012 и т.д. со своими конкретными часовыми поясами. Так, например, 20Jan2013 может иметь идентификатор часовой пояс Австралии/Мельбурна, а 08Aug2012 может иметь идентификатор Европы/Лондона. То, что я хочу сделать, основано на этих часовых поясах и датах, вычислить смещение UTC для этого часового пояса на данную дату. Я придумал это до сих пор:

DateTimeFormatter dtf = DateTimeFormat.forPattern("ZZ");
DateTimeFormatter dtf1 = DateTimeFormat.forPattern("ddMMMYYYY");

DateTimeZone zone = DateTimeZone.forID("Australia/Melbourne");  

DateTime thisDate = dtf1.parseDateTime("30Jul2013");                                            
System.out.println("\nZone: " + thisDate.withZone(zone));

Это дает мне результат:

Zone: 2013-07-30T00:00:00.000+10:00

Это правильно, но я хотел бы извлечь только смещение UTC от этого, которое в этом случае равно +10: 00. Я искал способы сделать это, но ничего не могу найти. Есть ли способ сделать это? Единственный вариант, который я вижу, это преобразовать вывод в String и использовать метод подстроки для получения смещения UTC.

В приведенном выше коде учитывается DST (летнее время). Так, например, если бы у меня было: DateTime thisDate = dtf1.parseDateTime( "30Jan2013" );

Выход будет: 2013-01-30T00: 00: 00.000 + 11: 00

(+ 11:00 в конце вместо +10: 00)

Так что в основном все, что мне нужно сделать, это найти способ извлечь +11: 00 с 2013-07-30T00: 00: 00.000 + 11: 00. Пожалуйста, помогите!

4b9b3361

Ответ 1

Простой способ получения названия часового пояса и смещения в часы

public static String getCurrentTimeZoneOffset() {
    DateTimeZone tz = DateTimeZone.getDefault();
    Long instant = DateTime.now().getMillis();

    String name = tz.getName(instant);

    long offsetInMilliseconds = tz.getOffset(instant);
    long hours = TimeUnit.MILLISECONDS.toHours( offsetInMilliseconds );
    String offset = Long.toString( hours );

    return name + " (" + offset + " Hours)";
    // Example: "Mountain Standard Time (-7 Hours)"
}

Пара предупреждений:

  • Это получает значение по умолчанию DateTimeZone от JodaTime. Вы можете изменить его, чтобы принять определенный DateTimeZone, который передается в метод.
  • Это возвращает его в формате " Mountain Standard Time (-7 Hours)", но вы можете отформатировать его, как видите, довольно легко.

Надеюсь, что это поможет.

В JP

Ответ 2

Если вам просто требуется смещение часового пояса, используйте DateTimeZone.forID(), чтобы получить часовой пояс, а затем tz.getOffset(instant), чтобы получить смещение по UTC в миллисекундах.

Может показаться странным, что вам нужно мгновенное вычисление смещения в UTC, но это необходимо учитывать с учетом летнего сбережения, а также изменения в часовом поясе. Да, страны время от времени меняют свои временные интервалы:

Почему изменения в часовом поясе?

Настройки часового пояса принимаются локально, и нет авторитета в мировом часовом поясе.

EDIT. Это дает правильный результат:

    DateTimeFormatter dtf1 = DateTimeFormat.forPattern("ddMMMYYYY");

    DateTimeZone zone = DateTimeZone.forID("Australia/Melbourne");  

    DateTime thisDate = dtf1.parseDateTime("30Jul2013").withZone(zone);                                            
    assertEquals( 10 * CommonConstants.MILLISECONDS_PER_HOUR,
        zone.getOffset( thisDate ) );

thisDate.get

Ответ 3

Чтобы Joda дала правильное смещение, вы должны предоставить мгновенное мгновение. Без мгновенного времени невозможно вычислить смещение, так как у нас есть разные смещения (переход на летнее время). Так я бы использовал Joda для смещения в формате + HH: mm:

    int offsetInMillis = DateTimeZone.forID(zoneId).getOffset(new DateTime().getMillis());
    String offset = String.format("%02d:%02d", Math.abs(offsetInMillis / 3600000),
            Math.abs((offsetInMillis / 60000) % 60));
    offset = (offsetInMillis >= 0 ? "+" : "-") + offset; 

Ответ 4

Java 8 улучшил обработку даты и времени, чтобы решить некоторые из предыдущих ограничений языка в этой области. Некоторые из моих проектов начали использовать его, а не Джоду.

Использование пакета java.time:

    ZonedDateTime dateTime = LocalDate.of(2013 , 1 , 20).atStartOfDay( ZoneId.of("Australia/Melbourne"));
    ZoneOffset zo = dateTime.getOffset();
    int offset = zo.getTotalSeconds();

    long hours = TimeUnit.SECONDS.toHours(offset);
    long minutes = TimeUnit.SECONDS.toMinutes(offset % 3600);

В переменной часов установлено значение 11, а минуты - 0.

Он также вычисляет смещение минут, для часовых поясов, которые являются частичными часами, такими как Ньюфаундленд и Лабрадор в восточной Канаде:

ZonedDateTime dateTime = LocalDate.of(2013, 1, 20).atStartOfDay( ZoneId.of("Canada/Newfoundland"));

В этом случае смещение -03:30 (три с половиной часа позади UTC), hours равно -3 и minutes равно -30.

Для представления String, а не целого числа часов и минут, используйте метод ZoneOffset toString(). Итак, для примера выше, используйте:

String offsetString = zo.toString();

Ответ 5

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

 public static String formatMonthDayMinuteByGivenUtcOffset(long timestamp, int offset) {
        return JODA_FORMATTER.print(createDateTime(timestamp, offset));
    }