tl;dr
The terrible old date-time classes are quite confusing, especially in their handling of implicit default time zones. But your mystery is moot, as these terrible old classes were supplanted years ago by modern java.time classes.
Instant.now()
.atZone(
ZoneId.of( "America/Montreal" )
)
.format(
DateTimeFormatter.ISO_LOCAL_DATE_TIME
)
.replace( "T" , " " )
2013-01-17 21:01:55
java.time
The issue is moot as the terrible old date-time classes such as SimpleDateFormat
have been supplanted by the java.time.
Current moment
The java.util.Date
class is replaced by java.time.Instant
. Both represent a moment in UTC, always in UTC. (Despite Date::toString
lying to you, in applying the JVM’s current default time zone.)
Instant instant = Instant.now() ;
Adjust into a time zone.
ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Adjust into another time zone.
ZoneId zKolkata = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdtKolkata = instant.atZone( zKolkata ) ;
All three objects (instant
, zdt
, & zdtKolkata
) represent the very same simultaneous moment, the same point on the timeline. Only the wall-clock time is different.
Strings
When generating strings representing date-time values, I recommend always including the offset/zone information unless the context is absolutely crystal-clear. I have seen much confusion in the business world caused by reports where the time frame was ambiguous.
But if you insist, either define your own formatting pattern with DateTimeFormatter
class, or use the given formatter ISO_LOCAL_DATE_TIME
and replace the T
in the middle with a SPACE.
DateTimeFormatter f = DateTimeFormatter.ISO_LOCAL_DATE_TIME ;
String output = zdt.format( f ) ;
2013-01-17 21:01:55
Unzoned date-time
Part of the problem is the ambiguity of your string 2013-01-17 21:01:55
. That string lacks any indicator of time zone or offset-from-UTC. Such a value is not a moment, is not a point on the timeline. For example, 9 PM in India comes several hours sooner than 9 PM in Québec. Without a zone or offset, that string represents only potential moments along a range of about 26-27 hours, the range of time zones around the globe.
The legacy classes had no such class to represent this kind of value. In the modern classes, we have LocalDateTime
for this purpose, a non-moment, date and time-of-day without zone/offset.
The java.time classes use ISO 8601 standard formats by default when parsing/generating strings. Your input nearly complies. We need only replace the SPACE in the middle with a T
.
LocalDateTime ldt = LocalDateTime.parse( "2013-01-17 21:01:55".replace( "" , "T" ) ) ;
If you know for a fact that the intent behind that string was to represent a moment in a particular time zone, apply a ZoneId
to get a ZonedDateTime
. For example, if you are certain it represents a moment on most of the west coast of North America, use America/Los_Angeles
.
ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
To adjust from that zone to UTC, extract a Instant
object. The Instant
class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = zdt.toInstant() ; // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.
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.
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.
Where to obtain the java.time classes?
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.
java.util.Date
,java.util.Calendar
, andjava.text.SimpleDateFormat
are now legacy, supplanted by the java.time classes built into Java 8 and later. See Tutorial by Oracle. – Basil Bourque