tl;dr
You do not provide enough info. Report:
- The results of this:
myJavaUtilDate.toInstant().toString()
- The inputs to the component
- The current default time zone of the app
Details
You do not really give enough information about your problem. Are you getting a correct date-time value in UTC via the java.util.Date
object from your GUI component or not?
If the user in Québec time zone of America/Montreal
entered 9 AM on December 1, 2016, and your component is correctly adjusting those values into UTC while producing the java.util.Date
object, then you have no problem. The UTC value would be 2 PM in the afternoon for UTC, as America/Montreal
is five hours behind UTC on that particular date. Just pass the Date
object to the database after converting to a java.sql.Timestamp
object.
FYI, both the old date-time classes classes (Date
& Calendar
etc.) and Joda-Time are now supplanted by the java.time classes. Here is some example code in java.time showing the kind of behavior your component is hopefully employing.
LocalDate ld = LocalDate.of ( 2016 , Month.DECEMBER , 1 );
LocalTime lt = LocalTime.of ( 9 , 0 );
ZoneId z = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.of ( ld , lt , z );
Instant instant = zdt.toInstant (); // UTC
System.out.println ( "zdt.toString(): " + zdt );
System.out.println ( "instant.toString(): " + instant );
zdt.toString(): 2016-12-01T09:00-05:00[America/Montreal]
instant.toString(): 2016-12-01T14:00:00Z
The Z
on the end of the string is short for Zulu
and means UTC.
Given the unfortunate behavior of java.util.Date::toString
to apply your current default time zone while generating the string, I suggest you convert your Date
to an Instant
so you can get a clear reading of its value.
Instant instantConvertedFromDateOfComponent = myJavaUtilDate.toInstant();
If after this step you do indeed see 2 PM in the afternoon, then all is well and your component is performing well.
If your component is acting badly, ignoring the issue of time zone and reporting your user’s input as if the user intended UTC as their own zone, then you will see 2016-12-01T09:00:00Z
. That is a problem. The workaround is to make the time zone adjustment yourself. Extract the “local” (zone-less) values, then apply the intended time zone.
To get the “local” date and time, first convert to OffsetDateTime
object.
OffsetDateTime odt = instantConvertedFromDateOfComponent.atOffset( ZoneOffset.UTC );
LocalDateTime ldt = odt.toLocalDateTime(); // 2016-12-01T09:00:00Z
ZonedDateTime zdt = ldt.atZone( z ); // 2016-12-01T09:00-05:00[America/Montreal]
If your JDBC driver complies with JDBC 4.2 or later, you may be able to pass these java.time types directly. If not, convert to java.sql types via new methods added to the old classes. Discussed already many times on Stack Overflow, so search for more info.
The server’s current default time zone should be irrelevant to your programming. Always specify explicitly the desired/expected time zone in optional arguments rather than rely implicitly on default.
About java.time
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
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
- Java SE 8 and SE 9 and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.