Convertir LocalDate en LocalDateTime ou java.sql.Timestamp


126

J'utilise JodaTime 1.6.2.

J'ai un LocalDateque je dois convertir en un (Joda) LocalDateTime, ou un java.sqlTimestamppour ormapping.

La raison en est que j'ai compris comment convertir entre a LocalDateTimeet a java.sql.Timestamp:

LocalDateTime ldt = new LocalDateTime();
DateTimeFormatter dtf = DateTimeFormatter.forPattern("yyyy-MM-dd HH:mm:ss");
Timestamp ts = Timestamp.valueOf(ldt.toString(dtf));

Donc, si je peux simplement convertir entre LocalDateet LocalDateTime, alors je peux continuer la conversion en java.sql.Timestamp. Merci pour tout coup de pouce dans la bonne direction!


Pour info, le projet Joda-Time est maintenant en mode maintenance , l'équipe conseillant la migration vers les classes java.time . Voir le didacticiel d'Oracle . De plus, la java.sql.Timestampclasse est désormais héritée, supplantée par les classes java.time , en particulier par Instant.
Basil Bourque

Réponses:


269

JodaTime

Pour convertir JodaTime org.joda.time.LocalDateen java.sql.Timestamp, faites simplement

Timestamp timestamp = new Timestamp(localDate.toDateTimeAtStartOfDay().getMillis());

Pour convertir JodaTime org.joda.time.LocalDateTimeen java.sql.Timestamp, faites simplement

Timestamp timestamp = new Timestamp(localDateTime.toDateTime().getMillis());

JavaTime

Pour convertir Java8 java.time.LocalDateen java.sql.Timestamp, faites simplement

Timestamp timestamp = Timestamp.valueOf(localDate.atStartOfDay());

Pour convertir Java8 java.time.LocalDateTimeen java.sql.Timestamp, faites simplement

Timestamp timestamp = Timestamp.valueOf(localDateTime);

Faites attention lors de la conversion LocalDateTimeen DateTimecar tous les LocalDateTimes ne sont pas valides DateTime. Source: joda-time.sourceforge.net/faq.html#illegalinstant et je suis juste en train de rencontrer ça.
Christophe De Troyer

obtenu une erreur de compilation sur l'argument car valueOf () accepte une chaîne.
Patriotic le

@Patriotic: Cela ne se produira que si vous n'utilisez pas Java SE 1.8 ou plus récent. Comme indiqué dans la réponse et dans les liens fournis vers le Javadoc (les textes bleus dans la réponse ci-dessus sont en fait des liens, vous pouvez cliquer dessus pour explorer le Javadoc), la Timestamp#valueOf()méthode accepte depuis Java SE 1.8 également un LocalDateTime.
BalusC

60

La meilleure façon d'utiliser l'API de temps Java 8:

  LocalDateTime ldt = timeStamp.toLocalDateTime();
  Timestamp ts = Timestamp.valueOf(ldt);

Pour une utilisation avec JPA mis en place avec votre modèle ( https://weblogs.java.net/blog/montanajava/archive/2014/06/17/using-java-8-datetime-classes-jpa ):

@Converter(autoApply = true)
public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime, Timestamp> {
    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime ldt) {
        return Timestamp.valueOf(ldt);
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp ts) {
        return ts.toLocalDateTime();
    }
}

Alors maintenant, c'est l'heure relative indépendante du fuseau horaire. De plus, il est facile de faire:

  LocalDate ld = ldt.toLocalDate();
  LocalTime lt = ldt.toLocalTime();

Mise en page:

 DateTimeFormatter DATE_TME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
 String str = ldt.format(DATE_TME_FORMATTER);
 ldt = LocalDateTime.parse(str, DATE_TME_FORMATTER);

MISE À JOUR: postgres 9.4.1208, HSQLDB 2.4.0 etc comprennent Java 8 Time API sans aucune conversation!


17

tl; dr

Le projet Joda-Time est en mode maintenance, désormais supplanté par les classes java.time .

  • Utilisez simplement lajava.time.Instant classe.
  • Pas besoin d:
    • LocalDateTime
    • java.sql.Timestamp
    • Cordes

Capturez le moment actuel en UTC.

Instant.now()  

Pour stocker ce moment dans la base de données:

myPreparedStatement.setObject(  , Instant.now() )  // Writes an `Instant` to database.

