Reputation: 465
I am trying to parse a date 2014-12-03T10:05:59.5646+08:00
using these two formats:
yyyy-MM-dd'T'HH:mm:ss
yyyy-MM-dd'T'HH:mm:ssXXX
When I parse using yyyy-MM-dd'T'HH:mm:ss
it works fine, but when I parse yyyy-MM-dd'T'HH:mm:ssXXX
a ParseException
is thrown.
Which is the correct format to parse the date and also what exactly is the difference between these two formats?
Note : I cannot use Joda :(
Upvotes: 10
Views: 93684
Reputation: 1
so I wrote the code myself
First by Creating a Data Class to store
Data class TimeAndDate(
val day : String,
val month : String,
val year : String,
val hours : String,
val minutes : String
)
Now for converting the String
//for the type of yyyy-MM-dd'T'HH:mm:ss.SSS
// Here timeStamp is a String in the above format
fun timeAndDateConverter(timeStamp: String): TimeAndDate {
val day = timeStamp.subSequence(8, 10).toString()
val year = timeStamp.subSequence(2, 4).toString()
var month = timeStamp.subSequence(5, 7).toString()
when (month) {
"01" -> month = "Jan"
"02" -> month = "Feb"
"03" -> month = "Mar"
"04" -> month = "Apr"
"05" -> month = "May"
"06" -> month = "Jun"
"07" -> month = "Jul"
"08" -> month = "Aug"
"09" -> month = "Sep"
"10" -> month = "Oct"
"11" -> month = "Nov"
"12" -> month = "Dec"
}
val hours = timeStamp.subSequence(11, 13).toString()
val minutes = timeStamp.subSequence(14, 16).toString()
return TimeAndDate(
day = day,
month = month,
year = year,
hours = hours,
minutes = minutes
)
}
This function will return the data class from where we can get all individual elements
Upvotes: 0
Reputation: 79015
When I parse using
yyyy-MM-dd'T'HH:mm:ss
it works fine, but when I parseyyyy-MM-dd'T'HH:mm:ssXXX
aParseException
is thrown.Which is the correct format to parse the date and also what exactly is the difference between these two formats?
yyyy-MM-dd'T'HH:mm:ss
:Check the following line (emphasis mine) from the documentation:
Parses text from the beginning of the given string to produce a date. The method may not use the entire text of the given string.
So, basically, the format, yyyy-MM-dd'T'HH:mm:ss
is considering only up to 2014-12-03T10:05:59
and ignoring the fraction of second and timezone offset information.
yyyy-MM-dd'T'HH:mm:ssXXX
?In this format, you have put the symbol for timezone offset correctly but missed the symbols for fraction of a second.
SimpleDateFormat
?The short answer: None
Long answer: SimpleDateFormat
can not handle a precision beyond milliseconds (i.e. 3 digits after .
) correctly and therefore none of the formats can parse it correctly. The only way to get it correct is by keeping the digits after .
up to three digits e.g. 2014-12-03T10:05:59.564+08:00
, 2014-12-03T10:05:59.56+08:00
etc. Let's see how SimpleDateFormat
will parse 2014-12-03T10:05:59.5646+08:00
erroneously.
SimpleDateFormat
considers the digits after .
as the number of milliseconds (instead of fraction of a second, the way the modern date-time API considers). Thus, the calculation goes like this:
5646 milliseconds = 5 seconds + 646 milliseconds
2014-12-03T10:05:59 + 5 seconds + 646 milliseconds = 2014-12-03T10:06:04.646
Let's validate it using the code:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
String strDateTime = "2014-12-03T10:05:59.5646+08:00";
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
Date date = sdf.parse(strDateTime);
sdf.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
System.out.println(sdf.format(date));
}
}
Output:
2014-12-03T10:06:04.646+08:00
With the release of Java SE 8 in March 2014, the outdated and error-prone legacy Date-Time API (java.util
Date-Time types and their formatting type, SimpleDateFormat
etc.) was supplanted by java.time
, the modern Date-Time API*. It is strongly recommended to stop using the legacy API and switch to this new API.
Solution using java.time
, the modern API:
import java.time.OffsetDateTime;
public class Main {
public static void main(String[] args) {
OffsetDateTime odt = OffsetDateTime.parse("2014-12-03T10:05:59.5646+08:00");
System.out.println(odt);
}
}
Output:
2014-12-03T10:05:59.564600+08:00
The modern Date-Time API is based on ISO 8601 and does not require using a DateTimeFormatter
object explicitly as long as the Date-Time string conforms to the ISO 8601 standards.
By the way, for any reason, if you need to convert this object of OffsetDateTime
to an object of java.util.Date
, you can do so as follows:
Date date = Date.from(odt.toInstant());
Learn more about java.time
, the modern Date-Time API* from Trail: Date Time.
* 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.
Upvotes: 0
Reputation: 26961
use this format yyyy-MM-dd'T'HH:mm:ss.SSSSX
From SimpleDateFormat
API
//Letter Date or Time Component Presentation Example
S Millisecond Number 978
X Time zone ISO 8601 time zone -08; -0800; -08:00
USE:
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSX");
String date = "2014-12-03T10:05:59.5646+08:00";
System.out.println(format.parse(date));
OUTPUT:
Wed Dec 03 03:06:04 CET 2014
Upvotes: 8
Reputation: 972
Those are valid formats:
yyyy-MM-dd'T'HH:mm:ss.SSSZ >>> e.g.: 2001-07-04T12:08:56.235-0700
yyyy-MM-dd'T'HH:mm:ss.SSSXXX >>> e.g.: 2001-07-04T12:08:56.235-07:00
Edit:
BTW, "X" refer to the (ISO 8601 time zone)
Upvotes: 7