2014-05-11 33 views
18

Gần đây tôi đã chuyển sang Java 8, hy vọng, đối phó với thời gian địa phương và khoanh vùng dễ dàng hơn.Không thể lấy ZonedDateTime từ TemporalAccessor bằng cách sử dụng DateTimeFormatter và ZonedDateTime trong Java 8

Tuy nhiên, tôi đang đối mặt với một ý kiến ​​đơn giản khi phân tích một ngày đơn giản.

public static ZonedDateTime convertirAFecha(String fecha) throws Exception { 
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
      ConstantesFechas.FORMATO_DIA).withZone(
      obtenerZonaHorariaServidor()); 

    ZonedDateTime resultado = ZonedDateTime.parse(fecha, formatter); 
    return resultado; 
} 

Trong trường hợp của tôi:

  • fecha là '15/06/2014'
  • ConstantesFechas.FORMATO_DIA là 'dd/MM/yyyy'
  • obtenerZonaHorariaServidor trả ZoneId.systemDefault()

Vì vậy, đây là một ví dụ đơn giản. Tuy nhiên, phân tích cú pháp này ném ngoại lệ này:

java.time.format.DateTimeParseException: Text '15/06/2014' could not be parsed: Unable to obtain ZonedDateTime from TemporalAccessor: {},ISO resolved to 2014-06-15 of type java.time.format.Parsed 

Bất kỳ mẹo nào? Tôi đã cố gắng kết hợp khác nhau của phân tích cú pháp và sử dụng TemporalAccesor, nhưng không có bất kỳ may mắn cho đến nay.

Trân trọng

Trả lời

19

Tôi không chắc chắn tại sao nó không hoạt động (có thể do đầu vào của bạn không có thông tin múi giờ/thời gian). Một cách đơn giản là để phân tích ngày của bạn như một LocalDate đầu tiên (không có thời gian hay thông tin múi giờ) sau đó tạo ra một ZonedDateTime:

public static ZonedDateTime convertirAFecha(String fecha) { 
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); 
    LocalDate date = LocalDate.parse(fecha, formatter); 

    ZonedDateTime resultado = date.atStartOfDay(ZoneId.systemDefault()); 
    return resultado; 
} 
9

Đây là một lỗi, xin xem JDK-bug-log. Theo thông tin đó, vấn đề đã được giải quyết cho Java 9 và Java 8u20. Hãy thử tải xuống phiên bản Java 8 mới nhất. Hôm nay vào ngày 2014-05-12: Có sẵn early access release 8u20.

UPDATE:

Cá nhân tôi nghĩ, vì bạn chỉ có và mong muốn "dd/MM/yyyy" như mẫu bạn nên sử dụng LocalDate as type chính của bạn như @assylias đã được đề xuất. Về bối cảnh của bạn, nó gần như chắc chắn một thiết kế thất bại để sử dụng ZonedDateTime. Bạn muốn làm gì với các đối tượng thuộc loại này? Tôi chỉ có thể nghĩ về các tính toán múi giờ chuyên biệt như trường hợp sử dụng. Và bạn thậm chí không thể lưu trữ trực tiếp những ZonedDateTime -objects này trong một cơ sở dữ liệu, vì vậy loại này ít hữu ích hơn nhiều người tin.

Điều tôi mô tả là sự cố sử dụng của bạn thực sự là một khía cạnh mới được giới thiệu với Java-8 so với lớp cũ GregorianCalendar (là loại tất cả trong một). Người dùng phải bắt đầu suy nghĩ về việc chọn loại thời gian thích hợp cho các vấn đề và trường hợp sử dụng của họ.

+1

đẹp catch - mặc dù tôi tin rằng op vẫn sẽ cần phải cung cấp một thời gian để có thể phân tích cú pháp đầu vào thành ZonedDateTime. – assylias

+1

@assylias Yep, OP nên mở rộng mẫu ít nhất cũng cho phần thời gian hoặc chọn đề xuất của bạn. Điều này cũng có thể phụ thuộc vào cấu hình phân tích cú pháp khoan dung, vv Thực ra không thể kiểm tra các chi tiết này với Java-8 ở vị trí hiện tại của tôi. –

+3

Liên kết báo cáo lỗi tốt hơn là https://bugs.openjdk.java.net/browse/JDK-8033662 – JodaStephen

2

Nói cách đơn giản, dòng

ZonedDateTime.parse('2014-04-23', DateTimeFormatter.ISO_OFFSET_DATE_TIME) 

ném một ngoại lệ:

Text '2014-04-23' could not be parsed at index 10 
java.time.format.DateTimeParseException: Text '2014-04-23' could not be parsed at index 10 

Nó trông giống như một lỗi cho tôi.

tôi đã sử dụng workaround này:

String dateAsStr = '2014-04-23'; 
if (dateAsStr.length() == 10) { 
    dateAsStr += 'T00:00:00'; 
} 
ZonedDateTime.parse(dateAsStr, DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneId.systemDefault())); 
+0

Đó là một dateTIME, do đó, một chuỗi không có phần thời gian không phải là một datetime hợp lệ ... – Koshinae

0

Chỉ cần một ví dụ chuyển đổi, tôi tin rằng một số người sẽ có được ngoại lệ bên dưới

(java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: 2014-10-24T18:22:09.800Z of type java.time.Instant) 

nếu họ cố gắng

LocalDateTime localDateTime = LocalDateTime.from(new Date().toInstant()); 

để giải quyết vấn đề, vui lòng chuyển vào Khu vực -

LocalDateTime localDateTime = LocalDateTime.from(new Date() 
     .toInstant().atZone(ZoneId.of("UTC"))); 
0

Nếu đến từ Google:

Thay vì thực hiện:

ZonedDateTime.from(new Date().toInstant()); 

Hãy thử điều này:

ZonedDateTime.ofInstant(new Date(), ZoneId.of("UTC")); 
Các vấn đề liên quan