Pour récupérer ce moment de la base de données:

myResultSet.getObject(  , Instant.class )  // Instantiates a `Instant`

Pour ajuster l'heure de l'horloge murale à celle d'un fuseau horaire particulier.

instant.atZone( z )  // Instantiates a `ZonedDateTime`

LocalDateTime est la mauvaise classe

D'autres réponses sont correctes, mais elles ne précisent pas que ce LocalDateTimen'est pas la bonne classe pour votre objectif.

Dans java.time et Joda-Time , il LocalDateTimemanque volontairement tout concept de fuseau horaire ou de décalage par rapport à UTC. En tant que tel, il ne représente pas un moment et n'est pas un point sur la chronologie. A LocalDateTimereprésente une idée approximative des moments potentiels sur une plage d'environ 26 à 27 heures.

Utilisez a LocalDateTimepour lorsque la zone / décalage est inconnu (ce n'est pas une bonne situation), ou lorsque le décalage de zone est indéterminé. Par exemple, «Noël commence au premier moment du 25 décembre 2018» serait représenté par un LocalDateTime.

Utilisez a ZonedDateTimepour représenter un moment dans un fuseau horaire particulier. Par exemple, Noël commençant dans une zone particulière telle que Pacific/Aucklandou America/Montrealserait représenté avec un ZonedDateTimeobjet.

Pour un moment toujours en UTC, utilisez Instant.

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

Appliquer un fuseau horaire. Même moment, même point sur la chronologie, mais vu avec une heure d'horloge murale différente.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, different wall-clock time.

Donc, si je peux simplement convertir entre LocalDate et LocalDateTime,

Non, mauvaise stratégie. Si vous avez une valeur de date uniquement et que vous souhaitez une valeur de date-heure, vous devez spécifier une heure. Cette heure du jour peut ne pas être valide à cette date pour une zone particulière - auquel cas la ZonedDateTimeclasse ajuste automatiquement l'heure au besoin.

LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 23 ) ;
LocalTime lt = LocalTime.of( 14 , 0 ) ;  // 14:00 = 2 PM.
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

Si vous voulez que le premier moment de la journée soit votre heure de la journée, laissez java.time déterminer ce moment. Ne supposez pas que la journée commence à 00h00. Des anomalies telles que l'heure d'été (DST) signifient que la journée peut commencer à une autre heure telle que 01:00:00.

ZonedDateTime zdt = ld.atStartOfDay( z ) ;

java.sql.Timestamp est la mauvaise classe

Le java.sql.Timestampfait partie des anciennes classes de date-heure gênantes qui sont maintenant héritées, entièrement supplantées par les classes java.time . Cette classe était utilisée pour représenter un moment en UTC avec une résolution de nanosecondes . Cet objectif est maintenant atteint java.time.Instant.

JDBC 4.2 avec getObject/setObject

À partir de JDBC 4.2 et versions ultérieures, votre pilote JDBC peut directement échanger des objets java.time avec la base de données en appelant:

Par exemple:

myPreparedStatement.setObject(  , instant ) ;

… et …

Instant instant = myResultSet.getObject(  , Instant.class ) ;

Convertir l'héritage ⬌ moderne

Si vous devez vous connecter avec un ancien code qui n'a pas encore été mis à jour vers java.time , effectuez une conversion en arrière en utilisant de nouvelles méthodes ajoutées aux anciennes classes.

Instant instant = myJavaSqlTimestamp.toInstant() ;  // Going from legacy class to modern class.

…et…

java.sql.Timestamp myJavaSqlTimestamp = java.sql.Timestamp.from( instant ) ;  // Going from modern class to legacy class.

À propos de java.time

Le framework java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent les anciens gênants hérités des classes date-heure tels que java.util.Date, Calendar, et SimpleDateFormat.

Le projet Joda-Time , désormais en mode maintenance , conseille la migration vers les classes java.time .

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

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

Où obtenir les classes java.time?

  • Java SE 8 , Java SE 9 et versions ultérieures
    • Intégré.
    • Partie de l'API Java standard avec une implémentation groupée.
    • Java 9 ajoute quelques fonctionnalités et corrections mineures.
  • Java SE 6 et Java SE 7
    • Une grande partie de la fonctionnalité java.time est rétroportée vers Java 6 et 7 dans ThreeTen-Backport .
  • Android
    • Versions ultérieures des implémentations de bundle Android des classes java.time.
    • Pour les versions antérieures d'Android (<26), le projet ThreeTenABP adapte ThreeTen-Backport (mentionné ci-dessus). Voir Comment utiliser ThreeTenABP… .

