web-dev-qa-db-fra.com

Convertir Java.sql.Timestamp en Java 8 ZonedDateTime?

Migration du temps Joda vers Java 8

Joda:

UserObject user = new UserObject()
user.setCreatedAt(new DateTime(rs.getTimestamp("columnName")));`

Migration vers Java 8

Ceci est mon code; il compile; Je doute que cela fonctionne:

ZonedDateTime.ofInstant(rs.getTimestamp("columnName").toLocalDateTime().toInstant(ZoneOffset.UTC),ZoneId.of("UTC")));

Dans certains cas, la date est incorrecte. Aucun conseil?

9
Parameswar

Cela semble fonctionner: -

ZonedDateTime.ofInstant(rs.getTimestamp("columnname").toInstant(), ZoneId.of("UTC"))
5
Parameswar

tl; dr

Pour suivre un moment de l'historique, utilisez Instant comme type de votre variable membre de classe. Plus précisément, ce moment est considéré comme une date et une heure dans UTC .

public class UserObject() {
    Instant createdAt ;
    …
    public void setCreatedAt( Instant instantArg ) {
        this.createdAt = instantArg ;
    {
}

Utilisation, capturant le moment actuel.

UserObject user = new UserObject() ;
user.setCreatedAt( Instant.now() ) ;

Utilisation, remplissage de la valeur de la base de données.

UserObject user = new UserObject() ;
Instant instant = myResultSet.getObject( "when_created" , Instant.class ) ;
user.setCreatedAt( instant ) ;

JDBC 4.2 ne nécessite pas de prise en charge pour Instant (un instant en UTC). Si votre pilote ne prend pas en charge cette classe, passez à OffsetDateTime qui est requis.

UserObject user = new UserObject() ;
OffsetDateTime odt = myResultSet.getObject( "when_created" , OffsetDateTime.class ) ;  
user.setCreatedAt( odt.toInstant() ) ;  // Convert from an `OffsetDateTime` (for any offset-from-UTC) to `Instant` (always in UTC). 

Table of date-time types in Java (both modern and legacy) and in standard SQL.

Présent à l'utilisateur, localisé pour l'interface utilisateur.

user               // Your business object.
.getCreatedAt()    // Returns a `Instant` object.
.atZone(           // Adjust from UTC to a time zone. Same moment, same point on the timeline, different wall-clock time.
    ZoneId.of( "Pacific/Auckland" )  // Specify the user’s desired/expected time zone.
)                  // Returns a `ZonedDateTime` object. 
.format(           // Generate a `String` representing the value of date-time object.
    DateTimeFormatter.ofLocalizedDateTime(
        FormatStyle.FULL   // Specify how long or abbreviated the string.
    )
    .withLocale(   // Specify `Locale` to determine human language and cultural norms for localization.
        Locale.CANADA_FRENCH 
    )
)                  // Returns a `String`.

Notez que Locale n'a rien à voir avec le fuseau horaire, un problème orthogonal. Le code ci-dessus peut être pour un homme d'affaires de Québec qui voyage en Nouvelle-Zélande . Elle veut voir l'heure de l'horloge murale utilisée par les kiwis autour d'elle, mais elle préfère lire son affichage textuel dans son français natal. Le fuseau horaire et les paramètres régionaux sont des questions qu'il vaut mieux laisser à la présentation uniquement; il est généralement préférable d'utiliser UTC dans le reste de votre code. Ainsi, nous avons défini notre variable membre createdAt comme Instant, Instant étant toujours en UTC par définition.

Éviter Java.sql.Timestamp

  • Le Java.sql.Timestamp, de même que Java.sql.Date, Java.util.Date et Calendar font tous partie des anciennes classes de date-heure terriblement gênantes qui ont été remplacées il y a des années par les classes Java.time .
  • Joda-Time est désormais supplanté par les classes Java.time , comme indiqué au début page du site du projet.

Java.time

Depuis JDBC 4.2 et versions ultérieures, nous pouvons directement échanger des objets Java.time avec la base de données.

Instant

Envoyez l'instant actuel à la base de données en utilisant la classe Instant. La classe Instant représente un moment de la chronologie dans UTC avec une résolution de nanosecondes (jusqu'à neuf (9) chiffres d'une fraction décimale).

Instant instant = Instant.now() ;  // Capture the current moment in UTC.
myPreparedStatement.setObject( … , instant ) ;

Et la récupération.

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

ZonedDateTime

Pour voir ce même moment à travers l'objectif de l'heure de l'horloge murale utilisée par les gens d'une région particulière (un fuseau horaire), appliquez un ZoneId pour obtenir un ZonedDateTime .

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

LocalDateTime n'est pas pas un instant

.toLocalDateTime ().

N'impliquez jamais la classe LocalDateTime lors de la représentation d'un moment précis dans le temps. La classe n'a délibérément aucun concept de fuseau horaire ou de décalage par rapport à l'UTC. En tant que tel, il ne peut pas représenter un moment, n'est pas un point sur la chronologie. C'est une vague idée de moments potentiels sur une plage d'environ 26-27 heures (la plage de fuseaux horaires).


À propos de Java.time

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

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

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

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.* 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 de futurs ajouts possibles à Java.time. Vous pouvez trouver ici des classes utiles telles que Interval , YearWeek , YearQuarter , et plus .

11
Basil Bourque

Utilisez le suivant:

rs.getTimestamp("columnName").toInstant()
    .atZone(ZoneId.[appropriate-zone-ID-here])

Vous devez utiliser un ZoneId approprié à la région (vous pouvez essayer avec ZoneId.systemDefault() pour commencer).

Pour plus de détails sur les différences entre les différentes API Java-Time, voir cette excellente réponse .

4
Tomasz Linkowski