Converting a time String to ISO 8601 format
Solution 1
tl;dr
Instant.parse( "2015-08-20T08:26:21.000Z" )
.toString()
2015-08-20T08:26:21Z
Date-Time Formatter
If all you want to do is eliminate the .000
, then use date-time objects to parse your input string value, then generate a new string representation of that date-time value in a different format.
ISO 8601
By the way, if that is your goal, the Question’s title make no sense as both strings mentioned in the first sentence are valid ISO 8601 formatted strings.
2015-08-20T08:26:21.000Z
2015-08-20T08:26:21Z
java.time
Java 8 and later has the new java.time package. These new classes supplant the old java.util.Date/.Calendar & java.text.SimpleDateFormat classes. Those old classes were confusing, troublesome, and flawed.
Instant
If all you want is UTC time zone, then you can use the Instant
class. This class represents a point along the timeline without regard to any particular time zone (basically UTC).
DateTimeFormatter.ISO_INSTANT
Calling an Instant’s toString
generates a String representation of the date-time value using a DateTimeFormatter.ISO_INSTANT
formatter instance. This formatter is automatically flexible about the fractional second. If the value has a whole second, no decimal places are generated (apparently what the Question wants). For a fractional second, digits appear in groups of 3, 6, or 9, as needed to represent the value up to nanosecond resolution. Note: this format may exceed ISO 8601 limit of milliseconds (3 decimal places).
Example code
Here is some example code in Java 8 Update 51.
String output = Instant.parse( "2015-08-20T08:26:21.000Z" ).toString( );
System.out.println("output: " + output );
output: 2015-08-20T08:26:21Z
Changing to a fractional second, .08
String output = Instant.parse( "2015-08-20T08:26:21.08Z" ).toString( );
output: 2015-08-20T08:26:21.080Z
If interested in any time zone other than UTC, then make a ZonedDateTime
object from that Instant
.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , ZoneId.of( "America/Montreal" ) ) ;
Solution 2
Your format is just not right try this :-
try {
String s = "2015-08-20T08:26:21.000Z";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
Date d = df.parse(s);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
System.out.println(sdf.format(d));
} catch (ParseException e) {
e.printStackTrace();
}
Solution 3
Conversion of a date String
of unknown formatting into a date String
that uses known formatting can be accomplished using two DateFormat
objects- one dynamically configured to parse the format of the input String
, and one configured to generate the formatted output String
. For your situation the input String
formatting is unspecified and must be provided by the caller, however, the output String
formatting can be configured to use ISO 8601 formatting without additional input. Essentially, generating an ISO 8601 formatted date String
output requires two inputs provided by the caller- a String
containing the formatted date and another String
that contains the SimpleDateFormat
format.
Here is the described conversion as Java code (I deliberately have left out null checks and validations, add these as appropriate for your code):
private String formatDateAsIso8601(final String inputDateAsString, final String inputStringFormat) throws ParseException {
final DateFormat iso8601DateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'", Locale.ENGLISH);
iso8601DateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
final DateFormat inputDateFormatter = new SimpleDateFormat(inputStringFormat, Locale.ENGLISH);
final Date inputDate = inputDateFormatter.parse(inputDateAsString);
return iso8601DateFormatter.format(inputDate);
}
If you want to modify that method please note that SimpleDateFormat
is not thread-safe, and that you should not use it from a static context without a workaround for multi-threaded code (ThreadLocal
is commonly used to do just such a workaround for SimpleDateFormat
).
An additional "gotcha" is the use of a Locale
during the construction of the SimpleDateFormat
objects- do not remove the Locale
configuration. It is not safe to allow the system to choose to use the default Locale
because that is user/machine specific. If you do allow it to use the default Locale
, you run the risk of transient bugs because your development machine uses a Locale
different than the Locale
of your end-user. You do not have to use my selected ENGLISH Locale
, it is perfectly fine to use a different Locale (you should understand the rules of that Locale
and modify the code as appropriate however). Specification of no Locale
and utilization of the system default is incorrect however, and likely will lead to many frustrating hours trying to diagnose an elusive bug.
Please understand this solution is not ideal as of Java 8 and the inclusion of the JodaTime based classes, like Instant
. I chose to answer using the outdated API's because those were what you seemed concerned with in your question. If you are using Java 8 I strongly urge to learn and utilize the new classes as they are an improvement in almost every conceivable way.
CodeMonkey
Updated on July 09, 2022Comments
-
CodeMonkey almost 2 years
I am trying to create a String in a format like 2015-08-20T08:26:21.000Z
to 2015-08-20T08:26:21ZI know it can be done with some String splitting techniques, but i am wondering if there is an elegant solution for that (with minimal code changes).
Both of the above are time strings, the final one which i need is Date in ISO 8601 . https://www.rfc-editor.org/rfc/rfc3339#section-5.6
I have tried a few similar questions like converting a date string into milliseconds in java but they dont actually solve the purpose.
Also tried using :
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ"); String nowAsString = df.format(new Date());
But it still does not do any String to String conversions. Getting the following error:
23:04:13,829 WARN [RuntimeExceptionMapper] caught RuntimeException: {}: java.lang.IllegalArgumentException: Cannot format given Object as a Date
Is there some library which someone can suggest ?
Thanks.