Comment convertir java.sql.timestamp en LocalDate (java8) java.time?

Réponses:

196

Tu peux faire:

timeStamp.toLocalDateTime().toLocalDate();

Notez que vous timestamp.toLocalDateTime() utiliserez le Clock.systemDefaultZone()fuseau horaire pour effectuer la conversion. Cela peut ou non être ce que vous voulez.

assylies
la source
1
Il a été ajouté dans Java 8.
assylias
54
Juste une note, la timestamp.toLocalDateTime()méthode utilisera le fuseau horaire systemDefault pour effectuer la conversion. Cela peut ou non être ce que vous voulez.
jacobhyphenated le
1
@jacobhyphenated veuillez poster la réponse en utilisant un fuseau horaire explicite. Merci!
user482745
Le commentaire de @ jacobhyphenated est extrêmement important ici, d'où le nombre de votes positifs. Voir ma réponse pour plus de détails stackoverflow.com/a/57101544/2032701
Ruslan
@jacobhyphenated, LocalDateTimeutilise toujours le fuseau horaire par défaut du système. C'est ce que signifie «Local» dans son nom.
M. Prokhorov
21

La réponse acceptée n'est pas idéale, j'ai donc décidé d'ajouter mes 2 centimes

timeStamp.toLocalDateTime().toLocalDate();

est une mauvaise solution en général , je ne sais même pas pourquoi ils ont ajouté cette méthode au JDK car cela rend les choses vraiment déroutantes en effectuant une conversion implicite en utilisant le fuseau horaire du système. Habituellement, lorsque vous n'utilisez que des classes de date java8, le programmeur est obligé de spécifier un fuseau horaire, ce qui est une bonne chose.

La bonne solution est

timestamp.toInstant().atZone(zoneId).toLocalDate()

zoneId est le fuseau horaire que vous souhaitez utiliser, qui est généralement soit ZoneId.systemDefault () si vous souhaitez utiliser votre fuseau horaire système ou un fuseau horaire codé en dur comme ZoneOffset.UTC

L'approche générale devrait être

  1. Libérez-vous des nouvelles classes de date java8 en utilisant une classe qui est directement liée, par exemple dans notre cas java.time.Instant est directement liée à java.sql.Timestamp , c'est-à-dire qu'aucune conversion de fuseau horaire n'est nécessaire entre elles.
  2. Utilisez les méthodes bien conçues de cette classe java8 pour faire ce qu'il faut. Dans notre cas, atZone (zoneId) a précisé que nous effectuons une conversion et que nous utilisons un fuseau horaire particulier pour cela.
Ruslan
la source
1
Je ne suis pas d'accord. L'horodatage (ainsi que la date) n'ont aucune information de zone. LocalDate ne dispose d'aucune information de zone, les deux sont donc équivalents. La conversion entre eux peut être effectuée indépendamment de toute zone particulière. La conversion en ZonedDateTime avant la conversion en LocalDate ajoute un fuseau horaire, puis l'enlève à nouveau - vous êtes beaucoup plus susceptible d'avoir une mauvaise - difficile à trouver - erreur en le faisant de cette façon.
AutomatedMike
5
@AutomatedMike Timestamp (et aussi Date) représentent un point dans le temps en UTC. LocalDate ne représente pas un point dans le temps, mais plutôt une heure telle qu'elle apparaît sur une horloge murale. Veuillez lire leurs javadocs. "La conversion entre eux peut être effectuée indépendamment de toute zone particulière" - ce n'est pas vrai , le nouveau Timestamp (0L) .toLocalDateTime () renvoie "1970-01-01T03: 00" pour mon fuseau horaire de Moscou. Le résultat peut être différent pour votre fuseau horaire.
Ruslan
1
@AutomatedMike Même si vous dépouillez l'heure en faisant toLocalDate (), il est facile de prouver que le jour peut être erroné si Timestamp avait une heure autour de minuit, par exemple new Timestamp (1000 * 60 * 60 * 23) .toLocalDateTime (). ToLocalDate () renvoie "1970-01-02" pour mon fuseau horaire de Moscou quand il est "1970-01-01" en UTC.
Ruslan
1
@AutomatedMike "ajoute un fuseau horaire puis l'enlève à nouveau" - le point n'est pas d'ajouter et de supprimer un fuseau horaire, mais plutôt de convertir entre différentes notions en utilisant un fuseau horaire explicite . Cela contraste avec les exemples de mes deux commentaires précédents où un fuseau horaire est appliqué implicitement .
Ruslan
7

Je vais développer légèrement la réponse @assylias pour prendre en compte le fuseau horaire. Il existe au moins deux façons d'obtenir LocalDateTime pour un fuseau horaire spécifique.

Vous pouvez utiliser le fuseau horaire setDefault pour toute l'application. Il doit être appelé avant toute conversion d'horodatage -> java.time:

public static void main(String... args) {
    TimeZone utcTimeZone = TimeZone.getTimeZone("UTC");
    TimeZone.setDefault(utcTimeZone);
    ...
    timestamp.toLocalDateTime().toLocalDate();
}

Ou vous pouvez utiliser la chaîne toInstant.atZone:

timestamp.toInstant()
        .atZone(ZoneId.of("UTC"))
        .toLocalDate();
Pavel
la source