Преобразование часового пояса - PullRequest
38 голосов
/ 04 июля 2011

Мне нужно конвертировать из одного часового пояса в другой часовой пояс в моем проекте.

Я могу конвертировать из моего текущего часового пояса в другой, но не из другого часового пояса в другой.

Например, я нахожусь в Индии, и я могу конвертировать из Индии в США, используя Date d=new Date();, назначая его объекту календаря и устанавливая часовой пояс.

Однако я не могу сделать это из другого часового пояса в другой часовой пояс. Например, я нахожусь в Индии, но у меня возникают проблемы с преобразованием часовых поясов из США в Великобританию.

Ответы [ 11 ]

44 голосов
/ 15 июля 2014

tl; dr

ZonedDateTime.now( ZoneId.of( "Pacific/Auckland" ))              // Current moment in a particular time zone.
             .withZoneSameInstant( ZoneId.of( "Asia/Kolkata" ))  // Same moment adjusted into another time zone. 

Подробности

Классу java.util.Date не присвоен часовой пояс , но его реализация toString сбивает с толкутекущий часовой пояс JVM по умолчанию.

Избегайте java.util.Date & .Calendar

Это одна из многих причин избегать печально известных классов java.util.Date, .Calendar и SimpleDateFormat, связанных с Java.Избежать их.Вместо этого используйте:

java.time

Java 8 и более поздних версий имеет встроенный пакет java.time .Этот пакет был вдохновлен Joda-Time .Хотя они имеют некоторые общие черты и имена классов, они разные;у каждого есть особенности, у другого нет.Одно заметное отличие состоит в том, что java.time избегает конструкторов, а вместо этого использует статические методы создания экземпляров.Обе структуры возглавляет один и тот же человек, Стивен Колборн .

Большая часть функциональности java.time была перенесена в Java 6 & 7 в проекте ThreeTen-Backport .Далее адаптирован для Android в проекте ThreeTenABP .

В случае с этим Вопросом они работают одинаково.Укажите часовой пояс и вызовите метод now, чтобы получить текущий момент, затем создайте новый экземпляр на основе старого неизменяемого экземпляра, чтобы настроить его для часового пояса.

Обратите внимание на два разныхклассы часовых поясов.Одним из них является именованный часовой пояс, включающий все правила перехода на летнее время и другие подобные аномалии, а также смещение от UTC, в то время как другое является только смещением.

ZoneId zoneMontréal = ZoneId.of("America/Montreal"); 
ZonedDateTime nowMontréal = ZonedDateTime.now ( zoneMontréal );

ZoneId zoneTokyo = ZoneId.of("Asia/Tokyo"); 
ZonedDateTime nowTokyo = nowMontréal.withZoneSameInstant( zoneTokyo );

ZonedDateTime nowUtc = nowMontréal.withZoneSameInstant( ZoneOffset.UTC );

Joda-Time

НекоторыеПример кода в Joda-Time 2.3 следует.Найдите в StackOveflow еще много примеров и много обсуждений.

DateTimeZone timeZoneLondon = DateTimeZone.forID( "Europe/London" );
DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" );
DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );

DateTime nowLondon = DateTime.now( timeZoneLondon ); // Assign a time zone rather than rely on implicit default time zone.
DateTime nowKolkata = nowLondon.withZone( timeZoneKolkata );
DateTime nowNewYork = nowLondon.withZone( timeZoneNewYork );
DateTime nowUtc = nowLondon.withZone( DateTimeZone.UTC );  // Built-in constant for UTC.

У нас есть четыре представления одного и того же момента на временной шкале Вселенной.


На самом деле java.util.Date класс имеет часовой пояс, скрытый в его исходном коде .Но класс игнорирует этот часовой пояс для большинства практических целей.Таким образом, в качестве стенограммы часто говорят, что juDate не имеет назначенного часового пояса.Смешение?Да.Избегайте беспорядка, который является juDate и используйте Joda-Time и / или java.time.

38 голосов
/ 04 июля 2011

Некоторые примеры

Преобразование времени между часовым поясом

Преобразование времени между часовыми поясами

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public class TimeZoneExample {
    public static void main(String[] args) {
        // Create a calendar object and set it time based on the local
        // time zone
        Calendar localTime = Calendar.getInstance();
        localTime.set(Calendar.HOUR, 17);
        localTime.set(Calendar.MINUTE, 15);
        localTime.set(Calendar.SECOND, 20);

        int hour = localTime.get(Calendar.HOUR);
        int minute = localTime.get(Calendar.MINUTE);
        int second = localTime.get(Calendar.SECOND);


        // Print the local time
        System.out.printf("Local time  : %02d:%02d:%02d\n", hour, minute, second);


        // Create a calendar object for representing a Germany time zone. Then we
        // wet the time of the calendar with the value of the local time

        Calendar germanyTime = new GregorianCalendar(TimeZone.getTimeZone("Europe/Berlin"));
        germanyTime.setTimeInMillis(localTime.getTimeInMillis());
        hour = germanyTime.get(Calendar.HOUR);
        minute = germanyTime.get(Calendar.MINUTE);
        second = germanyTime.get(Calendar.SECOND);


        // Print the local time in Germany time zone
        System.out.printf("Germany time: %02d:%02d:%02d\n", hour, minute, second);
    }
}
7 голосов
/ 04 июля 2011
    Date date = new Date();
    String formatPattern = ....;
    SimpleDateFormat sdf = new SimpleDateFormat(formatPattern);

    TimeZone T1;
    TimeZone T2;

    // set the Calendar of sdf to timezone T1
    sdf.setTimeZone(T1);
    System.out.println(sdf.format(date));

    // set the Calendar of sdf to timezone T2
    sdf.setTimeZone(T2);
    System.out.println(sdf.format(date));

    // Use the 'calOfT2' instance-methods to get specific info
    // about the time-of-day for date 'date' in timezone T2.
    Calendar calOfT2 = sdf.getCalendar();
