Конвертировать дату в восточное время - получить объект 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
и многое другое.