My partial table definition (MySQL) looks as follows:
+-----------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+----------+------+-----+---------+----------------+
| ... | ... | .. | ... | ... | ... |
| timestamp | datetime | YES | | NULL | |
| ... | ... | .. | ... | ... | ... |
+-----------+----------+------+-----+---------+----------------+
I want to update the timestamp field using JDBC. The assumption is that the timestamp is in UTC.
In my Java code I am obtaining the timestamp field as follows:
Timestamp datetime = new Timestamp(new Date().getTime());
The documentation for the java.util.Date states that:
Although the Date class is intended to reflect coordinated universal time (UTC), it may not do so exactly, depending on the host environment of the Java Virtual Machine.
Unfortunately on my Windows 10 environment (java version "1.8.0_231"), the Date object reflects my local timezone. As a result the timestamp that gets added to the database is for the local timezone, not UTC.
Q) How can I obtain the timestamp in UTC, so that the correct value is added to the database?
You have the wrong data type in MySQL, and the wrong class in Java.
TIMESTAMP
rather than DATETIME
.java.time.OffsetDateTime
rather than java.sql.Timestamp
.Example code snippet.
myPreparedStatement
.setObject(
… , // Specify which placeholder `?` to fill-in.
OffsetDateTime // JDBC 4.2 and later requires a JDBC driver support exchanging `java.time.OffsetDateTime` objects with the database.
.now( ZoneOffset.UTC ) // Capture the current moment as seen in UTC (an offset of zero hours-minutes-seconds).
)
The assumption is that the timestamp is in UTC
Do you understand that DATETIME
in MySQL is not in UTC? That type in MySQL has no concept of time zone nor offset-from-UTC.
If you are tracking moments, specific points on the timeline, you have the wrong data type in MySQL. You should be using TIMESTAMP
to track moments in MySQL.
You are using terrible date-time classes that were bundled with the earliest versions of Java. Those classes were supplanted by the modern java.time classes in Java 8 and later, as defined in JSR 310. Never use the java.sql.Timestamp
class.
To get the current moment in UTC, use Instant
.
Instant instant = Instant.now() ;
Define your column in MySQL as type TIMESTAMP
.
You may be able to write an Instant
via your JDBC driver. However, JDBC 4.2 requires support for OffsetDateTime
but oddly omits required support for Instant
. No matter, we can easily convert.
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
Write that to the database using your JDBC driver compliant with JDBC 4.2 or later, through a prepared statement.
myPreparedStatement.setObject( … , odt ) ;
Retrieval.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
If you follow the code seen here you will have no time zone problems.
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes. Hibernate 5 & JPA 2.2 support java.time.
Where to obtain the java.time classes?
Q) How can I obtain the timestamp in UTC
Do it as follows:
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Etc/UTC"));
Timestamp timestamp = Timestamp.valueOf(zdt.toLocalDateTime());
Notes:
TIMESTAMP
. Check this for more details.java.util
date-time API and switch to modern date-time API.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With