Converting a ldap date
What about using the split you described above, then reformatting the 0Z
timezone into a standard format, then using sdf.parse(...)
? Maybe something like this (with appropriate error checking added, of course):
String[] parts = inputDateTime.split("[.]");
String dateTimePart = parts[0];
String timeZonePart = "+0" + parts[1].substring(0, parts[1].length() - 1) + "00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssZ");
Date theDate = sdf.parse(dateTimePart + timeZonePart);
Checking the RFC mentioned above it seems like using UTC is the recommended default behavior for ldap dates. Therefor I converted it directly:
public Date parseLdapDate(String ldapDate){
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
try {
return sdf.parse(ldapDate);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
You can use the methods of org.apache.directory.shared.ldap.util.DateUtils:
String ldapDate="20090813145607.0Z";
Date date = DateUtils.parse(ldapDate);
String generalizedTime = DateUtils.getGeneralizedTime(date);
ISO 8601
As a couple of other Answers mentioned, the date-time format in question is defined by RFC 4517 Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching Rules. See section 3.3.13, Generalized Time.
That section explains this LDAP format is a restricted version of one of the date-time formats defined by ISO 8601. This style using a minimum of separators is known as “basic” in ISO 8601.
In these formats, the Z
on the end is short for Zulu
and means UTC (basically same as GMT).
The decimal point and digit at the end represents a fraction of a second. Note that a comma is possible instead of the dot (period) in both RFC 4517 and ISO 8601. The comma is actually recommended over the dot in ISO 8601. The RFC 4517 spec allows for only a single digit fraction (some tenths of a fraction) or no dot/comma & digit at all. Note that in contrast: (a) ISO 8601 allows for any number of fractional digits, and (b) java.time objects have nanosecond resolution for up to nine digits of fractional second.
java.time
The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date
, .Calendar
, & java.text.SimpleDateFormat
.
Now in maintenance mode, the Joda-Time project also 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.
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time.
Parsing
Define a formatting pattern to fit RFC 4517. Study the DateTimeFormatter
class for the pattern coding. This should work: uuuuMMddHHmmss[,S][.S]X
. The square brackets mean optional. We accommodate either a dot or comma. Note the singular digit for fraction of second. The X
on the end allows for either a Z
or an offset-from-UTC such as -08 or -0830 or -08:30 or -083015 or -08:30:15.
String input = "20090813145607.0Z";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "uuuuMMddHHmmss[,S][.S]X" );
OffsetDateTime odt = OffsetDateTime.parse ( input , f );
Instant instant = odt.toInstant ();
Dump to console.
System.out.println ( "input: " + input + " | odt: " + odt + " | instant: " + instant );
input: 20090813145607.0Z | odt: 2009-08-13T14:56:07Z | instant: 2009-08-13T14:56:07Z
Of course you should also be coding a check for java.time.format.DateTimeParseException
in case of unexpected input.