2016-08-08 1 views
4

Pourquoi est-il possible de passer un objet LocalDateTime dans la méthode ZonedDateTime.from() s'il n'est pas possible d'analyser un datetime simple, comme suit?Comment convertir LocalDateTime à GregorianCalendar?

@Test 
public void test() throws Exception { 
    GregorianCalendar.from(ZonedDateTime.from(LocalDateTime.parse("2016-08-31T23:00:59"))); 
} 

Résultat:

java.time.DateTimeException: Unable to obtain ZonedDateTime from TemporalAccessor: 2016-08-31T23:00:59 of type java.time.LocalDateTime 
    at java.time.ZonedDateTime.from(ZonedDateTime.java:565) 
+1

Demandez-vous comment convertir un 'GregorianCalendar', ou demandez-vous pourquoi il vous permet de passer un implémentation de l'interface 'TemporalAccessor' et ne s'en plaint qu'en runtime? – RealSkeptic

+2

GeorgianCalendar nécessite un fuseau horaire donc en fait vous pouvez faire 'GregorianCalendar.from (ZonedDateTime.parse (" 2016-08-31T23: 00: 59 + 00: 00 "));' fournissant un fuseau horaire. 'ZonedDateTime.from' peut échouer pour différents types d'entrée et ceux mentionnés dans javadoc. – vsminkov

+1

Le diagramme montrant les conversions des anciennes classes date-heure en java.time dans [my Answer] (http://stackoverflow.com/a/36639155) en [Convertir java.util.Date en quel type "java.time" ?] (http://stackoverflow.com/q/36639154) peut être utile. Trouvez également un exemple de conversion de code dans les deux sens. –

Répondre

4

Vous devrez fournir IDZone aussi bien, je vais devoir rechercher sur le comportement pour expliquer pourquoi cela est, je vais éditer et poster dès que je vois il

LocalDateTime ldt = LocalDateTime.parse("2016-08-31T23:00:59"); 
GregorianCalendar gc = GregorianCalendar.from(ZonedDateTime.of(ldt, ZoneId.systemDefault())); 
System.out.println(gc); 

il en résulte:

java.util.GregorianCalendar [temps = 1472664659000, areFieldsSet = tru e, areAllFieldsSet = true, indentation = true, zone = sun.util.calendar.ZoneInfo [id = "Asie/Calcutta", décalage = 19800000, dstSavings = 0, useDaylight = false, transitions = 6, lastRule = null], firstDayOfWeek = 2, minimalDaysInFirstWeek = 4, ERA = 1, YEAR = 2016, MOIS = 7, WEEK_OF_YEAR = 35, WEEK_OF_MONTH = 5, DAY_OF_MONTH = 31, DAY_OF_YEAR = 244, DAY_OF_WEEK = 4, DAY_OF_WEEK_IN_MONTH = 5, AM_PM = 1, HOUR = 11 , HOUR_OF_DAY = 23, MINUTE = 0, SECOND = 59, MILLISECOND = 0, ZONE_OFFSET = 19800000, DST_OFFSET = 0]

Edits Tout est tombé sur ce fil (Unable to obtain ZonedDateTime from TemporalAccessor when parsing a Date)

Java 8 java.time. * package est un paquet très strict. Il ne permet pas la flexibilité entre les types et les entrées - si vous voulez un objet ZonedDateTime, vous devez le construire à partir d'une entrée qui a un fuseau horaire, une date & une fois.

5

Pourquoi est-il possible de passer un objet LocalDateTime dans la méthode ZonedDateTime.from() s'il est impossible d'analyser simple datetime ?

Les deux LocalDateTime et ZonedDateTime implémente l'interface appelée Temporal, qui étend TemporalAccessor.

LocalDateTime est date-heure sans fuseau horaire dans le système de calendrier ISO-8601, comme 2007-12-03T10: 15: 30

ZonedDateTime est date-heure avec un fuseau horaire dans la norme ISO -8601 système de calendrier, tel que 2007-12-03T10: 15: 30 + 01: 00 Europe/Paris.

Maintenant, si vous voyez l'implémentation de la méthode from(TemporalAccessor temporal) qui attend le TemporalAccessor. Tant ZonedDateTime que LocalDateTime implémente la méthode de la super interface TemporalAccessor (Temporal extends TemporalAccessor), il est normal (comportement polymorphique) de nous permettre de passer à la fois la date locale et la date zonée.

code:

public static ZonedDateTime from(TemporalAccessor temporal) { 
      if (temporal instanceof ZonedDateTime) { 
       return (ZonedDateTime) temporal; 
      } 
      try { 
       ZoneId zone = ZoneId.from(temporal); 
       if (temporal.isSupported(INSTANT_SECONDS)) { 
        long epochSecond = temporal.getLong(INSTANT_SECONDS); 
        int nanoOfSecond = temporal.get(NANO_OF_SECOND); 
        return create(epochSecond, nanoOfSecond, zone); 
       } else { 
        LocalDate date = LocalDate.from(temporal); 
        LocalTime time = LocalTime.from(temporal); 
        return of(date, time, zone); 
       } 
      } catch (DateTimeException ex) { 
       throw new DateTimeException("Unable to obtain ZonedDateTime from TemporalAccessor: " + 
         temporal + " of type " + temporal.getClass().getName(), ex); 
      } 
     } 

Nous arrivons maintenant à votre problème. Vous transmettez LocalDateTime.parse("2016-08-31T23:00:59") à la méthode from(TemporalAccessor temporal).Donc le temporel n'est pas une instance de ZonedDateTime, il vient ZoneId zone = ZoneId.from(temporal);

Ainsi, vous obtenez l'erreur car LocalDateTime ne contient pas le fuseau horaire .

Comment résoudre ce problème?

Utilisez la zone Id avec le ZonedDateTime

LocalDateTime ldt = LocalDateTime.parse("2016-08-31T23:00:59"); 
ZoneId zoneId = ZoneId.of("Europe/Paris"); 
ZonedDateTime zdt = ldt.atZone(zoneId); 
GregorianCalendar gc = GregorianCalendar.from(zdt); 

Avec test JUnit

@Test 
public void test() throws Exception { 
    ZoneId zoneId = ZoneId.of("Europe/Paris"); 
    GregorianCalendar.from(LocalDateTime.parse("2016-08-31T23:00:59").atZone(zoneId)); 
}