Skip to content

Instantly share code, notes, and snippets.

@VincentMasselis
Last active May 31, 2021 09:49
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save VincentMasselis/9912b4be4d952eaa9265 to your computer and use it in GitHub Desktop.
Save VincentMasselis/9912b4be4d952eaa9265 to your computer and use it in GitHub Desktop.
Simple Java 7 RFC3339 parser (Android compatible)
/*
Inspired by http://cokere.com/RFC3339Date.txt
All rights deserve to Chad Okere
*/
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class DateUtil {
/*
Values tested :
"2007-05-01T15:43:26+07:00"
"2007-05-01T15:43:26.3+07:00"
"2007-05-01T15:43:26.3452+07:00"
"2007-05-01T15:43:26-07:00"
"2007-05-01T15:43:26.3-07:00"
"2007-05-01T15:43:26.3452-07:00"
"2007-05-01T15:43:26.3452Z"
"2007-05-01T15:43:26.3Z"
"2007-05-01T15:43:26Z"
*/
public synchronized static Date parseRFC3339Date(String dateString) throws java.text.ParseException, IndexOutOfBoundsException {
Date d;
//if there is no time zone, we don't need to do any special parsing.
if (dateString.endsWith("Z")) {
try {
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault());//spec for RFC3339 with a 'Z'
s.setTimeZone(TimeZone.getTimeZone("UTC"));
d = s.parse(dateString);
} catch (java.text.ParseException pe) {//try again with optional decimals
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'", Locale.getDefault());//spec for RFC3339 with a 'Z' and fractional seconds
s.setTimeZone(TimeZone.getTimeZone("UTC"));
s.setLenient(true);
d = s.parse(dateString);
}
return d;
}
//step one, split off the timezone.
String firstPart;
String secondPart;
if (dateString.lastIndexOf('+') == -1) {
firstPart = dateString.substring(0, dateString.lastIndexOf('-'));
secondPart = dateString.substring(dateString.lastIndexOf('-'));
} else {
firstPart = dateString.substring(0, dateString.lastIndexOf('+'));
secondPart = dateString.substring(dateString.lastIndexOf('+'));
}
//step two, remove the colon from the timezone offset
secondPart = secondPart.substring(0, secondPart.indexOf(':')) + secondPart.substring(secondPart.indexOf(':') + 1);
dateString = firstPart + secondPart;
SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.getDefault());//spec for RFC3339
try {
d = s.parse(dateString);
} catch (java.text.ParseException pe) {//try again with optional decimals
s = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ", Locale.getDefault());//spec for RFC3339 (with fractional seconds)
s.setLenient(true);
d = s.parse(dateString);
}
return d;
}
}
@liminal
Copy link

liminal commented Mar 13, 2016

This breaks in line 32 on date strings with a positive timezone offset which is perfectly valid according to RFC 3339.

Eg. 2016-03-13T17:20:24+00:00

@VincentMasselis
Copy link
Author

@liminal I've updated the gist to support + time zones.
Thanks.

@VincentMasselis
Copy link
Author

Test results : http://ideone.com/DW4vDg

@thermosym
Copy link

For Java8, can directly use java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME

@trietbui85
Copy link

Thank you for the code snippet. It's really helpful.
Would you consider a Kotlin version?

@VincentMasselis
Copy link
Author

@anticafe Sorry but I'm no longer using this snippet since I'm working on other projects

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment