PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Qual deve ser o tipo de parâmetro em Java quando é um timestamp sem fuso horário no postgresql?

tl;dr


Para SQL usando intervalo de 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()
) ;

Cuidado:suponho que você esteja usando o tipo errado para sua coluna em seu banco de dados. Momentos só podem ser rastreados com TIMESTAMP WITH TIME ZONE , não TIMESTAMP WITHOUT TIME ZONE . Pesquise o Stack Overflow para obter mais informações.

Nem um momento


A resposta de Jens agora está ultrapassada. Hoje em dia você deve estar usando o moderno java.time classes que suplantaram as antigas e problemáticas classes de data e hora legadas.

Esse tipo de dados no Postgres e no padrão SQL propositalmente não possui o contexto de um deslocamento de UTC ou um fuso horário. Portanto, cuidado, este tipo não pode representar um momento, não um ponto na linha do tempo.

Não, tipo de dados errado. Além de ser herdado e ter um design terrivelmente falho, o java.sql.Timestamp classe representa um momento, um ponto específico na linha do tempo. Portanto, esta é uma incompatibilidade com sua coluna do tipo TIMESTAMP WITHOUT TIME ZONE .

LocalDateTime


Em vez disso, você deve usar o LocalDateTime classe. Essa classe representa uma data com hora do dia, mas não possui nenhum conceito de deslocamento ou fuso horário.

Para recuperar um valor do banco de dados.
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;

Para enviar um valor ao banco de dados.
myPreparedStatement.setObject( … , ldt ) ;

Início do dia


Você tem outra incompatibilidade aqui. Você está fornecendo um valor somente de data, mas sua coluna contém valores de data com hora do dia.

Outro problema:você está usando strings burras onde deveria estar usando objetos inteligentes. A partir do JDBC 4.2 podemos trocar java.time objetos com o banco de dados. Use um PreparedStatement com placeholders, e passar objetos através do `set



Para resolver o problema de data com hora do dia, precisamos determinar o início do dia. Com LocalDateTime , não temos anomalias de fuso horário para explicar. Assim, o dia sempre começa às 00:00. No entanto, devemos ter o hábito de perguntar java.time para determinar o início do dia.
LocalDate startDate = LocalDate.parse( "2014-11-20" ) ;
LocalDate stopDate = LocalDate.parse( "2014-11-21" ) ;

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

Escreva SQL com espaços reservados.

Sugiro que você mude seu pensamento para criar o hábito da abordagem Meio Aberto para definir o intervalo de tempo. No Half-Open, o início é inclusivo enquanto o final é exclusivo . Portanto, para o único dia inteiro do dia 20, pesquise datas iguais ou posteriores ao dia 20 e até, mas não inclusive, dia 21. Quanto à primeira parte, uma maneira mais curta de dizer "igual a ou posterior" é "não antes", então usamos !< .
String sql = "SELECT * FROM tbl WHERE when !< ? AND when < ? ; " ;

Alimente esse sql string para sua instrução preparada. Em seguida, passe os dois LocalDateTime objetos para os espaços reservados.
myPreparedStatement.setObject( 1 , start ) ;
myPreparedStatement.setObject( 2 , stop ) ;