2014-05-11 33 views
18

Niedawno przeniosłem się na Java 8, aby, mam nadzieję, łatwiej było radzić sobie z lokalnymi i strefowymi czasami.Nie można uzyskać ZonedDateTime z TemporalAccessor za pomocą DateTimeFormatter i ZonedDateTime w Javie 8

Mam jednak do czynienia, moim zdaniem, z prostym problemem podczas analizowania prostej daty.

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

W moim przypadku:

  • Fecha jest '15/06/2014'
  • ConstantesFechas.FORMATO_DIA jest 'dd/mm/rrrr'
  • obtenerZonaHorariaServidor zwraca ZoneId.systemDefault()

To jest prosty przykład. Jednak w tej analizie wyjątek jest następujący:

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 

Jakieś wskazówki? Próbowałem różnych kombinacji parsowania i używania TemporalAccesor, ale bez żadnego szczęścia do tej pory.

poważaniem

Odpowiedz

19

Nie jestem pewien, dlaczego to nie działa (prawdopodobnie dlatego, że wejście nie ma strefy czasowej/czasu). Prostym sposobem jest do analizowania datę jako LocalDate pierwszy (bez czasu i strefy czasowej), a następnie utworzyć 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

Jest to błąd, patrz JDK-bug-log. Według tych informacji problem został rozwiązany dla Javy 9 i Javy 8u20. Spróbuj pobrać najnowszą wersję Java 8. Dzisiaj w dniu 2014-05-12: Dostępny jest numer early access release 8u20.

UPDATE:

Osobiście myślę, skoro masz tylko i oczekiwać „dd/mm/rrrr” jako wzór, który trzeba zastosować LocalDate jako podstawowego typu jak @assylias zaproponowała już. Jeśli chodzi o twój kontekst, prawie pewne jest, że projekt nie użyje ZonedDateTime. Co chcesz robić z obiektami tego typu? Mogę myśleć tylko o specjalistycznych obliczeniach strefy czasowej jako przypadków użycia. Nie można nawet bezpośrednio przechowywać tych obiektów w bazie danych, więc ten typ jest o wiele mniej użyteczny, niż wielu ludzi sądzi.

To, co opisałem jako twój problem z przypadkami użycia, jest rzeczywiście nowym aspektem wprowadzonym w Java-8 w porównaniu ze starą klasą GregorianCalendar (która jest typu "wszystko w jednym"). Użytkownicy muszą zacząć myśleć o wyborze właściwego typu czasowego dla swoich problemów i przypadków użycia.

+1

Niezły chwyt - choć wierzę, że PO będzie nadal trzeba zapewnić czas na być w stanie przeanalizować dane wejściowe w ZonedDateTime. – assylias

+1

@assylias Yep, OP powinien rozszerzyć wzór przynajmniej na część czasu lub wybrać sugestię. Może to być również zależne od łagodnej konfiguracji parsowania itp. Nie jestem w stanie przetestować tych szczegółów za pomocą Java-8 w moim bieżącym miejscu. –

+3

Lepsze łącze do raportu o błędach to https://bugs.openjdk.java.net/browse/JDK-8033662 – JodaStephen

2

W prostych słowach, linia

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

zgłasza wyjątek:

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 

wygląda jak dla mnie błąd.

użyłem tego rozwiązania:

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

To jest dataTIME, więc ciąg bez części czasu nie jest prawidłową datą ... – Koshinae

0

tylko przykład konwersje, wierzę, niektórzy ludzie będą mieli wyjątek poniżej

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

jeśli starają

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

rozstrzygnąć wystaw, proszę przekazać w Strefie -

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

Jadąc od Google:

Zamiast robić:

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

Spróbuj tego:

ZonedDateTime.ofInstant(new Date(), ZoneId.of("UTC"));