Le projet ThreeTen-Extra étend java.time avec des classes supplémentaires. Ce projet est un terrain d'essai pour d'éventuels futurs ajouts à java.time. Vous trouverez peut - être des classes utiles ici, comme Interval, YearWeek, YearQuarteret plus .


5

En fonction de votre fuseau horaire, vous pouvez perdre quelques minutes (1650-01-01 00:00:00 devient 1649-12-31 23:52:58)

Utilisez le code suivant pour éviter cela

new Timestamp(localDateTime.getYear() - 1900, localDateTime.getMonthOfYear() - 1, localDateTime.getDayOfMonth(), localDateTime.getHourOfDay(), localDateTime.getMinuteOfHour(), localDateTime.getSecondOfMinute(), fractional);

3

Depuis Joda est se fanée, quelqu'un pourrait vouloir convertir LocaltDateà LocalDateTimeJava 8. En Java 8 , LocalDateTimeil donnera un moyen de créer une LocalDateTimeinstance à l' aide d' un LocalDateet LocalTime. Vérifiez ici.

public static LocalDateTime of (LocalDate date, LocalTime time)

L'échantillon serait,

    // just to create a sample LocalDate
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
    LocalDate ld = LocalDate.parse("20180306", dtf);

    // convert ld into a LocalDateTime
    // We need to specify the LocalTime component here as well, it can be any accepted value
    LocalDateTime ldt = LocalDateTime.of(ld, LocalTime.of(0,0)); // 2018-03-06T00:00

Juste pour référence, pour obtenir les secondes d'époque ci-dessous peuvent être utilisées,

    ZoneId zoneId = ZoneId.systemDefault();
    long epoch = ldt.atZone(zoneId).toEpochSecond(); 

    // If you only care about UTC
    long epochUTC = ldt.toEpochSecond(ZoneOffset.UTC);

Pas besoin d'utiliser LocalDateTimedu tout ici. Cette classe n'a volontairement aucun concept de fuseau horaire ou de décalage par rapport à UTC. Cela ne sert donc à rien ici. Au lieu de cela: LocalDate.parse( “20180306” , DateTimeFormatter.BASIC_ISO_DATE ).atStartOfDay( ZoneId.of( “Africa/Tunis” ).toEpochSecond()ne supposez pas que la journée commence à 00h00, ce n'est pas toujours le cas.
Basil Bourque

Que voulez-vous dire par ne pas supposer que la journée commence à 00h00
prime

1
Des anomalies telles que l' heure d'été (DST) signifient qu'à certaines dates, à certains endroits, la journée peut commencer à une autre heure, par exemple 01:00:00. Donc, plutôt que de supposer, laissez java.time déterminer le premier moment en appelant java.time.LocalDate.atStartOfDaypour obtenir un ZonedDateTime. Voir des exemples dans ma réponse . Comme je l'ai dit, la LocalDateTimeclasse est inutile et contre-productive dans tout cela.
Basil Bourque

Donc, avec LocalDateTimenous devons utiliser un ZoneId?
prime

Je pense que vous avez manqué tous mes points. Relisez ma réponse sur cette page. Recherchez Stack Overflow pour en savoir plus à partir de nombreux autres exemples et discussions. Mais je vais dire pour la dernière fois ici: LocalDateTimen'est pas approprié au problème à l'étude ici. A LocalDateTimene représente pas un moment. A LocalDateTimen'a rien à voir avec une localité ou un fuseau horaire particulier, bien que le nom puisse impliquer le contraire à première vue - en savoir plus sur l'intention et les détails de cette classe. La LocalDateTimeclasse sert un but, mais pas le but vu dans cette Question.
Basil Bourque

2

l'appel de fonction asStartOfDay()sur un java.time.LocalDateobjet renvoie un java.time.LocalDateTimeobjet


0

Java8 +

import java.time.Instant;
Instant.now().getEpochSecond(); //timestamp in seconds format (int)
Instant.now().toEpochMilli(); // timestamp in milliseconds format (long)

Utile, mais ne semble pas vraiment répondre à la question.
Ole VV

Merci pour le code, mais cela n'a rien à voir avec la question.
refaelio le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.