Chuyển đổi LocalDateTime thành LocalDateTime trong UTC


82

Chuyển đổi LocalDateTime thành LocalDateTime trong UTC.

LocalDateTime convertToUtc(LocalDateTime date) {

    //do conversion

}

Tôi đã tìm kiếm trên mạng. Nhưng không nhận được một giải pháp


4
Bạn có tìm thấy javadoc cho LocalDateTime không? Nó nói: "Lớp này không lưu trữ hoặc đại diện cho múi giờ. Thay vào đó, nó là một mô tả về ngày, như được sử dụng cho sinh nhật, kết hợp với giờ địa phương như được thấy trên đồng hồ treo tường. Nó không thể đại diện cho một thời điểm trên dòng thời gian không có thông tin bổ sung, chẳng hạn như chênh lệch hoặc múi giờ. "
aro_tech

1
Câu hỏi của bạn không có ý nghĩa - bạn nên giải thích bối cảnh của phương pháp này và những gì bạn đang cố gắng đạt được. Có vẻ như bạn đã hiểu sai cơ bản về những gì mà các lớp khác nhau của API đại diện.
assylias

3
Nếu bạn quan tâm đến thời gian khu, bạn cần phải sử dụng ZonedDateTime, trong đó có phương pháp chuyển đổi giữa thời gian khu withZoneSameLocal () và withZoneSameInstant ()
JodaStephen

Ya. Tôi đã hiểu. Cảm ơn
Sarika.S

Câu trả lời:


103

Cá nhân tôi thích

LocalDateTime.now(ZoneOffset.UTC);

vì nó là tùy chọn dễ đọc nhất.


19
Điều này không tạo ra một thời gian mới (bây giờ)? Câu hỏi ban đầu là về việc chuyển đổi một thời gian đã biết sang UTC
Evvo

73

Có một cách đơn giản hơn

LocalDateTime.now(Clock.systemUTC())

21
Tốt, nhưng không trả lời câu hỏi ban đầu.
eirirlar

2
Câu trả lời này chuyển đổi ngày UTC thành LocalDate. Câu hỏi ban đầu là làm cách nào để chuyển đổi LocalDate thành UTC Date.
Cypress Frankenfeld,

57

LocalDateTime không chứa thông tin Vùng. ZonedDatetime không.

Nếu bạn muốn chuyển LocalDateTime sang UTC, bạn cần phải bọc bởi nắm đấm ZonedDateTime.

Bạn có thể chuyển đổi như bên dưới.

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
Điều này là chính xác, mặc dù không được bọc kỹ thuật. ldt.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC"))trong khi ngắn gọn vẫn truyền tải đủ ý nghĩa để không cần đến biến cá thể được khoanh vùng.
Brett Ryan,

19
ZoneOffset.UTClà một sự thay thế tốt đẹp choZoneI‌​d.of("UTC")
ycomp

2
Đối với UTC, OffsetDateTimethích hợp hơn ZonedDateTime. Sử dụng: OffsetDateTime.now( ZoneOffset.UTC )hoặcmyInstant.atOffset( ZoneOffset.UTC )
Basil Bourque

15

Sử dụng bên dưới. Nó lấy ngày giờ địa phương và chuyển đổi nó thành UTC bằng cách sử dụng múi giờ. Bạn không cần tạo chức năng của nó.

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

Nếu bạn cần lấy phần LocalDateTime của ZonedDateTime thì bạn có thể sử dụng phần sau.

nowUTC.toLocalDateTime();

Đây là một phương pháp tĩnh mà tôi sử dụng trong ứng dụng của mình để chèn thời gian UTC trong mysql vì tôi không thể thêm giá trị mặc định UTC_TIMESTAMP vào cột ngày giờ.

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

    return nowUTC.toLocalDateTime();
}

14

Đây là một lớp tiện ích nhỏ đơn giản mà bạn có thể sử dụng để chuyển đổi ngày giờ cục bộ từ vùng này sang vùng khác, bao gồm một phương thức tiện ích trực tiếp để chuyển đổi ngày giờ cục bộ từ vùng hiện tại sang UTC (với phương thức chính để bạn có thể chạy nó và xem kết quả của một bài kiểm tra đơn giản):

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());
    }
}

Cũng thêm: final LocalDateTime backToLocal = DateTimeUtil.toZone (utc, ZoneOffset.UTC, ZoneId.systemDefault ()); System.out.println ("Quay lại Cục bộ:" + backToLocal);
rjdkolb 21/1218

7

Câu hỏi?

Nhìn vào câu trả lời và câu hỏi, có vẻ như câu hỏi đã được sửa đổi đáng kể. Vì vậy, để trả lời câu hỏi hiện tại:

Chuyển đổi LocalDateTime thành LocalDateTime trong UTC.

Múi giờ?

