Java конвертировать время ET в время UTC Oracle DB Timestamp - PullRequest
0 голосов
/ 19 октября 2019

У нас есть столбец update_date в БД. Этот столбец базы данных Oracle типа TIMESTAMP обновляется со временем ET.

Когда я нахожусь в UTC время - 19-Oct-2019 4:51 AM, БД сохраняет это время в Update_date Column как 19-Oct-19 00:51 AM.

Я пытаюсь преобразовать Update_date в UTC в Java из БД. Это не работает. Тем не менее, он показывает только часовой пояс ET.

Мой текущий системный часовой пояс - UTC - 19-Oct-2019 4:51 AM
Сохранение БД в часовом поясе ET - 19-Oct-2019 00:51 AM
Преобразование столбца БД (часового пояса ET) в UTC в Java: 19-Oct-2019 00:51 AM
ожидаетсявывод: 19-Oct-2019 4:51 AM

Java-код, используемый не работает:

Date fromDate = new Date(2019,10,19,00,51,00); //ET time from DB Update_date column
DateFormat gmtFormat = new SimpleDateFormat("MM/dd/yyyy hh:mm aa");
TimeZone gmtTime = TimeZone.getTimeZone("GMT");

gmtFormat.setTimeZone(gmtTime);
System.out.println(gmtFormat.format(fromDate));

1 Ответ

3 голосов
/ 19 октября 2019

java.time

Эта проблема неоднократно освещалась при переполнении стека, поэтому я буду краток. И вы забыли предоставить важную информацию, такую ​​как, какая база данных и какой тип данных столбца, поэтому я не могу дать конкретное решение для кода.

Чтобы извлечь момент из базы данных, используйте OffsetDateTime.

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

Чтобы увидеть этот момент через настенные часы, используемые людьми определенного региона (часового пояса), примените ZoneId, чтобы получить ZonedDateTime объект.

Обратите внимание, что "ET time" это , а не часовой пояс. Укажите собственное имя часового пояса в формате Continent/Region, например America/Montreal, Africa/Casablanca или Pacific/Auckland. Никогда не используйте 2-4 буквенные сокращения, такие как EST или IST, так как они не истинных часовых поясов, не стандартизированы и даже не уникальны (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ; 
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

Для столбцов типа, схожего с стандартом SQL TIMESTAMP WITH TIME ZONE, многие базы данных перед сохранением вводят значения UTC . Поэтому при получении объект OffsetDateTime, скорее всего, будет в UTC. Но чтобы быть уверенным, просто извлеките Instant. Instant всегда находится в UTC по определению.

Instant instant = odt.toInstant() ;  // Adjust to UTC (if not already in UTC).

Если ваш столбец имеет тип, похожий на стандарт SQL TIMESTAMP WITHOUT TIME ZONE, вы используете неправильный тип для отслеживания момента, определенногоуказать на временной шкале. Вы не знаете, какой часовой пояс был у предыдущих сохраненных значений, потому что любая предоставленная информация о часовом поясе или смещении игнорируется и удаляется из всех входных данных. Так что у вас в руках беспорядок. Вы должны реорганизовать вашу базу данных , чтобы использовать правильный тип. Вы можете попытаться угадать предполагаемый часовой пояс и применить эту зону во время рефакторинга, но вы будете только догадываться.

// Extract old value without zone/offset info.
LocalDateTime ldt = myResultSet.getObject( oldColumn , LocalDateTime.class ) ;

// Guessing this time zone was originally intended. 
ZoneId z = ZoneId.of( "America/New_York" ) ;

// Arbitrarily apply the time zone that we assume, but do not truly know, was intended when that date-time was originally stored.
ZonedDateTime zdt = ldt.atZone( z ) ;
OffsetDateTime odt = zdt.toOffsetDateTime() ;

// Store the new value in a new column.
myPreparedStatement.setObject( newColumn , odt ) ;

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

Ваш драйвер JDBC может обрабатывать ZonedDateTime. Но спецификация JDBC требует поддержки только для OffsetDateTime.

enter image description here

...