Reputation: 23576
I have a string with the format: String dateString = "2014-03-17T20:05:49.2300963Z"
Trying this:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'kk:mm:ss.SSSX");
Date date = df.parse(dateString);
Results in an Unparsable date
exceptioon.
The docs: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html indicate that X
is used with ISO 8601
when a single letter is used for the TimeZone.
EDIT
Re-reading the docs, I've switched up the SimpleDateFormat
a little:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
dateString = dateString.replace("Z", "");
I take out the Z
because I know the timezone, use H
instead of k
and add a couple more S
for giggles.
Now the time is parsing, but incorrectly. Date is accurate, Time seems to be random.
EDIT 2
The problem is that java only allows millisecond accuracy, so 2300963
is being interpreted as 2300 seconds and 963 milliseconds. I'll need to format my string a little differently to get this to work.
EDIT 3 Turns out you can't have a fractional part of a second in Java. It has to be truncated to milliseconds. I ended up using a type made available to me by my database, but the general solution is to truncate the fractional part of the second to millisecond. I'll post example code of how to do that as an answer.
Upvotes: 2
Views: 421
Reputation: 339303
Instant.parse( "2014-03-17T20:05:49.2300963Z" )
You are using the troublesome old date-time classes, now legacy, supplanted by the java.time classes.
The ISO 8601 standard defines string formats to represent date-time values. You input complies with ISO 8601.
The java.time classes use ISO 8601 formats by default when parsing and generating strings. So no need to specify a formatting pattern.
Instant instant =
Instant.parse( "2014-03-17T20:05:49.2300963Z" );
Upvotes: 0
Reputation: 23576
How to truncate the fractional seconds to milliseconds (because Java can't handle fractional seconds):
public String truncate(String dateString){
int numberOfDigits = dateString.substring(dateString.indexOf("."), dateString.length() - 1).length();
String justMilliSecondsDate = null;
if (numberOfDigits == 3) {
justMicrosDate = dateString;
}
else if (numberOfDigits > 3) {
justMilliSecondsDate = dateString.substring(0, dateString.length() - numberOfDigits + 3);
}
else {
justMilliSecondsDate = dateString;
for (int i = numberOfDigits ; i < 3 ; i++) justMilliSecondsDate += "0";
}
return justMilliSecondsDate;
}
Upvotes: 0
Reputation: 3181
This works: SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'kk:mm:ss.SSSSSSS'Z'");
S
.X
will parse a timezone of the sort -0800
. So your string would have to look like 2014-03-17T20:05:49.2300963-0800
(or something similar). Treat the Z
as a literal, like T
.EDIT: Relevant to your partial seconds issue.
Upvotes: 1
Reputation: 280092
You need to provide as many S
as you have in your date String
. In this case, 7
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'kk:mm:ss.SSSSSSSX");
This is required because, otherwise, the DateFormat
doesn't know where the milliseconds end and where the time zone starts.
Note also, that
2300963
as a millisecond value means 2300 seconds and 963 milliseconds. Why do you have it that way? Why aren't those seconds part of the value in their corresponding position? When the DateFormat
parses it, they will be added.
Upvotes: 4