PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Quale dovrebbe essere il tipo di parametro in Java quando è un timestamp senza fuso orario in postgresql?

tl;dr

Per SQL che utilizza l'intervallo di tempo Half-Open:
"SELECT * FROM tbl WHERE when !< ? AND when < ? ; "

myPreparedStatement.setObject(       // Use a prepared statement so you can pass smart objects rather than dumb strings.
    1 ,                              // Specify which placeholder is being fulfilled.
    LocalDate                        // Represent a date-only value, without time-of-day and without time zone or offset-from-UTC.
    .parse( "2014-11-20" )           // Parse an input string in standard ISO 8601 format to get a `LocalDate` object.
    .atStartOfDay()                  // Determine the first moment of the day on that date. Returns a `LocalDateTime` object representing a date with time-of-day but lacking any concept of time zone or offset-from-UTC.
) ;
myPreparedStatement.setObject( 
    2 , 
    LocalDate
    .parse( "2014-11-21" )
    .atStartOfDay()
) ;

Attenzione:suppongo che tu stia usando il tipo sbagliato per la tua colonna nel tuo database. I momenti possono essere monitorati solo con TIMESTAMP WITH TIME ZONE , non TIMESTAMP WITHOUT TIME ZONE . Cerca Stack Overflow per ulteriori informazioni.

Neanche un momento

La risposta di Jens è ormai superata. Al giorno d'oggi dovresti usare il moderno java.time classi che hanno soppiantato le fastidiose vecchie classi data-ora.

Questo tipo di dati sia su Postgres che sullo standard SQL manca di proposito del contesto di un offset da UTC o di un fuso orario. Quindi, attenzione, questo tipo non può rappresentare un momento, non un punto sulla sequenza temporale.

No, tipo di dati errato. Oltre ad essere legacy e ad essere terribilmente imperfetto nel design, java.sql.Timestamp la classe rappresenta un momento, un punto specifico sulla timeline. Quindi questa è una mancata corrispondenza con la tua colonna di tipo TIMESTAMP WITHOUT TIME ZONE .

LocalDateTime

Dovresti invece usare LocalDateTime classe. Questa classe rappresenta una data con un'ora del giorno ma non ha alcun concetto di offset o fuso orario.

Per recuperare un valore dal database.

LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;

Per inviare un valore al database.

myPreparedStatement.setObject( … , ldt ) ;

Inizio della giornata

Hai un'altra discrepanza qui. Stai fornendo un valore di sola data ma la tua colonna contiene valori di data con ora del giorno.

Un altro problema:stai usando stringhe stupide in cui dovresti usare oggetti intelligenti. A partire da JDBC 4.2 possiamo scambiare java.time oggetti con il database. Usa un PreparedStatement con segnaposto e passare gli oggetti tramite il `set

Per risolvere il problema della data con l'ora, dobbiamo determinare l'inizio della giornata. Con LocalDateTime , non abbiamo anomalie di fuso orario di cui tenere conto. Quindi la giornata inizia sempre alle 00:00. Tuttavia, dovremmo prendere l'abitudine di chiedere a java.time per determinare l'inizio della giornata.

LocalDate startDate = LocalDate.parse( "2014-11-20" ) ;
LocalDate stopDate = LocalDate.parse( "2014-11-21" ) ;

LocalDateTime start = startDate.atStartOfDay() ;
LocalDateTime stop = stopDate.atStartOfDay() ;

Scrivi il tuo SQL con i segnaposto.

Ti suggerisco di cambiare il tuo modo di pensare per prendere l'abitudine dell'approccio Half-Open per definire l'intervallo di tempo. In Half-Open, l'inizio è inclusivo mentre il finale è esclusivo . Quindi per il singolo giorno intero del 20, cerca date uguali o successive al 20 e fino a, ma non compreso, il 21. Per quanto riguarda quella prima parte, un modo più breve per dire "uguale a o successivo" è "non prima", quindi usiamo !< .

String sql = "SELECT * FROM tbl WHERE when !< ? AND when < ? ; " ;

Dai da mangiare a quel sql stringa alla tua dichiarazione preparata. Quindi passa i due LocalDateTime oggetti per i segnaposto.

myPreparedStatement.setObject( 1 , start ) ;
myPreparedStatement.setObject( 2 , stop ) ;