PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Was sollte der Parametertyp in Java sein, wenn es sich in Postgresql um einen Zeitstempel ohne Zeitzone handelt?

tl;dr

Für SQL mit Half-Open-Zeitspanne:
"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()
) ;

Achtung:Ich vermute, Sie verwenden den falschen Typ für Ihre Spalte in Ihrer Datenbank. Momente können nur mit TIMESTAMP WITH TIME ZONE verfolgt werden , nicht TIMESTAMP WITHOUT TIME ZONE . Durchsuchen Sie Stack Overflow nach weiteren Informationen.

Nicht einen Augenblick

Die Antwort von Jens ist mittlerweile veraltet. Heutzutage sollten Sie die moderne java.time verwenden Klassen, die die lästigen alten Legacy-Datums-Zeit-Klassen ersetzt haben.

Diesem Datentyp fehlt sowohl bei Postgres als auch beim SQL-Standard absichtlich der Kontext eines Offsets von UTC oder einer Zeitzone. Also Vorsicht, dieser Typ kann keinen Moment darstellen, ist es nicht ein Punkt auf der Zeitachse.

Nein, falscher Datentyp. Der java.sql.Timestamp ist nicht nur veraltet und hat schreckliche Designfehler Klasse repräsentiert einen Moment, einen bestimmten Punkt auf der Zeitachse. Das stimmt also nicht mit Ihrer Spalte vom Typ TIMESTAMP WITHOUT TIME ZONE überein .

LocalDateTime

Sie sollten stattdessen LocalDateTime verwenden Klasse. Diese Klasse repräsentiert ein Datum mit einer Uhrzeit, aber es fehlt jegliches Konzept von Offset oder Zeitzone.

Um einen Wert aus der Datenbank abzurufen.

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

Um einen Wert an die Datenbank zu senden.

myPreparedStatement.setObject( … , ldt ) ;

Tagesbeginn

Sie haben hier eine andere Diskrepanz. Sie geben einen Nur-Datum-Wert an, aber Ihre Spalte enthält Werte für Datum und Uhrzeit.

Ein weiteres Problem:Sie verwenden dumme Zeichenfolgen, wo Sie intelligente Objekte verwenden sollten. Ab JDBC 4.2 können wir java.time austauschen Objekte mit der Datenbank. Verwenden Sie ein PreparedStatement mit Platzhaltern und übergeben Sie Objekte über das `set

Um das Problem mit dem Datum und der Uhrzeit zu lösen, müssen wir den Beginn des Tages bestimmen. Mit LocalDateTime , haben wir keine Zeitzonenanomalien zu berücksichtigen. Der Tag beginnt also immer um 00:00 Uhr. Trotzdem sollten wir uns angewöhnen, nach java.time zu fragen um den Tagesbeginn zu bestimmen.

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

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

Schreiben Sie SQL mit Platzhaltern.

Ich schlage vor, Sie ändern Ihr Denken und machen sich den halboffenen Ansatz zur Definition von Zeitspannen zur Gewohnheit. Bei Half-Open ist der Anfang inklusive während das Ende exklusiv ist . Suchen Sie also für den einzelnen ganzen Tag des 20. nach Daten, die gleich oder später als der 20. sind und bis zum, aber nicht laufen darunter der 21. Was diesen ersten Teil angeht, ist eine kürzere Art, „gleich oder später“ zu sagen, „nicht vorher“, also verwenden wir !< .

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

Füttern Sie diese sql string zu Ihrer vorbereiteten Anweisung. Übergeben Sie dann die beiden LocalDateTime Objekte für die Platzhalter.

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