I have a Date object that is getting the date from the database which is already in UTC,
Don’t.
The terrible Date
class was supplanted years ago by the modern java.time classes.
You should be retrieving a moment from a database column of type TIMESTAMP WITH TIME ZONE
by using OffsetDateTime
.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
That value is likely to be in UTC. If you want to view that moment adjusted into a time zone, apply a ZoneId
to get a ZonedDateTime
.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
but the timezone offset gets converted based on the location where the application is running.
Be aware that while a java.util.Date
is actually a moment in UTC, its toString
method tells a lie. That method dynamically applies the JVM’s current default time zone while generating its text. While well-intentioned, this anti-feature creates the illusion of a time zone being present inside the Date
.
No such problem if you use the java.time classes only. There is no need to ever again use java.util.Date
, java.sql.Date
, Calendar
, GregorianCalendar
, SimpleDateFormat
, DateFormat
, or other such legacy classes.
So if the database has date: 2019-09-06 00:00:00.000 and the application is running in LA, the Date object will have the offset of 7 and the output will look like this 2019-09-06T07:00Z
This part makes no sense to me.
Do you have the correct data types in your database? The TIMESTAMP WITHOUT TIME ZONE
would be the wrong type to track a moment. This type has only a date and a time-of-day, but lacks the context of an offset-from-UTC or a time zone. This type cannot represent a specific point on the timeline.
Edit your Question to specify exactly what database and what data types are your columns.
At least try using the java.time to eliminate the confusion of Date::toString
injecting an inappropriate time zone.
The Date class does not have a setTimeZone() method
A java.util.Date
is always in UTC, just a count of milliseconds since the first moment of 1970 in UTC, 1970-01-01T00:00:00Z. Nothing more. (Actually there is more, a time zone buried deep, with no getter methods, that affects behavior of equals
and such, but in irrelevant to our discussion here. This class is a bloody mess of bad design.)
and the first thing that came to mind is to convert it to a String and hardcode 00:00Z at the end, which isn't clean. Any ideas?
No, you definitely should not play such games. You will only get deeper into trouble. Get your data types straight in your database, use only the java.time classes in Java, and your problems will be solved.
I cannot give further help since you did not provide enough details. Search Stack Overflow to learn more. This topic has been addressed many many times already.