Преобразование даты UTC в дату другого часового пояса - PullRequest
0 голосов
/ 17 апреля 2019

Я получаю дату, которая представляет дату и время в utc. Скажем так: 21 июня 2019 г. 10:00

Я бы хотел перевести эту дату в часовой пояс "Европа / Вена", ожидая: 21 июня 2016 г. 12:00

Я не понимаю, почему мой код ниже показывает одинаковое время для обоих

        Date utcFinish = new Date(new Date().getYear(), Calendar.JUNE, 21);
        TimeZone europeVienna = TimeZone.getTimeZone("Europe/Vienna");
        Calendar finishInViennaTime = Calendar.getInstance(europeVienna);
        finishInViennaTime.setTime(utcFinish);

        System.out.println(format.format(utcFinish));
        System.out.println(format.format(finishInViennaTime.getTime()));

Выход:

2019-06-21 00:00
2019-06-21 00:00

Какое будет лучшее решение только для java7 (без joda, localdate pls) !? Спасибо

РЕДАКТИРОВАТЬ: Я также пытался:

        SimpleDateFormat formatWithTimezone = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        formatWithTimezone.setTimeZone(TimeZone.getTimeZone("Europe/Vienna"));

        SimpleDateFormat formatonly = new SimpleDateFormat("yyyy-MM-dd HH:mm");

        Date utcDate = new Date(new Date().getYear(), Calendar.JUNE, 21);

        System.out.println(formatonly.format(utcDate));
        System.out.println(formatWithTimezone.format(utcDate));

Выход:

2019-06-21 00:00
2019-06-21 00:00

РЕШЕНИЕ

Спасибо за все решения. В итоге проблема была в часовом поясе по умолчанию. Вот мое текущее решение (дальнейшая обратная связь приветствуется!):

        // Unfortunately this date has the wrong time zone (Local Time Zone),
        // because Date assumes Local Time Zone the database stores timestamps 
        // in utc that's why I now convert to a datestring and reparse

        Date finishTimeWrongTimeZone = new Date(new Date().getYear(), Calendar.JUNE, 21);
        // in reality i call the db here like getFinishTime();

        // get the plain date string without time shifting
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MMM-dd HH:mm");
        String dateWithoutTimeZone = formatter.format(finishTimeWrongTimeZone);

        // add the timezone to the formatter and reinterpret the datestring
        // effectively adding the correct time zone the date should be in
        formatter.setTimeZone(TimeZone.getTimeZone("UTC"));

        String finishTime = null;
        try {

            Date dateWithCorrectTimeZone = formatter.parse(dateWithoutTimeZone);

            // Convert to expected local time zone (europe/vienna)
            formatter.setTimeZone(TimeZone.getTimeZone("Europe/Vienna"));
            finishTime = formatter.format(dateWithCorrectTimeZone);

        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(finishTime);

Ответы [ 4 ]

1 голос
/ 17 апреля 2019

Современное (java.time) решение

У меня есть версия для старого API ниже, как вы и просили, но для полноты я также предоставлю более современное решение.Я рекомендую вам заглянуть в ThreeTen-Backport, если обновление Java не является вариантом:

ZonedDateTime zdt = LocalDateTime.of(
    Year.now().getValue(), Month.JUNE, 21, 10, 0, 0
).atZone(ZoneOffset.UTC);

System.out.println(
    zdt.withZoneSameInstant(ZoneId.of("Europe/Vienna"))
      .format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm"))
);

Старое (java.util) решение

new Date(...) устарело, и вы не должны использоватьЭто.Если вам действительно нужно придерживаться старого API;вам нужно будет использовать Calendar:

Calendar utcFinish = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
utcFinish.set(Calendar.MONTH, Calendar.JUNE);
utcFinish.set(Calendar.DATE, 21);
utcFinish.set(Calendar.HOUR_OF_DAY, 10);
utcFinish.set(Calendar.MINUTE, 0);

А затем использовать DateFormat с часовым поясом, с которым вы действительно хотите напечатать его:

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
TimeZone europeVienna = TimeZone.getTimeZone("Europe/Vienna");
format.setTimeZone(europeVienna);

System.out.println(format.format(utcFinish.getTime()));

Output

Оба решения должны вывести (на момент написания, в 2019 году):

2019-06-21 12:00
1 голос
/ 17 апреля 2019

Измените часовой пояс перед выполнением формата.Дата будет соответственно «преобразована», но, как мы уже говорили, у этого старого стиля кодирования есть много недостатков:

public static void main(String[] x) {
    Date instant = new Date(new Date().getYear(), Calendar.JUNE, 21); // this call assumes the Timezone is your current default (system dependant).
    DateFormat sdf = SimpleDateFormat.getDateTimeInstance();

    sdf.setTimeZone(TimeZone.getTimeZone("Europe/Vienna"));
    System.out.println(sdf.format(instant)); //21 juin 2019 00:00:00

    sdf.setTimeZone(TimeZone.getTimeZone("Europe/Greenwich"));
    System.out.println(sdf.format(instant)); // 20 juin 2019 22:00:00

}
1 голос
/ 17 апреля 2019

Я использую один объект форматирования и изменяю часовой пояс на нем

Формат SimpleDateFormat = новый SimpleDateFormat ("дд-мм-гггг ЧЧ: мм"); format.setTimeZone (TimeZone.getTimeZone ( "UTC"));

Date dUtc = format.parse("21-06-2019 10:00");
System.out.println(dUtc);

TimeZone europeVienna = TimeZone.getTimeZone("europe/vienna");

format.setTimeZone(europeVienna);
String sVienna = format.format(dUtc);
System.out.println(sVienna);
0 голосов
/ 17 апреля 2019

Пожалуйста, используйте SimpleDateFormat для преобразования часового пояса

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date utcFinish = new Date(new Date().getYear(), Calendar.JUNE, 21);
TimeZone europeVienna = TimeZone.getTimeZone("Europe/Vienna");
format.setTimeZone(europeVienna);
System.out.println(format.format(utcFinish));
...