Перетворити LocalDateTime на LocalDateTime в UTC


86

Перетворити LocalDateTime на LocalDateTime в UTC.

LocalDateTime convertToUtc(LocalDateTime date) {

    //do conversion

}

Я шукав через мережу. Але рішення не отримав


4
Ви знайшли javadoc для LocalDateTime? У ньому сказано: "Цей клас не зберігає і не відображає часовий пояс. Натомість, це опис дати, яка використовується для днів народження, в поєднанні з місцевим часом, який видно на настінному годиннику. Він не може представляти мить на часовий рядок без додаткової інформації, наприклад, зміщення або часовий пояс ".
aro_tech

1
Ваше запитання не має сенсу - вам слід пояснити контекст цього методу та те, що ви намагаєтесь досягти. Здається, у вас є фундаментальне нерозуміння того, що представляють різні класи API.
assylias

3
Якщо ви дбаєте про часові пояси, вам потрібно використовувати ZonedDateTime, який має методи перетворення між часовими поясами withZoneSameLocal () та withZoneSameInstant ()
JodaStephen

Я. Я зрозумів. Дякую
Sarika.S

Відповіді:


105

Я особисто віддаю перевагу

LocalDateTime.now(ZoneOffset.UTC);

оскільки це найбільш читабельний варіант.


26
Хіба це не створює нового часу (зараз)? Початкове питання
стосувалось

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

74

Є ще простіший спосіб

LocalDateTime.now(Clock.systemUTC())

26
Приємно, але не відповідає на вихідне запитання.
eirirlar

3
Ця відповідь перетворює дату UTC у LocalDate. Початкове питання полягало в тому, як перетворити LocalDate на дату UTC.
Cypress Frankenfeld

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

65

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 )
Василь Бурк

15

Скористайтеся наведеним нижче. Він бере місцевий час і перетворює його у UTC, використовуючи часовий пояс. Вам не потрібно створювати його функцію.

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

Якщо вам потрібно отримати частину LocalDateTime із ZonedDateTime, тоді ви можете використовувати наступне.

nowUTC.toLocalDateTime();

Ось статичний метод, який я використовую у своєму додатку, щоб вставити час UTC у mysql, оскільки я не можу додати значення UTC_TIMESTAMP за замовчуванням до стовпця дати та часу.

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()методу залежить від часу, переданого як аргумент, оскільки він враховує всі правила часового поясу, включаючи літній час. У прикладах час був 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 не змінюється. Тому зміщення в інших часових поясах коригується. У цьому прикладі літній час Естонії становить 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 пт до UTC Z? нічого не означає. UTC = Z, UTC <> пт
Трістан

-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сучасний API дати та часу Java та його DateTimeFormatter.
Оле В. В.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.