tl;dr
LocalDateTime
.parse(
"20190310022817" ,
DateTimeFormatter.ofPattern( "uuuuMMddHHmmss" )
)
.atZone(
ZoneId.of( "America/Montreal" )
)
Result is 3 AM rather than 2 AM. Feature, not a bug, adjusting for DST.
2019-03-10T03:28:17-04:00[America/Montreal]
If your goal is to reject such invalid inputs rather than adjust them, see my Answer an another Question that explains the ResolverStyle
enum: LENIENT
, SMART
, & STRICT
.
Avoid legacy date-time classes
You are using terrible date-time classes that were supplanted years ago by the modern java.time classes.
Daylight Saving Time (DST)
As pointed out in the Answer by rgettman, some jurisdictions crazy enough to participate in Daylight Saving Time (DST) were doing their “Spring-ahead” jump on your given date of March 10 at the 2 AM hour. This was happening in most of the US & Canada, and maybe elsewhere. See Wikipedia about DST in the United States.
In these locations, there is no 2 AM hour. When the clock strikes 2 AM, the clock jumps instantly to 3 AM. The two o’clock hour never existed.
By the way, DST is not the only scheme by which the clock changes. Politicians around the world have shown a penchant for messing with the offset-from-UTC in their jurisdiction. For example, see North Korea, Venezuela, Turkey, and Russia in recent years. And now some states with the US are in the process of choosing to stop the DST nonsense, though some are thinking of staying on DST permanently. The point is, for robust handling of date-times, regardless of current practice you should always assume politicians will make a change at some point in the future, and code accordingly.
Your input was invalid (likely)
The legacy class you used was likely rejecting your input as invalid given the DST jump in your JVM’s current default time zone that was implicitly applied since you did not indicate a zone. This strict protocol in parsing for a valid value is not wrong, just one approach in dealing with invalid input.
The ZonedDateTime
class uses another approach by default, making an adjustment as it sees fit.
ZonedDateTime
The java.time.ZonedDateTime
class knows the time zone’s history of past, present, and future changes to the offset-from-UTC used by the people of a particular region. So that class will adjust automatically. Be sure to read the class documentation so you know and agree to its adjustment protocol.
LocalDateTime
Here is some example code. First we parse your input as a LocalDateTime
, because your input lacks any indication of time zone or offset-from-UTC. As such, a LocalDateTime
does not represent a moment, is not a point on the timeline. So if a time zone is known to have been intended for that date and time-of-day, we can apply a ZoneId
to get a ZonedDateTime
.
Here in this example we arbitrarily choose two zones to apply, so you can see the differing results. In the US, March 10 was the day of the DST jump. In much of Europe such as France, the jump is scheduled for later, on the last day of March. So 2 AM is a valid time in France but not in the US.
String input = "20190310022817";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMddHHmmss" ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
ZoneId zParis = ZoneId.of( "Europe/Paris" ) ;
ZonedDateTime zdtParis = ldt.atZone( zParis ) ;
ZoneId zNewYork = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdtNewYork = ldt.atZone( zNewYork ) ;
Dump to console.
System.out.println( "ldt.toString(): " + ldt ) ;
System.out.println( "zdtParis.toString(): " + zdtParis ) ;
System.out.println( "zdtNewYork.toString(): " + zdtNewYork ) ;
When run. See this code run live at IdeOne.com. Notice the hour on each of these three outputs:
- 2 AM in the first two
- 3 AM in the last one
ldt.toString(): 2019-03-10T02:28:17
zdtParis.toString(): 2019-03-10T02:28:17+01:00[Europe/Paris]
zdtNewYork.toString(): 2019-03-10T03:28:17-04:00[America/New_York]

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
.
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.
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.