5 голосов
/ 04 июля 2011

Часовой пояс «по умолчанию» можно полностью избежать, просто установив часовой пояс для объекта Calendar.Тем не менее, я бы лично предложил вам использовать Joda Time в качестве значительно превосходящего API для операций с датой и временем в Java.Среди прочего, преобразование часового пояса в Joda очень простое.

Не ясно, как выглядит ваш текущий код и почему вы можете конвертировать только через часовой пояс по умолчанию, но в Joda Time вы быпросто укажите часовой пояс явно при создании (скажем) объекта DateTime, а затем используйте withZone(DateTimeZone zone).

Если бы вы могли рассказать нам больше о том, как вы получаете входные данныеМы могли бы привести более полный пример.

4 голосов
/ 15 июля 2014

Вы можете использовать следующий фрагмент кода

String dateString = "14 Jul 2014 00:11:04 CEST";
date = formatter.parse(dateString);
System.out.println(formatter.format(date));

// Set the formatter to use a different timezone - Indochina Time
formatter.setTimeZone(TimeZone.getTimeZone("Asia/Bangkok"));
System.out.println("ICT time : "+formatter.format(date));
2 голосов
/ 19 мая 2016

Если вы не хотите использовать Joda, вот детерминированный способ использования встроенных библиотек.

Прежде всего, я рекомендую принудительно установить для вашей JVM часовой пояс. Это решает проблемы, с которыми вы можете столкнуться при перемещении JVM с одного компьютера на другой, для которого установлены разные часовые пояса, но ваши исходные данные всегда находятся в определенном часовом поясе. Например, допустим, ваши данные всегда являются часовым поясом PDT / PST, но вы запускаете окно, для которого установлен часовой пояс UTC.

Следующий фрагмент кода устанавливает часовой пояс по умолчанию в моей JVM:

 //You can either pass the JVM a parameter that 
 //enforces a TZ: java -Duser.timezone=UTC or you can do it
 //programatically like this
 TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
 TimeZone.setDefault(tz);

Теперь предположим, что ваша исходная дата указывается в формате PDT / PST, но вам нужно преобразовать ее в UTC. Это шаги:

    DateFormat dateFormatUtc = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC"));

    String dateStrInPDT = "2016-05-19 10:00:00";
    Date dateInPDT = dateFormat.parse(dateStrInPDT);


    String dateInUtc = dateFormatUtc.format(dateInPDT);

    System.out.println("Date In UTC is " + dateInUtc);

Вывод будет:

Date In UTC is 2016-05-19 17:00:00
1 голос
/ 16 января 2017

Это не ответ, но он может помочь кому-то попытаться сгенерировать даты с тем же часовым поясом и применить смещение другого часового пояса. Это полезно, когда ваш сервер приложений работает в одном часовом поясе, а база данных - в другом.

public static Date toGreekTimezone (Date date) {
  ZoneId greek = ZoneId.of(EUROPE_ATHENS);
  ZonedDateTime greekDate = ZonedDateTime.ofInstant(date.toInstant(), greek);

  ZoneId def = ZoneId.systemDefault();
  ZonedDateTime defDate = greekDate.withZoneSameLocal(def);

  return Date.from(defDate.toInstant());
}
1 голос
/ 18 июля 2016

Вы можете использовать метод java.time.ZoneDateTime#ofInstant():

import java.time.*;

public class TimeZonesConversion {
    static ZonedDateTime convert(ZonedDateTime time, ZoneId newTimeZone) {
        return ZonedDateTime.ofInstant(
                time.toInstant(),
                newTimeZone);
    };

    public static void main(String... args) {
        ZonedDateTime mstTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("-07")); 
        ZonedDateTime localTime = convert(mstTime, Clock.systemDefaultZone().getZone());
        System.out.println("MST(" + mstTime + ") = " + localTime);
    }
}
1 голос
/ 14 марта 2015

Зависит от того, что вы на самом деле подразумеваете под «преобразованием».

Это МОЖЕТ быть таким же простым, как установка часового пояса в FORMATTER, и вообще не связываться с Календарем.

Calendar cal = Calendar.getInstance();

TimeZone tzUTC = TimeZone.getTimeZone( "UTC" );
TimeZone tzPST = TimeZone.getTimeZone( "PST8PDT" );

DateFormat dtfmt = new SimpleDateFormat( "EEE, yyyy-MM-dd KK:mm a z" );

dtfmt.setTimeZone( tzUTC );
System.out.println( "UTC: " + dtfmt.format( cal.getTime() ));

dtfmt.setTimeZone( tzPST );
System.out.println( "PST: " + dtfmt.format( cal.getTime() ));
1 голос
/ 04 июля 2011

Вы можете сделать что-то подобное, чтобы получить текущее время в другом часовом поясе.

Calendar japanCal = new GregorianCalendar(TimeZone.getTimeZone("Japan"));
japanCal.setTimeInMillis(local.getTimeInMillis());
...