Converti LocalDate in LocalDateTime o java.sql.Timestamp


126

Sto usando JodaTime 1.6.2.

Ho un file LocalDateche devo convertire in (Joda) LocalDateTimeo in java.sqlTimestampfor ormapping.

Il motivo è che ho capito come convertire tra a LocalDateTimee 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));

Quindi, se riesco a convertire solo tra LocalDatee LocalDateTime, posso effettuare la conversione continua in java.sql.Timestamp. Grazie per eventuali spinte nella giusta direzione!


Cordiali saluti, il progetto Joda-Time è ora in modalità di manutenzione , con il team che consiglia la migrazione alle classi java.time . Vedi Tutorial di Oracle . Inoltre, la java.sql.Timestampclasse è ora legacy, soppiantata dalle classi java.time , in particolare da Instant.
Basil Bourque

Risposte:


269

JodaTime

Per convertire JodaTime org.joda.time.LocalDatein java.sql.Timestamp, basta farlo

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

Per convertire JodaTime org.joda.time.LocalDateTimein java.sql.Timestamp, basta farlo

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

JavaTime

Per convertire Java8 java.time.LocalDatein java.sql.Timestamp, basta farlo

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

Per convertire Java8 java.time.LocalDateTimein java.sql.Timestamp, basta farlo

Timestamp timestamp = Timestamp.valueOf(localDateTime);

Fai attenzione durante la conversione LocalDateTimein DateTimepoiché non tutti LocalDateTimei messaggi sono validi DateTime. Fonte: joda-time.sourceforge.net/faq.html#illegalinstant e mi imbatto in questo.
Christophe De Troyer

ha ottenuto un errore di compilazione sull'argomento poiché valueOf () accetta una stringa.
Patriottico

@ Patriotic: ciò accadrà solo se in realtà non stai utilizzando Java SE 1.8 o più recente. Come indicato nella risposta e nei collegamenti forniti a Javadoc (i testi blu nella risposta sopra sono in realtà collegamenti, è possibile fare clic su di essi per eseguire il drill down nel Javadoc), il Timestamp#valueOf()metodo accetta poiché Java SE 1.8 anche a LocalDateTime.
BalusC

60

Il modo migliore per utilizzare Java 8 Time API:

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

Per l'uso con JPA inserito con il tuo modello ( 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();
    }
}

Quindi ora è il tempo indipendente dal fuso orario relativo. Inoltre è facile:

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

Formattazione:

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

AGGIORNAMENTO: postgres 9.4.1208, HSQLDB 2.4.0 ecc. Capiscono Java 8 Time API senza alcuna conversazione!


17

tl; dr

Il progetto Joda-Time è in modalità di manutenzione, ora soppiantato dalle classi java.time .

  • Usa solo lajava.time.Instant classe.
  • Non c'è bisogno di:
    • LocalDateTime
    • java.sql.Timestamp
    • stringhe

Cattura il momento attuale in UTC.

Instant.now()  

Per memorizzare quel momento nel database:

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

Per recuperare quel momento dal database:

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

Per regolare l'ora dell'orologio da parete a quella di un particolare fuso orario.

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

LocalDateTime è la classe sbagliata

Altre risposte sono corrette, ma non indicano che LocalDateTimeè la classe sbagliata per il tuo scopo.

Sia in java.time che in Joda-Time , LocalDateTimemanca volutamente qualsiasi concetto di fuso orario o offset-da-UTC. In quanto tale, non rappresenta un momento e non è un punto sulla sequenza temporale. A LocalDateTimerappresenta un'idea approssimativa del potenziale momenti in un intervallo di circa 26-27 ore.

Utilizzare a LocalDateTimeper quando la zona / offset è sconosciuta (non è una buona situazione) o quando l'offset di zona è indeterminato. Ad esempio, "Natale inizia al primo momento del 25 dicembre 2018" sarebbe rappresentato come un LocalDateTime.

Usa a ZonedDateTimeper rappresentare un momento in un particolare fuso orario. Ad esempio, il Natale che inizia in una zona particolare come Pacific/Aucklando America/Montrealsarebbe rappresentato con un ZonedDateTimeoggetto.

Per un momento sempre in UTC, usa Instant.

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

Applica un fuso orario. Stesso momento, stesso punto sulla sequenza temporale, ma visualizzato con un orario dell'orologio da parete diverso.

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

Quindi, se posso solo convertire tra LocalDate e LocalDateTime,

No, strategia sbagliata. Se si dispone di un valore di sola data e si desidera un valore di data e ora, è necessario specificare un'ora del giorno. Quell'ora del giorno potrebbe non essere valida in quella data per una zona particolare, nel qual caso la ZonedDateTimeclasse regola automaticamente l'ora come necessario.

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

Se vuoi che il primo momento della giornata sia l'ora del giorno, lascia che java.time determini quel momento. Non dare per scontato che la giornata inizi alle 00:00:00. Anomalie come l'ora legale (DST) indicano che il giorno può iniziare in un altro momento come l'01: 00:00.

ZonedDateTime zdt = ld.atStartOfDay( z ) ;

java.sql.Timestamp è la classe sbagliata

