Преобразование LocalDateTime в LocalDateTime в формате UTC


86

Преобразуйте LocalDateTime в LocalDateTime в формате UTC.

LocalDateTime convertToUtc(LocalDateTime date) {

    //do conversion

}

Я поискал в сети. Но не получил решения


4
Вы нашли javadoc для LocalDateTime? В нем говорится: «Этот класс не хранит и не представляет часовой пояс. Вместо этого он представляет собой описание даты, которая используется для дней рождения, в сочетании с местным временем, как видно на настенных часах. Он не может представлять мгновение на шкала времени без дополнительной информации, такой как смещение или часовой пояс ".
aro_tech 06

1
Ваш вопрос не имеет смысла - вы должны объяснить контекст этого метода и то, чего вы пытаетесь достичь. Похоже, у вас есть фундаментальное непонимание того, что представляют собой различные классы API.
assylias 06

3
Если вам важны часовые пояса, вам нужно использовать ZonedDateTime, у которого есть методы преобразования между часовыми поясами withZoneSameLocal () и withZoneSameInstant ()
JodaStephen

Я. Я понял. Спасибо
Sarika.S 06

Ответы:


105

Я лично предпочитаю

LocalDateTime.now(ZoneOffset.UTC);

так как это наиболее читаемый вариант.


26
Разве это не создает новое время (сейчас)? Первоначальный вопрос был о преобразовании известного времени в UTC
Evvo

Как нам преобразовать LocalDateTime в UTC -7: 00
Ашок Кумар Ганесан

74

Есть еще более простой способ

LocalDateTime.now(Clock.systemUTC())

26
Красиво, но не отвечает на исходный вопрос.
eirirlar

3
Этот ответ преобразует дату в формате UTC в LocalDate. Первоначальный вопрос заключался в том, как преобразовать LocalDate в дату в формате UTC.
Cypress Frankenfeld

Как нам преобразовать LocalDateTime в UTC -7: 00
Ашок Кумар Ганесан

64

LocalDateTime не содержит информации о зоне. ZonedDatetime делает.

Если вы хотите преобразовать LocalDateTime в UTC, вам нужно обернуть кулаком ZonedDateTime.

Вы можете конвертировать, как показано ниже.

LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt.toLocalTime());

ZonedDateTime ldtZoned = ldt.atZone(ZoneId.systemDefault());

ZonedDateTime utcZoned = ldtZoned.withZoneSameInstant(ZoneId.of("UTC"));

System.out.println(utcZoned.toLocalTime());

2
Это правильно, хотя технически не завернутый. ldt.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC"))в то время как краткий по-прежнему передает достаточно смысла, чтобы не нуждаться в переменной зонированного экземпляра.
Бретт Райан

22
ZoneOffset.UTCхорошая замена дляZoneI‌​d.of("UTC")
ycomp

2
Для UTC OffsetDateTimeболее уместно, чем ZonedDateTime. Используйте: OffsetDateTime.now( ZoneOffset.UTC )илиmyInstant.atOffset( ZoneOffset.UTC )
Basil

15

Используйте ниже. Он берет местное datetime и преобразует его в UTC с использованием часового пояса. Вам не нужно создавать его функцию.

ZonedDateTime nowUTC = ZonedDateTime.now(ZoneOffset.UTC);
System.out.println(nowUTC.toString());

Если вам нужно получить часть LocalDateTime ZonedDateTime, вы можете использовать следующее.

nowUTC.toLocalDateTime();

Вот статический метод, который я использую в своем приложении для вставки времени UTC в mysql, поскольку я не могу добавить значение по умолчанию UTC_TIMESTAMP в столбец datetime.

public static LocalDateTime getLocalDateTimeInUTC(){
    ZonedDateTime nowUTC = ZonedDateTime.now(ZoneOffset.UTC);

    return nowUTC.toLocalDateTime();
}

