Java: Как вы конвертируете временную метку UTC в локальное время?
У меня есть отметка времени, что в UTC, и я хочу преобразовать ее в локальное время без использования вызова API, такого как TimeZone.getTimeZone("PST")
. Как именно вы должны это делать? Я использовал следующий код без особого успеха:
private static final SimpleDateFormat mSegmentStartTimeFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
Calendar calendar = Calendar.getInstance();
try {
calendar.setTime(mSegmentStartTimeFormatter.parse(startTime));
}
catch (ParseException e) {
e.printStackTrace();
}
return calendar.getTimeInMillis();
Пример входного значения: [2012-08-15T22:56:02.038Z]
должен возвращать эквивалент [2012-08-15T15:56:02.038Z]
Ответы
Ответ 1
Date
не имеет часовой пояс и внутренне хранится в UTC. Только при форматировании даты применяется коррекция часового пояса. При использовании DateFormat
по умолчанию используется часовой пояс JVM, в котором он запущен. Используйте setTimeZone
, чтобы изменить его при необходимости.
DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = utcFormat.parse("2012-08-15T22:56:02.038Z");
DateFormat pstFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
pstFormat.setTimeZone(TimeZone.getTimeZone("PST"));
System.out.println(pstFormat.format(date));
Отпечатает 2012-08-15T15:56:02.038
Обратите внимание, что я оставил 'Z'
в формате PST, так как он указывает UTC. Если вы просто пошли с Z
, тогда выход был бы 2012-08-15T15:56:02.038-0700
Ответ 2
Используйте современный API дат и времени Java, и это просто:
String inputValue = "2012-08-15T22:56:02.038Z";
Instant timestamp = Instant.parse(inputValue);
ZonedDateTime losAngelesTime = timestamp.atZone(ZoneId.of("America/Los_Angeles"));
System.out.println(losAngelesTime);
Отпечатает
2012-08-15T15:56:02.038-07:00[America/Los_Angeles]
Примечание:
- Это небольшая ошибка в ваших ожиданиях.
Z
в вашей метке времени означает UTC, также известное как время Зулу. Поэтому в вашем местном значении времени Z
не должно быть. Скорее вам нужно получить возвращаемое значение, например, 2012-08-15T15:56:02.038-07:00
, так как смещение теперь составляет -7 часов, а не Z.
- Избегайте аббревиатур с часовыми поясами из трех букв. Они не стандартизированы и, следовательно, чаще всего неоднозначны. PST, например, может означать стандартное время Philppine, стандартное время в Pacific Standard или стандартное время Pitcairn (хотя S в аббревиатуре часто используется для летнего времени (что означает DST)). Если вы планируете использовать "Стандартное время по тихоокеанскому времени", это даже не часовой пояс, так как летом (где падает временная метка вашего образца) используется тихое время дневного света. Вместо аббревиатур используются идентификаторы часовых поясов в формате region/city, как в моем коде.
- Временные метки обычно лучше всего обрабатываются как объекты
Instant
. Преобразуйте в ZonedDateTime
только тогда, когда у вас есть необходимость, например, для презентации.
Вопрос: могу ли я использовать современный API с моей версией Java?
Если вы используете хотя бы Java 6, вы можете.
Ответ 3
Вот простое модифицированное решение
public String convertToCurrentTimeZone(String Date) {
String converted_date = "";
try {
DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = utcFormat.parse(Date);
DateFormat currentTFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
currentTFormat.setTimeZone(TimeZone.getTimeZone(getCurrentTimeZone()));
converted_date = currentTFormat.format(date);
}catch (Exception e){ e.printStackTrace();}
return converted_date;
}
//get the current time zone
public String getCurrentTimeZone(){
TimeZone tz = Calendar.getInstance().getTimeZone();
System.out.println(tz.getDisplayName());
return tz.getID();
}