Specify Time Zone
Two different JVMs, each with its own (different) current default time zone. Each used its own current default time zone during parsing of the string to interpret the meaning of the input data.
Solution: Always specify the desired/expected time zone.
The JVM’s current default time zone can be initialized in various ways. And the current default time zone can be changed during runtime by any code in any thread of any app within the JVM. So never depend on this externality of time zone.
Specify a proper time zone name, in format of continent/region
. Never use the 3-4 letter abbreviations such as EDT
, IST
, CST
, etc. These are not true time zones, are not standardized, and are not unique(!).
Specify Locale
Same goes for Locale
, used in parsing name of day & month, determining comma vs period, and such. The JVM’s current default Locale
is out of your control. So always specify the desired/expected Locale
appropriate to the context of your input data.
java.time
You are using old date-time classes that have proven to be poorly designed, confusing, and troublesome. Avoid them.
The java.time classes are built into Java 8 and later. Much of their functionality has been back-ported to Java 6 & 7 in the ThreeTen-Backport project, and further adapted to Android in the ThreeTenABP project.
The java.time classes are the successor to the highly successful Joda-Time library, both projects led by the same man, Stephen Colbourne. The java.time classes supplant the notoriously troublesome old date-time classes bundled with the earliest versions of Java.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
Locale locale = Locale.CANADA_FRENCH ;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MMM dd, yyyy h:mm:ss a" );
formatter = formatter.withLocale( locale );
formatter = formatter.withZone( zoneId );
ZonedDateTime zdt = ZonedDateTime.parse( input , formatter );
We often want to work with values in UTC. For this, use Instant
, a moment on the timeline in UTC with a resolution of nanosecond.
Instant instant = zdt.toInstant();
Convert
If you must have one of the old types, use new methods added to the old date-time classes to convert to/from java.time.
java.util.Date utilDate = java.util.Date.from( instant );
java.util.Calendar utilCal = java.util.GregorianCalendar.from( zdt );