Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Data Java e fusos horários do MySQL

tl;dr

myPreparedStatement
.setObject(  
    … ,                                   // Specify which placeholder `?` in your SQL statement. 
    OffsetDateTime.now( ZoneOffset.UTC )  // Capture the current moment as seen in the wall-clock time of UTC (an offset-from-UTC of zero).
) ;

Evite aulas de data e hora legadas


Você está usando terríveis classes de data e hora que foram suplantadas anos atrás pelo java.time Aulas.

Nunca use Date ou Timestamp .

UTC


Capture o momento atual, em UTC. A maioria dos bancos de dados armazena um momento em UTC. E geralmente você deve fazer a maior parte de sua lógica de negócios, depuração, log, armazenamento e troca de dados em UTC.

OffsetDateTime


Represente um momento com um deslocamento de UTC usando o OffsetDateTime apropriadamente chamado classe.

Queremos o próprio UTC, ou um deslocamento de zero. Podemos usar uma constante para isso, ZoneOffset.UTC .
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ) ;

JDBC 4.2


A partir do JDBC 4.2, podemos trocar diretamente java.time objetos com o banco de dados.

Para salvar este momento em uma coluna de um tipo de dados semelhante ao padrão SQL TIMESTAMP WITH TIME ZONE :
myPreparedStatement.setObject( … , odt ) ;

Recuperação:
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

ZonedDateTime


Para apresentar esse momento recuperado ao usuário, convém ajustar o fuso horário esperado/desejado do usuário.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

Nunca confie no fuso horário padrão


Observe no código acima que sempre especificamos o deslocamento ou zona desejado/esperado.

Se você não especificar, um deslocamento ou zona será aplicado de forma silenciosa e implícita. É melhor especificar suas intenções explicitamente, pois o padrão atual de sua JVM, banco de dados e sistema operacional host estão fora de suas mãos como programador. O que significa que o código que depende do padrão variará em comportamento em tempo de execução.

Java 6 e 7


O mesmo homem, Stephen Colebourne, que lidera o JSR 310 e o java.time implementação, bem como o famoso Joda-Time projeto, também lidera outro projeto, ThreeTen-Backport . A maior parte do java.time a funcionalidade é portada para Java 6 e 7 nesta biblioteca, com API quase idêntica.

Então faça todo o seu trabalho em classes de back-port. Então, no último momento, converta para/de java.sql.Timestamp através do DateTimeUtils classe.

Esses métodos de conversão usam principalmente Instant objetos. Um Instant é um momento em UTC, sempre em UTC. Você pode ajustar a partir do seu OffsetDateTime para UTC extraindo um Instant . O Instant class é a classe básica do bloco de construção em java.time , com OffsetDateDate ter mais flexibilidade, como padrões de formatação alternativos ao gerar uma string. Mas ambos Instant e OffsetDateTime representam um momento, um ponto na linha do tempo.
Instant instant = odt.toInstant() ;  
java.sql.Timestamp ts = org.threeten.bp.DateTimeUtils.toSqlTimestamp( instant ) ;

Indo na outra direção, recuperando um Timestamp do seu banco de dados e, em seguida, convertendo imediatamente para um Instant .
java.sql.Timestamp ts = myResultSet.getTimestamp( … ) ;
Instant instant = org.threeten.bp.DateTimeUtils.toInstant( ts ) ;

Sobre java.time


O java.time framework é construído em Java 8 e posterior. Essas classes substituem o antigo e problemático legado classes de data e hora, como java.util.Date , Calendar , &SimpleDateFormat .

O Joda-Time projeto, agora em modo de manutenção , aconselha a migração para o java.time Aulas.

Para saber mais, consulte o Tutorial do Oracle . E pesquise no Stack Overflow muitos exemplos e explicações. A especificação é JSR 310 .

Você pode trocar java.time objetos diretamente com seu banco de dados. Use um driver JDBC compatível com JDBC 4.2 ou mais tarde. Não há necessidade de strings, não há necessidade de java.sql.* Aulas.

Onde obter as classes java.time?

O ThreeTen-Extra projeto estende java.time com classes adicionais. Este projeto é um campo de provas para possíveis adições futuras ao java.time. Você pode encontrar algumas classes úteis aqui, como Interval , YearWeek , YearQuarter e mais .