web-dev-qa-db-fra.com

Conversion de Java8 Java.util.Date en Java.time.ZonedDateTime

Je reçois l'exception suivante en essayant de convertir Java.util.Date à Java.time.LocalDate.

Java.time.DateTimeException: Unable to obtain ZonedDateTime from TemporalAccessor: 2014-08-19T05:28:16.768Z of type Java.time.Instant

Le code est le suivant:

public static Date getNearestQuarterStartDate(Date calculateFromDate){

    int[] quaterStartMonths={1,4,7,10};     
    Date startDate=null;

    ZonedDateTime d=ZonedDateTime.from(calculateFromDate.toInstant());
    int frmDateMonth=d.getMonth().getValue();

Quelque chose ne va pas dans la façon dont j'utilise la classe ZonedDateTime?

Selon la documentation, ceci devrait convertir un Java.util.Date objet à ZonedDateTime. Le format de date ci-dessus est standard Date?

Dois-je avoir recours au temps de Joda?

Si quelqu'un pouvait faire une suggestion, ce serait génial.

58
Ironluca

Pour transformer un Instant en un ZonedDateTime, ZonedDateTime offre la méthode ZonedDateTime.ofInstant(Instant, ZoneId) . Alors

Donc, en supposant que vous souhaitiez un ZonedDateTime dans le fuseau horaire par défaut, votre code devrait être

ZonedDateTime d = ZonedDateTime.ofInstant(calculateFromDate.toInstant(),
                                          ZoneId.systemDefault());
84
JB Nizet

Pour obtenir un ZonedDateTime à partir d’une date, vous pouvez utiliser:

calculateFromDate.toInstant().atZone(ZoneId.systemDefault())

Vous pouvez ensuite appeler la méthode toLocalDate si vous avez besoin d'un LocalDate. Voir aussi: Convertir Java.util.Date en Java.time.LocalDate

32
assylias

Le Answer by assylias et le Answer by JB Nizet sont corrects:

  1. Appelez la nouvelle méthode de conversion ajoutée à la classe existante, Java.util.Date::toInstant .
  2. Appel Instant::atZone , en passant un ZoneId , résultant en un ZonedDateTime .

enter image description here

Mais votre exemple de code vise les quartiers. Pour cela, lisez la suite.

Trimestres

Pas besoin de rouler vous-même la gestion des quartiers. Utilisez une classe déjà écrite et testée.

org.threeten.extra.YearQuarter

Les classes Java.time sont étendues par le projet ThreeTen-Extra . Parmi les nombreuses classes pratiques fournies dans cette bibliothèque, vous trouverez Quarter et YearQuarter .

Commencez par obtenir votre ZonedDateTime .

ZonedId z = ZoneID.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = myJavaUtilDate.toInstant().atZone( z ) ;

Déterminez le trimestre de l'année pour cette date.

YearQuarter yq = YearQuarter.from( zdt ) ;

Ensuite, nous avons besoin de la date de début de ce trimestre.

LocalDate quarterStart = yq.atDay( 1 ) ;

Bien que je ne le recommande pas nécessairement, vous pouvez utiliser une seule ligne de code plutôt que d'implémenter une méthode.

LocalDate quarterStart =                    // Represent a date-only, without time-of-day and without time zone.
    YearQuarter                             // Represent a specific quarter using the ThreeTen-Extra class `org.threeten.extra.YearQuarter`. 
    .from(                                  // Given a moment, determine its year-quarter.
        myJavaUtilDate                      // Terrible legacy class `Java.util.Date` represents a moment in UTC as a count of milliseconds since the Epoch of 1970-01-01T00:00:00Z. Avoid using this class if at all possible.
        .toInstant()                        // New method on old class to convert from legacy to modern. `Instant` represents a moment in UTC as a count of nanoseconds since the Epoch of 1970-01-01T00:00:00Z. 
        .atZone(                            // Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone). Same moment, same point on the timeline, different wall-clock time.
            ZoneID.of( "Africa/Tunis" )     // Specify a time zone using proper `Continent/Region` format. Never use 2-4 letter pseudo-zone such as `PST` or `EST` or `IST`. 
        )                                   // Returns a `ZonedDateTime` object.
    )                                       // Returns a `YearQuarter` object.
    .atDay( 1 )                             // Returns a `LocalDate` object, the first day of the quarter. 
;

À propos, si vous pouvez éliminer votre utilisation de Java.util.Date tout à fait, faites-le. C'est une classe terrible , avec ses frères et soeurs tels que Calendar. Utilisez Date uniquement où vous devez, lorsque vous vous connectez avec un ancien code non encore mis à jour vers Java.time .


À propos de Java.time

Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent l'ancien problème - legacy classes date-heure telles que Java.util.Date , Calendar , & SimpleDateFormat .

Pour en savoir plus, consultez le Oracle Tutorial . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 31 .

Le projet Joda-Time , maintenant en mode de maintenance , conseille de migrer vers le Java.time = cours.

Vous pouvez échanger des objets Java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou une version ultérieure. Pas besoin de chaînes, pas besoin de Java.sql.* Des classes.

Où obtenir les classes Java.time?

Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d’essai pour d’éventuels ajouts à Java.time. Vous pouvez trouver ici quelques classes utiles telles que Interval , YearWeek , YearQuarter , et plus .

2
Basil Bourque

La réponse n'a pas fonctionné pour moi sur Java 10 stockant util.Date en UTC.

Date.toInstant () semble convertir EpochMillis dans le fuseau horaire local du serveur.

ZDT.ofInstant (instant, zoneId) et instant.atZone (zoneId) semblent juste taguer sur un TZ à l'instant, mais c'est déjà foiré.

Je ne pouvais pas trouver un moyen d'empêcher Date.toInstant () de modifier l'heure UTC avec le fuseau horaire du système.

La seule façon pour moi de contourner ce problème était de passer par la classe sql.Timestamp:

new Java.sql.Timestamp(date.getTime()).toLocalDateTime()
                                      .atZone(ZoneId.of("UTC"))
                                      .withZoneSameInstant(desiredTZ)
0
TheArchitect