14

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

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public final class DateTimeUtil {
    private DateTimeUtil() {
        super();
    }

    public static void main(final String... args) {
        final LocalDateTime now = LocalDateTime.now();
        final LocalDateTime utc = DateTimeUtil.toUtc(now);

        System.out.println("Now: " + now);
        System.out.println("UTC: " + utc);
    }

    public static LocalDateTime toZone(final LocalDateTime time, final ZoneId fromZone, final ZoneId toZone) {
        final ZonedDateTime zonedtime = time.atZone(fromZone);
        final ZonedDateTime converted = zonedtime.withZoneSameInstant(toZone);
        return converted.toLocalDateTime();
    }

    public static LocalDateTime toZone(final LocalDateTime time, final ZoneId toZone) {
        return DateTimeUtil.toZone(time, ZoneId.systemDefault(), toZone);
    }

    public static LocalDateTime toUtc(final LocalDateTime time, final ZoneId fromZone) {
        return DateTimeUtil.toZone(time, fromZone, ZoneOffset.UTC);
    }

    public static LocalDateTime toUtc(final LocalDateTime time) {
        return DateTimeUtil.toUtc(time, ZoneId.systemDefault());
    }
}

Также добавьте: final LocalDateTime backToLocal = DateTimeUtil.toZone (utc, ZoneOffset.UTC, ZoneId.systemDefault ()); System.out.println («Вернуться к локальному:» + backToLocal);
rjdkolb

9

Вопрос?

Глядя на ответы и вопрос, кажется, что вопрос был значительно изменен. Итак, чтобы ответить на текущий вопрос:

Преобразуйте LocalDateTime в LocalDateTime в формате UTC.

Часовой пояс?

LocalDateTimeне хранит никакой информации о часовом поясе, он просто содержит значения года, месяца, дня, часа, минуты, секунды и меньших единиц. Итак, важный вопрос: каков часовой пояс оригинала LocalDateTime? С таким же успехом это может быть UTC, поэтому преобразование производить не нужно.

Системный часовой пояс по умолчанию

Учитывая, что вы все равно задали вопрос, вы, вероятно, имели в виду, что исходное время находится в часовом поясе вашей системы по умолчанию, и вы хотите преобразовать его в UTC. Потому что обычно LocalDateTimeобъект создается с использованием, LocalDateTime.now()которое возвращает текущее время в часовом поясе системы по умолчанию. В этом случае преобразование будет следующим:

LocalDateTime convertToUtc(LocalDateTime time) {
    return time.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime();
}

Пример процесса конвертации:

2019-02-25 11:39 // [time] original LocalDateTime without a timezone
2019-02-25 11:39 GMT+1 // [atZone] converted to ZonedDateTime (system timezone is Madrid)
2019-02-25 10:39 GMT // [withZoneSameInstant] converted to UTC, still as ZonedDateTime
2019-02-25 10:39 // [toLocalDateTime] losing the timezone information

Явный часовой пояс

В любом другом случае, когда вы явно указываете часовой пояс времени для преобразования, преобразование будет следующим:

LocalDateTime convertToUtc(LocalDateTime time, ZoneId zone) {
    return time.atZone(zone).withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime();
}

Пример процесса конвертации:

2019-02-25 11:39 // [time] original LocalDateTime without a timezone
2019-02-25 11:39 GMT+2 // [atZone] converted to ZonedDateTime (zone is Europe/Tallinn)
2019-02-25 09:39 GMT // [withZoneSameInstant] converted to UTC, still as ZonedDateTime
2019-02-25 09:39 // [toLocalDateTime] losing the timezone information

В atZone()Метод

Результат atZone() метода зависит от времени, переданного в качестве аргумента, поскольку он учитывает все правила часового пояса, включая летнее время (DST). В примерах было 25 февраля, в Европе это означает зимнее время (без летнего времени).

Если бы мы использовали другую дату, скажем 25 августа прошлого года, результат был бы другим, учитывая летнее время:

2018-08-25 11:39 // [time] original LocalDateTime without a timezone
2018-08-25 11:39 GMT+3 // [atZone] converted to ZonedDateTime (zone is Europe/Tallinn)
2018-08-25 08:39 GMT // [withZoneSameInstant] converted to UTC, still as ZonedDateTime
2018-08-25 08:39 // [toLocalDateTime] losing the timezone information

Время по Гринвичу не меняется. Поэтому корректируются смещения в других часовых поясах. В этом примере летнее время в Эстонии - GMT + 3, а зимнее время - GMT + 2.

Также, если вы укажете время перехода, измените часы на один час назад. Например, 28 октября 2018 г., 03:30 для Эстонии, это может означать два разных времени:

2018-10-28 03:30 GMT+3 // summer time [UTC 2018-10-28 00:30]
2018-10-28 04:00 GMT+3 // clocks are turned back 1 hour [UTC 2018-10-28 01:00]
2018-10-28 03:00 GMT+2 // same as above [UTC 2018-10-28 01:00]
2018-10-28 03:30 GMT+2 // winter time [UTC 2018-10-28 01:30]

Без указания смещения вручную (GMT + 2 или GMT + 3) время 03:30для часового поясаEurope/Tallinn может означать два разных времени UTC и два разных смещения.

Резюме

Как видите, конечный результат зависит от часового пояса времени, переданного в качестве аргумента. Поскольку часовой пояс не может быть извлечен из LocalDateTimeобъекта, вы должны сами знать, из какого он часового пояса, чтобы преобразовать его в UTC.


1
спасибо за информацию о LocalDateTime не хранит никакой информации о часовом поясе! LocalDateTime does not store any information about the time-zone, it just basically holds the values of year, month, day, hour, minute, second, and smaller units.
LiuWenbin_NO.

5

tldr: это просто невозможно сделать; если вы пытаетесь это сделать, вы ошибаетесь с LocalDateTime .

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

Фактически, LocalDateTime.now () никогда не следует вызывать в производственном коде, если ваша цель - получение случайных результатов. Когда вы создаете экземпляр LocalDateTime таким образом, этот экземпляр содержит дату и время ТОЛЬКО на основе часового пояса текущего сервера, что означает, что этот фрагмент кода будет генерировать другой результат, если он запускает сервер с другой конфигурацией часового пояса.

LocalDateTime может упростить расчет даты. Если вам нужно реальное универсальное время передачи данных, используйте ZonedDateTime или OffsetDateTime: https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html .


LocalDateTime не записывает часовой пояс, но вы можете получить эту информацию откуда-то еще и добавить эту информацию в LocalDateTimes перед преобразованием.
Тристан

1

Попробуйте это с помощью этого метода.

конвертировать LocalDateTimeTo ZonedDateTime, используя из метода и передать часовой пояс системы по умолчанию , или вы можете использовать ZoneId вашей зоны , какZoneId.of("Australia/Sydney");

LocalDateTime convertToUtc(LocalDateTime dateTime) {
  ZonedDateTime dateTimeInMyZone = ZonedDateTime.
                                        of(dateTime, ZoneId.systemDefault());

  return dateTimeInMyZone
                  .withZoneSameInstant(ZoneOffset.UTC)
                  .toLocalDateTime();
  
}

Чтобы преобразовать обратно в местное время вашей зоны, используйте:

LocalDateTime convertFromUtc(LocalDateTime utcDateTime){
    return ZonedDateTime.
            of(utcDateTime, ZoneId.of("UTC"))
            .toOffsetDateTime()
            .atZoneSameInstant(ZoneId.systemDefault())
            .toLocalDateTime();
}

-1

вы можете реализовать помощник, делающий что-то вроде этого:

public static LocalDateTime convertUTCFRtoUTCZ(LocalDateTime dateTime) {
    ZoneId fr = ZoneId.of("Europe/Paris");
    ZoneId utcZ = ZoneId.of("Z");
    ZonedDateTime frZonedTime = ZonedDateTime.of(dateTime, fr);
    ZonedDateTime utcZonedTime = frZonedTime.withZoneSameInstant(utcZ);
    return utcZonedTime.toLocalDateTime();
}

UTC fr до UTC Z? ничего не значит. UTC = Z, UTC <> fr
Tristan

-2
public static String convertFromGmtToLocal(String gmtDtStr, String dtFormat, TimeZone lclTimeZone) throws Exception{
        if (gmtDtStr == null || gmtDtStr.trim().equals("")) return null;
        SimpleDateFormat format = new SimpleDateFormat(dtFormat);
        format.setTimeZone(getGMTTimeZone());
        Date dt = format.parse(gmtDtStr);
        format.setTimeZone(lclTimeZone);
        return

format.format (dt); }


1
Пожалуйста, не учите молодых пользоваться давно устаревшим и заведомо неприятным SimpleDateFormatуроком. По крайней мере, не как первый вариант. И не без оговорок. Сегодня у нас намного лучше java.time, современный Java API даты и времени и его DateTimeFormatter.
Ole VV
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.