2015-03-05 21 views
7

Tôi có nguồn dữ liệu với các đối tượng DateTime được lưu trữ trong thời gian joda. Tôi cần phải chuyển đổi chúng thành các đối tượng java ZonedDateTime, giữ nguyên múi giờ ban đầu.Cách chuyển đổi từ org.joda.time.DateTime sang java.time.ZonedDateTime

Không đủ để giữ khoảng trống vì một số đối tượng DateTime đại diện cho các tác vụ lặp lại hàng ngày và các tác vụ này phải xảy ra tại một thời điểm cụ thể trong một múi giờ cụ thể cho mỗi ngày. Do đó, chúng phải tuân theo các chuyển đổi TimeZone được chỉ định ví dụ như mùa hè và mùa đông. Tôi không thể cho biết cách sử dụng cuối cùng của các đối tượng DateTime, vì vậy tôi cần giữ thông tin Múi giờ trên tất cả các đối tượng để an toàn.

Cách chuyển đổi từ org.joda.time.DateTime thành java.time.ZonedDateTime?

Will tất cả

ord.joda.time.DateTimeZone.getId()

bản đồ để id của sẵn trong

java.time.ZoneId

Trả lời

15

Không phải tất cả múi giờ chuỗi từ Joda-Thời gian sẽ phù hợp với java.time nhưng phần lớn sẽ vì chúng đều dựa trên dữ liệu IZ tz. So sánh DateTimeZone.getAvailableIDs() đến ZoneId.getAvailableZoneIds() để xác định sự không phù hợp. Số nhận dạng bổ sung có thể được ánh xạ bằng cách sử dụng ZoneId.of(String, Map).

Để làm được việc chuyển đổi chính trong cách hiệu quả nhất, bạn phải vượt qua trong từng lĩnh vực:

ZonedDateTime zdt = ZonedDateTime.ofLocal(
    LocalDateTime.of(
     dt.getYear(), 
     dt.getMonthOfYear(), 
     dt.getDayOfMonth(), 
     dt.getHourOfDay(), 
     dt.getMinuteOfHour(), 
     dt.getSecondOfMinute(), 
     dt.getMillisOfSecond() * 1_000_000), 
    ZoneId.of(dt.getZone().getID(), ZoneId.SHORT_IDS), 
    ZoneOffset.ofTotalSeconds(dt.getZone().getOffset(dt)/1000)); 

Lưu ý việc sử dụng ZoneId.SHORT_IDS như Map trong trường hợp này.

Đối với một giải pháp đơn giản để xử lý hầu hết các trường hợp sử dụng, nhưng ít hiệu suất thấp hơn, sử dụng này:

ZonedDateTime zdt = dt.toGregorianCalendar().toZonedDateTime(); 
+0

Có một tập hợp con cụ thể không có tập hợp con này hay không? Có lẽ một số vùng tương thích POSIX cũ hơn? Tôi hy vọng tất cả các khu vực kiểu "Khu vực/Địa phương" hiện đại sẽ có sẵn ở cả hai. –

+2

Sự khác biệt duy nhất là ROC, được thay thế bằng ROK. Các vùng EST, HST và MST có thể được truy cập bằng cách sử dụng 'ZoneId.SHORT_IDS'. Nếu không, bất kỳ sự khác biệt nào chỉ là từ phiên bản sau của cơ sở dữ liệu múi giờ trong Joda-Time. – JodaStephen

+1

@JodaStephen Thay cho 'ZoneId.of (dt.getZone().getID(), ZoneId.SHORT_IDS)) 'will' dt.toTimeZone(). toZoneId() 'có hoạt động không? nó dường như để lại gritty nitty để JodaTime và Java tương ứng. – NomeN

3

Bạn nên tránh cung cấp cho mỗi lĩnh vực riêng biệt nếu bạn đang làm việc với các chuyển động tiết kiệm ánh sáng ban ngày. Chuyển đổi bằng cách sử dụng epochMillis thay vào đó, như trong ví dụ sau.

Instant instant = Instant.ofEpochMilli(dt.getMillis()); 
ZoneId zoneId = ZoneId.of(dt.getZone().getId(), ZoneId.SHORT_IDS); 
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, zoneId); 

Nếu không, bạn sẽ mất một giờ vào ngày chuyển đổi. Ví dụ: Đức đã chuyển từ thời gian mùa hè (GMT + 2) sang giờ mùa đông (GMT + 1) vào ngày 29.10.2017 lúc 03:00 GMT + 2, trở thành 02:00 GMT + 1. Vào ngày đó, bạn có 2 phiên bản của 02:00 - phiên bản cũ hơn với GMT + 2 và phiên bản mới hơn với GMT + 1.

Vì bạn đang làm việc với ZoneIds chứ không phải với bù đắp, không có cách nào biết được một trong 2 trường hợp bạn muốn. Theo mặc định, giá trị đầu tiên được giả định trong quá trình chuyển đổi. Cả 02:00 GMT + 2 và 02:00 GMT + 1 sẽ được chuyển đổi thành 02:00 GMT + 2 nếu bạn cung cấp hourOfDay cùng với ZoneId.

Các vấn đề liên quan