Конвертировать дату в восточное время - получить объект Date в качестве выходного

Я видел много примеров преобразования даты из одного часового пояса в другой. Но все они имеют вывод в виде строки. Я хочу объект даты в качестве вывода.

Методы, которые я попробовал -

Подход 1

SimpleDateFormat dateTimeFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss a z");
dateTimeFormat.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta"));
Date date = new Date();

System.out.println(dateTimeFormat.format(date)); // this print IST Timezone

DateFormat timeFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss a z");
timeFormat.setTimeZone(TimeZone.getTimeZone("America/New_York"));

String estTime = timeFormat.format(date);
try {
    date = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss a z", Locale.ENGLISH).parse(estTime);
    System.out.println(date);

    } catch (ParseException ex) {
    Logger.getLogger(A.class.getName()).log(Level.SEVERE, null, ex);
}


System.out.println(timeFormat.format(date));

Подход 2

private static Date shiftTimeZone(Date date, TimeZone sourceTimeZone, TimeZone targetTimeZone) {
        System.out.println(sourceTimeZone.toString());
        System.out.println(targetTimeZone.toString());
        Calendar sourceCalendar = Calendar.getInstance();
        sourceCalendar.setTime(date);
        sourceCalendar.setTimeZone(sourceTimeZone);

        Calendar targetCalendar = Calendar.getInstance();
        for (int field : new int[]{Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, Calendar.HOUR, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND}) {
            targetCalendar.set(field, sourceCalendar.get(field));
        }
        targetCalendar.setTimeZone(targetTimeZone);

        return targetCalendar.getTime();
    }

Подход 1 дает мне результат в виде строки.

03/22/2018 10:16:57 AM EDT <- instanceOf String

Подход 2 дает мне правильную дату и время восточного часового пояса, но у даты есть часовой пояс IST.

Thu Mar 22 10:16:57 IST 2018 <- instanceof Date

Может кто-нибудь, пожалуйста, помогите мне получить объект Date с Eastern Time TimeZone.

Обновление - моя конечная цель - получить Unix Timestamp текущего восточного времени.

1 ответ

Решение

ТЛ; др

Instant.now()                        // Capture the current moment in UTC, an `Instant` object.
    .atZone(                         // Adjust from UTC into a particular time zone.
        ZoneId.of( “Asia/Kolkata” ) 
    )                                // Returns a `ZonedDateTime` object. 
    .withZoneSameInstant(            // Adjust into yet another time zone. All three are the same moment but vowed using different wall-clock times. 
        ZoneId.of( “Africa/Tunis” ) 
    )                                // Returns another `ZonedDateTime` object. 

Или же…

ZonedDateTime.now( 
    ZoneId.of( “Asia/Kolkata” )
).withZoneSameInstant(
    ZoneId.of( “Africa/Tunis” )
)

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

Во-первых, прекратите использовать устаревшие классы даты и времени. Они ужасный беспорядок. Заменены классами java.time.

  • Date заменяется Instant,
  • Calendar заменяется ZonedDateTime
  • SimpleDateFormat заменяется DateTimeFormatter,

Обманутый Date::toString

Во-вторых, понимаю, что Date имеет ужасно запутанную функцию динамического применения текущего часового пояса JVM по умолчанию при генерации строки. Date всегда представляет момент в UTC. toString метод создает ложную иллюзию Date несущий часовой пояс, когда фактически его значение находится в UTC. Несмотря на благие намерения дизайнеров классов, это было катастрофическое решение, которое в течение десятилетий не вызывало путаницы среди бесчисленных программистов.

Еще хуже: там на самом деле часовой пояс похоронен в Date, но не имеет отношения к этому обсуждению. Смешение? Да; как я уже сказал, ужасный беспорядок плохого дизайна.

Instant

Instant замена класса Date намного понятнее Instant представляет момент, точку на временной шкале, всегда в UTC, с разрешением наносекунд.

использование Instant захватить текущий момент в UTC. Текущий часовой пояс JVM по умолчанию не имеет значения. Назначенный часовой пояс операционной системы не имеет значения.

Instant instant = Instant.now() ;  // Capture the current moment in UTC. 

В отличие от Date::toString, Instant::toString Метод говорит правду. Instant всегда в UTC, поэтому toString всегда сообщает UTC. Строка генерируется в стандартном формате ISO 8601. Z на конце не хватает Zulu и означает UTC.

instant.toString (): 2018-01-23T12: 34: 56.123456789Z

О захвате текущего момента... В Java 8 текущий момент был захвачен в миллисекундах, хотя классы java.time могут представлять наносекунды. В Java 9 и позже, новая реализация Clock обеспечивает захват текущего момента в более тонкой детализации. В Java 9.0.4 на macOS Sierra я вижу микросекунды. Аппаратные часы на обычных компьютерах в настоящее время не могут уловить текущий момент с точностью до микросекунд.

ZonedDateTime

Чтобы увидеть тот же момент через объектив настенного времени, используемого людьми определенного региона, назначьте часовой пояс этого региона. Применяя ZoneId для Instant производит ZonedDateTime, Концептуально:

ZonedDateTime = (Instant + ZoneId)

В коде:

ZoneId z = ZoneId.of( “Pacific/Auckland” ) ;
ZonedDateTime zdt = instant.atZone( z ) ;   // Same moment, same point on the timeline, different wall-clock time. 

Настроиться на другой часовой пояс легко. Вы можете начать с Instant снова.

ZoneId zKolkata = ZoneId.of( “Asia/Kolkata” ) ;
ZonedDateTime zdt = instant.atZone( zKolkata ) ;  

Или вы можете настроить ZonedDateTime объект. Классы java.time используют неизменяемые объекты. Таким образом, вместо того, чтобы "видоизменять" (изменять) исходный объект, корректировка создает новый отдельный объект.

ZonedDateTime zdtKolkata = zdt.withZoneSameInstant( zKolkata ) ;  // Same moment, same point on the timeline, different wall-clock time. 

Вы можете пропустить использование Instant, Я не рекомендую делать это. Программисты должны думать, отлаживать, регистрировать, обмениваться данными и многое из своей бизнес-логики в UTC. Так Instant должен быть вашим переходным классом всякий раз, когда вы начинаете любую работу со значениями даты и времени.

ZonedDateTime zdtNewYork = ZonedDateTime.now( ZoneId.of( "America/New_York" ) ) ;

ZonedDateTime::toString Метод мудро расширяет стандарт ISO 8601, добавляя название часового пояса в квадратных скобках.

String output = zdtNewYork.toString() ;

2018-01-23T07: 34: 56.123456789-05: 00 [Америка /New_York]


О java.time

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

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

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

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

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

  • Java SE 8, Java SE 9 и более поздние
    • Встроенный.
    • Часть стандартного Java API со встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функциональности java.time перенесена на Java 6 и 7 в ThreeTen-Backport.
  • Android
    • Более поздние версии Android связывают реализации классов java.time.
    • Для более ранних версий Android (<26) проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите Как использовать ThreeTenABP….

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

Другие вопросы по тегам