Java >> Java tutorial >  >> Tag >> SQL

Konverter java.sql.Timestamp til Java 8 ZonedDateTime?

tl;dr

Brug Instant for at spore et øjeblik i historien som typen af ​​din klassemedlemsvariabel. Specifikt ses dette øjeblik som en dato og et tidspunkt på dagen i UTC.

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

Brug, fanger det aktuelle øjeblik.

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

Brug, udfyldning af værdi fra database.

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

JDBC 4.2 kræver ikke understøttelse af Instant (et øjeblik i UTC). Hvis din chauffør ikke understøtter den klasse, skal du skifte til OffsetDateTime som er påkrævet.

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). 

Præsenter for brugeren, lokaliseret til brugergrænsefladen.

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`.

Bemærk, at Locale har ingenting at gøre med tidszone, et ortogonalt problem. Ovenstående kode kan være til en forretningsmand fra Québec, som rejser i New Zealand. Hun vil gerne se væguret, der bruges af kiwierne omkring hende, men hun foretrækker at læse dens tekstvisning på sit franske modersmål. Både tidszone og lokalitet er problemer, der bedst kun overlades til præsentationen; generelt bedst at bruge UTC i resten af ​​din kode. Således definerede vi vores medlemsvariabel createdAt som en Instant , med Instant altid være i UTC per definition.

Undgå java.sql.Timestamp

  • java.sql.Timestamp , sammen med java.sql.Date , java.util.Date og Calendar er alle en del af de frygtelig besværlige gamle date-time klasser, der blev fortrængt for år siden af ​​java.time klasser.
  • Joda-Time også er nu fortrængt af java.time klasser, som angivet på forsiden af ​​projektets websted.

java.time

Fra og med JDBC 4.2 og senere kan vi udveksle java.time direkte objekter med databasen.

Instant

Send det aktuelle øjeblik til databasen ved hjælp af Instant klasse. Instant klasse repræsenterer et øjeblik på tidslinjen i UTC med en opløsning på nanosekunder (op til ni (9) cifre af en decimalbrøk).

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

Og hentning.

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

ZonedDateTime

For at se det samme øjeblik gennem linsen af ​​væguret, der bruges af befolkningen i en bestemt region (en tidszone), skal du anvende en ZoneId for at få en ZonedDateTime .

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

LocalDateTime er ikke et øjeblik

.toLocalDateTime().

Involver aldrig LocalDateTime klasse, når de repræsenterer et bestemt tidspunkt. Klassen mangler bevidst ethvert koncept for tidszone eller offset-fra-UTC. Som sådan kan det ikke repræsentere et øjeblik, er ikke et punkt på tidslinjen. Det er en vag idé om potentiale øjeblikke i et interval på omkring 26-27 timer (intervallet af tidszoner).

Om java.time

java.time framework er indbygget i Java 8 og nyere. Disse klasser erstatter de besværlige gamle gamle dato-tidsklasser såsom java.util.Date , Calendar , &SimpleDateFormat .

Se Oracle Tutorial for at lære mere . Og søg i Stack Overflow for mange eksempler og forklaringer. Specifikationen er JSR 310.

Joda-tiden projekt, nu i vedligeholdelsestilstand, rådgiver migrering til java.time-klasserne.

Du kan udveksle java.time objekter direkte med din database. Brug en JDBC-driver, der er kompatibel med JDBC 4.2 eller nyere. Intet behov for strenge, intet behov for java.sql.* klasser. Hibernate 5 og JPA 2.2 understøtter java.time .

Hvor får man java.time klasserne?

  • Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 , og senere - En del af standard Java API med en bundtet implementering.
    • Java 9 bragte nogle mindre funktioner og rettelser.
  • Java SE 6 og Java SE 7
    • Det meste af java.time funktionalitet er back-porteret til Java 6 og 7 i ThreeTen-Backport .
  • Android
    • Senere versioner af Android (26+) bundter implementeringer af java.time klasser.
    • For tidligere Android (<26), en proces kendt som API-afsugning bringer et undersæt af java.time funktionalitet, der ikke oprindeligt var indbygget i Android.
      • Hvis afsukkeringen ikke tilbyder det, du har brug for, kan ThreeTenABP projektet tilpasser ThreeTen-Backport (nævnt ovenfor) til Android. Se Sådan bruger du ThreeTenABP... .

Dette ser ud til at virke:-

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

Brug følgende:

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

Du skal bruge en ZoneId passende til regionen (du kan prøve med ZoneId.systemDefault() til en start).

For flere detaljer om forskellene mellem forskellige Java-Time API'er, se dette gode svar.


Java tag