tl;dr
DateTimeFormatter f = new DateTimeFormatterBuilder ().parseCaseInsensitive ().appendPattern ( "dd-MMM-yy hh.mm.ss.SSSSSSSSS a ZZZZZ" ).toFormatter ().withLocale ( Locale.US );
OffsetDateTime odt = OffsetDateTime.parse ( "03-AUG-12 08.15.00.000000000 PM -05:00" , f );
Objects, not strings
You mentioned Oracle. When retrieving data from a database, use objects rather than strings. Ask your ResultSet
for a java.sql.Timestamp
object.
java.sql.Timestamp ts = myResultSet.getTimestamp( … );
Convert from the troublesome old date-time class to the modern java.time type. Look to new methods added on the old classes to facilitate conversion to/from java.time.
Instant instant = ts.toInstant();
Or preferably, if using JDBC 4.2 or later, and using Java 8 or later, you may be able to retrieve an java.time.Instant
via the ResultSet::getObject
method.
But if you must parse a string, read on.
Avoid old date-time classes
The old date-time classes bundled with the earliest versions of Java are troublesome and confusing. Now supplanted by the java.time classes.
Nanoseconds
That bunch of zeros must represent a fraction of a second with nanosecond resolution, up to nine digits of a decimal fraction. The old date-time classes can handle only milliseconds, but fortunately the modern java.time classes can indeed handle a resolution up to nanoseconds.
Using java.time
Define a formatting pattern to parse the given input. By the way, your data’s format is less than optimal; in the future, use ISO 8601 standard formats for strings that represent date-time values.
We use a “builder” in order to specify case-insensitive parsing. Proper abbreviation for a name of month in English is initial-cap, Aug
, but your input uses all-caps.
String pattern = "dd-MMM-yy hh.mm.ss.SSSSSSSSS a ZZZZZ";
DateTimeFormatterBuilder fb = new DateTimeFormatterBuilder ().parseCaseInsensitive ().appendPattern ( pattern );
Tell the builder to instantiate our formatter. The Locale
to determines (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, and such.
Locale l = Locale.US;
DateTimeFormatter f = fb.toFormatter ().withLocale ( l );
Finally, parse the string as an OffsetDateTime
object.
String input = "03-AUG-12 08.15.00.000000000 PM -05:00";
OffsetDateTime odt = OffsetDateTime.parse ( input , f );
Dump to console. Note how our 8 PM is transformed into the 24-hour clock value of 20 hours.
System.out.println ( "input: " + input + " | odt.toString(): " + odt );
input: 03-AUG-12 08.15.00.000000000 PM -05:00 | odt.toString(): 2012-08-03T20:15-05:00
A time zone is an offset-from-UTC plus a set of rules for handling anomalies such as Daylight Saving Time (DST). If desired, apply a ZoneId
to get a ZonedDateTime
.
ZoneId z = ZoneId.of( “America/Montreal” );
ZonedDateTime zdt = odt.atZoneSameInstant( z );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).
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.