La java.sql.Timestampfa parte delle classi fastidiosi vecchi data-ora che sono ora patrimonio, soppiantato interamente dai java.time classi. Quella classe è stata utilizzata per rappresentare un momento in UTC con una risoluzione di nanosecondi . Quello scopo è ora servito con java.time.Instant.

JDBC 4.2 con getObject /setObject

A partire da JDBC 4.2 e versioni successive, il tuo driver JDBC può scambiare direttamente oggetti java.time con il database chiamando:

Per esempio:

myPreparedStatement.setObject(  , instant ) ;

… e …

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

Converti legacy ⬌ moderno

Se è necessario interfacciarsi con il vecchio codice non ancora aggiornato a java.time , eseguire la conversione avanti e indietro utilizzando nuovi metodi aggiunti alle vecchie classi.

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

…e…

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

Informazioni su java.time

Il framework java.time è integrato in Java 8 e versioni successive. Queste classi soppiantare la vecchia fastidiosi legacy classi data-time come java.util.Date, Calendar, e SimpleDateFormat.

Il progetto Joda-Time , ora in modalità di manutenzione , consiglia la migrazione alle classi java.time .

Per saperne di più, vedere il tutorial Oracle . E cerca Stack Overflow per molti esempi e spiegazioni. La specifica è JSR 310 .

Puoi scambiare oggetti java.time direttamente con il tuo database. Utilizza un driver JDBC compatibile con JDBC 4.2 o successivo. Non c'è bisogno di stringhe, non c'è bisogno di java.sql.*classi.

Dove ottenere le classi java.time?

  • Java SE 8 , Java SE 9 e versioni successive
    • Built-in.
    • Parte dell'API Java standard con un'implementazione in bundle.
    • Java 9 aggiunge alcune funzionalità e correzioni minori.
  • Java SE 6 e Java SE 7
    • Gran parte delle funzionalità java.time sono portate indietro su Java 6 e 7 in ThreeTen-Backport .
  • androide
    • Versioni successive delle implementazioni di bundle Android delle classi java.time.
    • Per precedenza Android (<26), il ThreeTenABP progetto si adatta ThreeTen-Backport (di cui sopra). Vedi Come usare ThreeTenABP… .

Il progetto ThreeTen-Extra estende java.time con classi aggiuntive. Questo progetto è un banco di prova per possibili future aggiunte a java.time. Si possono trovare alcune classi utili, come per esempio Interval, YearWeek, YearQuartere altro .


5

A seconda del fuso orario, potresti perdere qualche minuto (1650-01-01 00:00:00 diventa 1649-12-31 23:52:58)

Usa il codice seguente per evitarlo

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

3

Dal momento che Joda è sempre sbiadita, qualcuno potrebbe voler convertire LocaltDatea LocalDateTimein Java 8. In Java 8 LocalDateTimedarà un modo per creare un LocalDateTimeesempio utilizzando una LocalDatee LocalTime. Controlla qui.

public static LocalDateTime di (LocalDate date, LocalTime time)

Il campione sarebbe,

    // 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

Solo per riferimento, per ottenere i secondi dell'epoca di seguito possono essere utilizzati,

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

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

Non c'è bisogno di usare LocalDateTimeaffatto qui. Quella classe manca intenzionalmente di qualsiasi concetto di fuso orario o offset da UTC. Quindi non serve a nessuno scopo utile qui. Invece: LocalDate.parse( “20180306” , DateTimeFormatter.BASIC_ISO_DATE ).atStartOfDay( ZoneId.of( “Africa/Tunis” ).toEpochSecond()non dare per scontato che la giornata inizi alle 00:00, non sempre è così.
Basil Bourque

Cosa intendi per non dare per scontato che la giornata inizi alle 00.00
prime

1
Anomalie come l' ora legale (DST) indicano che in alcune date in alcuni luoghi il giorno può iniziare in un altro momento, come l'01: 00:00. Quindi, piuttosto che supporre, lascia che java.time determini il primo momento chiamando java.time.LocalDate.atStartOfDayper ottenere un file ZonedDateTime. Vedi esempi nella mia risposta . Come ho commentato, la LocalDateTimeclasse è inutile e controproducente in tutto questo.
Basil Bourque

Quindi con LocalDateTimedobbiamo usare un ZoneId?
Prime

Penso che tu abbia perso tutti i miei punti. Rileggi la mia risposta in questa pagina. Cerca in Stack Overflow per saperne di più da molti altri esempi e discussioni. Ma lo dico per l'ultima volta qui: nonLocalDateTime è appropriato al problema in questione qui. A non non rappresentare un momento. A non ha nulla a che fare con una particolare località o fuso orario, sebbene il nome possa implicare il contrario a prima vista: scopri di più sull'intenzione e sui dettagli di questa classe. La classe ha uno scopo, ma non quello visto in questa domanda. LocalDateTimeLocalDateTimeLocalDateTime
Basil Bourque

2

funzione di chiamata asStartOfDay()in java.time.LocalDateoggetto restituisce un java.time.LocalDateTimeoggetto


0

Java8 +

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

Utile, ma non sembra davvero rispondere alla domanda.
Ole VV

Grazie per il codice, ma non ha nulla a che fare con la domanda.
refaelio
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.