LocalDateTimekhông lưu trữ bất kỳ thông tin nào về múi giờ, về cơ bản nó chỉ giữ các giá trị của năm, tháng, ngày, giờ, phút, giây và các đơn vị nhỏ hơn. Vì vậy, một câu hỏi quan trọng là: Múi giờ của bản gốc là LocalDateTimegì? Nó cũng có thể là UTC rồi, do đó không cần phải chuyển đổi.

Múi giờ mặc định của hệ thống

Cân nhắc rằng bạn đã đặt câu hỏi dù sao, có thể bạn muốn nói rằng giờ gốc nằm trong múi giờ mặc định của hệ thống và bạn muốn chuyển đổi nó thành UTC. Bởi vì thường một LocalDateTimeđối tượng được tạo bằng cách sử dụng LocalDateTime.now()nó trả về thời gian hiện tại trong múi giờ mặc định của hệ thống. Trong trường hợp này, chuyển đổi sẽ như sau:

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

Một ví dụ về quá trình chuyển đổi:

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

Múi giờ rõ ràng

Trong bất kỳ trường hợp nào khác, khi bạn chỉ định rõ ràng múi giờ của thời gian để chuyển đổi, chuyển đổi sẽ như sau:

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

Một ví dụ về quá trình chuyển đổi:

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

các atZone()Phương pháp

Kết quả của atZone()phương pháp phụ thuộc vào thời gian đã qua làm đối số của nó, vì nó xem xét tất cả các quy tắc của múi giờ, bao gồm Giờ tiết kiệm ánh sáng ban ngày (DST). Trong các ví dụ, thời gian là ngày 25 tháng 2, ở Châu Âu, điều này có nghĩa là giờ mùa đông (không có DST).

Nếu chúng tôi sử dụng một ngày khác, giả sử ngày 25 tháng 8 so với năm ngoái, kết quả sẽ khác, xem xét DST:

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

Giờ GMT không thay đổi. Do đó, hiệu số trong các múi giờ khác được điều chỉnh. Trong ví dụ này, giờ mùa hè của Estonia là GMT + 3 và giờ mùa đông là GMT + 2.

Ngoài ra, nếu bạn chỉ định thời gian trong quá trình chuyển đổi đồng hồ lùi lại một giờ. Ví dụ: ngày 28 tháng 10 năm 2018 03:30 đối với Estonia, điều này có nghĩa là hai thời điểm khác nhau:

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]

Nếu không chỉ định chênh lệch theo cách thủ công (GMT + 2 hoặc GMT + 3), thời gian 03:30cho múi giờ Europe/Tallinncó thể có nghĩa là hai thời gian UTC khác nhau và hai hiệu số khác nhau.

Tóm lược

Như bạn có thể thấy, kết quả cuối cùng phụ thuộc vào múi giờ của thời gian đã qua làm đối số. Vì không thể trích xuất múi giờ từ LocalDateTimeđối tượng, bạn phải tự biết múi giờ đó đến từ múi giờ nào để chuyển đổi nó sang UTC.


1
cảm ơn vì thông tin về LocalDateTime không lưu trữ bất kỳ thông tin nào về múi giờ! 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: đơn giản là không có cách nào để làm điều đó; nếu bạn đang cố gắng làm điều đó, bạn nhận được LocalDateTime sai.

Lý do là LocalDateTime không ghi lại Múi giờ sau khi các phiên bản được tạo. Bạn không thể chuyển đổi một ngày giờ không có múi giờ thành một ngày giờ khác dựa trên một múi giờ cụ thể.

Trên thực tế, LocalDateTime.now () không bao giờ được gọi trong mã sản xuất trừ khi mục đích của bạn là nhận được kết quả ngẫu nhiên. Khi bạn tạo một phiên bản LocalDateTime như vậy, phiên bản này CHỈ chứa ngày giờ dựa trên múi giờ của máy chủ hiện tại, có nghĩa là đoạn mã này sẽ tạo ra kết quả khác nếu nó đang chạy một máy chủ có cấu hình múi giờ khác.

LocalDateTime có thể đơn giản hóa việc tính toán ngày tháng. Nếu bạn muốn có thời gian dữ liệu thực sự có thể sử dụng được trên toàn cầu, hãy sử dụng ZonedDateTime hoặc OffsetDateTime: https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html .


LocalDateTime không ghi lại Múi giờ, nhưng bạn có thể có kiến ​​thức này từ nơi khác và thêm thông tin này vào LocalDateTimes của bạn trước khi chuyển đổi.
Tristan

-1

bạn có thể triển khai một người trợ giúp làm những việc như vậy:

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 từ UTC đến UTC Z? không có nghĩa gì cả. 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
Xin đừng dạy những đứa trẻ sử dụng SimpleDateFormatlớp học đã lỗi thời và khét tiếng phiền phức . Ít nhất không phải là tùy chọn đầu tiên. Và không phải không có bất kỳ đặt trước. Hôm nay chúng ta có rất nhiều thứ tốt hơn java.time, API ngày giờ hiện đại của Java và nó DateTimeFormatter.
Ole VV
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.