I am receiving DateTime
as a String
from a webservice. An example of this DateTime
string is: "DateTime":"2021-06-06T04:54:41-04:00"
.
This 2021-06-06T04:54:41-04:00
more or less matches the ISO-8601 format, so I have used this pattern to parse it: yyyy-MM-dd'T'HH:mm:ssZ
. However, the colon in the timezone part of the response DateTime is causing issues. 2021-06-06T04:54:41-04:00
is giving parse exception, but 2021-06-06T04:54:41-0400
is parsing fine.
Below code should explain it better:
public void stringToDate() {
String pattern = "yyyy-MM-dd'T'HH:mm:ssZ"; //ISO - 8601 Format
TimeZone timeZoneEST = TimeZone.getTimeZone("US/Eastern");
SimpleDateFormat sdf = new SimpleDateFormat(pattern, new Locale("en", "US"));
sdf.setLenient(false);
sdf.setTimeZone(timeZoneEST);
String timeFromWebService = "2021-06-06T04:54:41-04:00";
try {
Date parsedDate = sdf.parse(timeFromWebService); // not working because of colon in timezone part
System.out.println(parsedDate);
} catch (ParseException e) {
e.printStackTrace();
}
try {
Thread.sleep(1000); //sleep to avoid interleaving output from stacktrace (above) and syso (below)
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
String timeFromWebServiceModified = "2021-06-06T04:54:41-0400"; //removed colon from timezone part
try {
Date parsedDate = sdf.parse(timeFromWebServiceModified); // working because colon is removed in timezone part
System.out.println(parsedDate);
} catch (ParseException e) {
e.printStackTrace();
}
}
I want to handle this parsing without modifying the response DateTime
. Any suggestions on how I can parse the original DateTime
. Any suggestion on what pattern to use will be very help full.
The java.util
Date-Time API and their formatting API, SimpleDateFormat
are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Solution using java.time
, the modern API:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("u-M-d'T'H:m:s[XXX][XX][X]", Locale.ENGLISH);
//Test
Stream.of(
"2021-06-06T04:54:41-04:00",
"2021-06-06T04:54:41-0400",
"2021-06-06T04:54:41-04",
"2021-06-06T04:54:41Z"
).forEach(s -> System.out.println(OffsetDateTime.parse(s, dtf)));
}
}
Output:
2021-06-06T04:54:41-04:00
2021-06-06T04:54:41-04:00
2021-06-06T04:54:41-04:00
2021-06-06T04:54:41Z
Check How to use OffsetDateTime
in JDBC?.
Learn more about java.time
, the modern Date-Time API* from Trail: Date Time.
Solution using legacy API:
SimpleDateFormat
does not have a feature to specify optional patterns, the way we do, using the square bracket, with DateTimeFormatter
. In this case, you can create multiple instances of SimpleDateFormat
and try with each one.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
SimpleDateFormat sfdArr[] = {
new SimpleDateFormat("y-M-d'T'H:m:sXXX", Locale.ENGLISH),
new SimpleDateFormat("y-M-d'T'H:m:sXX", Locale.ENGLISH),
new SimpleDateFormat("y-M-d'T'H:m:sX", Locale.ENGLISH)
};
String []strDateTimeArr = {
"2021-06-06T04:54:41-04:00",
"2021-06-06T04:54:41-0400",
"2021-06-06T04:54:41-04",
"2021-06-06T04:54:41Z"
};
for(String s : strDateTimeArr) {
Date date = null;
for(SimpleDateFormat sdf : sfdArr) {
try {
date = sdf.parse(s);
}catch(ParseException e) {
//...
}
}
System.out.println(date);
}
}
}
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.