Java: Как вы конвертируете временную метку UTC в локальное время? - программирование

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]

4b9b3361

Ответ 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, вы можете.

  • В Java 8 и более поздних версиях появился новый API.
  • В Java 6 и 7 получите The ThreeTen Backport, backport из новых классов (это ThreeTen для JSR-310, где современный API был сначала определен).
  • На Android, используйте Android-версию ThreeTen Backport. Его называют ThreeTenABP, и я думаю, что theres замечательное объяснение в этом вопросе: как использовать ThreeTenABP в проекте Android.

Ответ 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();
    }