I have to create the XMLGregorianCalendar object with this date format "YYYY-MM-DDTHH:MI:SS±TZ" e.g. "2015-07-01T17:42:49+04"
I have no idea how to do this. I've used a number of ways on how to convert date, but this pattern doesn't seem to work.
After some experiments I found that "YYYY-MM-dd'T'HH:mm:ssX" will give me the desired output. But it's a string and I can't achieve the same format with XMLGregorianCalendar.
It gives me "2015-07-01T17:42:4234+05:00", as you see there're additional symbols that i don't need.
Date-time objects have no format
XMLGregorianCalendar object with this date format
Date-time objects such as XMLGregorianCalendar do not have a “format”. They internally represent the date-time value in some manner, though not likely to be in text.
You can instantiate date-time objects by parsing text. And your date-time objects can generate text representing their internal value. But the text and the date-time object are distinct and separate from one another.
java.time
The XMLGregorianCalendar class is now obsolete. Supplanted by the modern java.time classes defined in JSR 310.
Parse your input string as a OffsetDateTime as in includes an offset-from-UTC but not a time zone.
OffsetDateTime odt = OffsetDateTime.parse( "2015-07-01T17:42:49+04" );
Generate text in standard ISO 8601 format.
String output = odt.toString() ; // Generates text in ISO 8601 format.
2015-07-01T17:42:49+04:00
Parts of an offset
The part at the end is the offset-from-UTC, a number of hours-minutes-seconds ahead or behind the prime meridian. In ISO 8601, the Plus sign is a positive number that means ahead of UTC. A Minus sign is a negative number that means behind UTC.
Suppressing parts of an offset
Some people may drop the seconds when zero, or drop the minutes when zero. But suppressing those digits does not change the meaning. These three strings all represent the very same moment:
2015-07-01T17:42:49+04
2015-07-01T17:42:49+04:00
2015-07-01T17:42:49+04:00:00
You said:
"2015-07-01T17:42:4234+05:00", as you see there're additional symbols that i don't need.
[I assume you really meant "2015-07-01T17:42:49+04:00" but made typos.]
You really should not care about this. Indeed, I recommend you always include both the hours and the minutes as I have seen multiple libraries/protocols that expect both hours and minutes, breaking if omitted. While the minutes and seconds are indeed optional in ISO 8601 when their value is zero, I suggest you always include the minutes when zero.
DateTimeFormatter
If you insist otherwise, you will need to use DateTimeFormatter class, and possibly DateTimeFormatterBuilder, to suppress the minutes when zero. Perhaps this:
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssx" );
String output = odt.format( f );
2015-07-01T17:42:49+04
The x code in that formatting pattern suppressed the minutes, and seconds, if their value is zero.
If doing your own formatting, be sure to not truncate when non-zero, or your result will be a falsehood (a different moment). Take for example, representing this moment as seen in India where current the offset in use is five and half hours (an offset that includes 30 minutes rather than zero).
ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );
OffsetDateTime odtKolkata = zdt.toOffsetDateTime();
Dump to console.
System.out.println( "odtKolkata = " + odtKolkata );
2015-07-01T19:12:49+05:30
XMLGregorianCalendar
If you absolutely must use the old legacy class XMLGregorianCalendar, you can create one from the ISO 8601 output of our OffsetDateTime object seen in code above. See this Answer on another Question.
XMLGregorianCalendar xgc = null;
try
{
xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar( odt.toString() );
}
catch ( DatatypeConfigurationException e )
{
e.printStackTrace();
}
System.out.println( "xgc.toString(): " + xgc );
xgc.toString(): 2015-07-01T17:42:49+04:00
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
Related
I'm a little bit frustrated of java 8 date format/parse functionality. I was trying to find Jackson configuration and DateTimeFormatter to parse "2018-02-13T10:20:12.120+0000" string to any Java 8 date, and didn't find it.
This is java.util.Date example which works fine:
Date date = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSZZZ")
.parse("2018-02-13T10:20:12.120+0000");
The same format doesn't work with new date time api
ZonedDateTime dateTime = ZonedDateTime.parse("2018-02-13T10:20:12.120+0000",
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'hh:mm:ss.SSSZZZ"));
We should be able to format/parse date in any format suitable for FE UI application. Maybe I misunderstand or mistake something, but I think java.util.Date gives more format flexibility and easier to use.
tl;dr
Until bug is fixed:
OffsetDateTime.parse(
"2018-02-13T10:20:12.120+0000" ,
DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" )
)
When bug is fixed:
OffsetDateTime.parse( "2018-02-13T10:20:12.120+0000" )
Details
You are using the wrong classes.
Avoid the troublesome old legacy classes such as Date, Calendar, and SimpleDateFormat. Now supplanted by the java.time classes.
The ZonedDateTime class you used is good, it is part of java.time. But it is intended for a full time zone. Your input string has merely an offset-from-UTC. A full time zone, in contrast, is a collection of offsets in effect for a region at different points in time, past, present, and future. For example, with Daylight Saving Time (DST) in most of North America, the offsets change twice a year growing smaller in the Spring as we shift clocks forward an hour, and restoring to a longer value in the Autumn when we shift clocks back an hour.
OffsetDateTime
For only an offset rather than a time zone, use the OffsetDateTime class.
Your input string complies with the ISO 8601 standard. The java.time classes use the standard formats by default when parsing/generating strings. So no need to specify a formatting pattern.
OffsetDateTime odt = OffsetDateTime.parse( "2018-02-13T10:20:12.120+0000" );
Well, that should have worked. Unfortunately, there is a bug in Java 8 (at least up through Java 8 Update 121) where that class fails to parse an offset omitting the colon between hours and minutes. So the bug bites on +0000 but not +00:00. So until a fix arrives, you have a choice of two workarounds: (a) a hack, manipulating the input string, or (b) define an explicit formatting pattern.
The hack: Manipulate the input string to insert the colon.
String input = "2018-02-13T10:20:12.120+0000".replace( "+0000" , "+00:00" );
OffsetDateTime odt = OffsetDateTime.parse( input );
DateTimeFormatter
The more robust workaround is to define and pass a formatting pattern in a DateTimeFormatter object.
String input = "2018-02-13T10:20:12.120+0000" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" );
OffsetDateTime odt = OffsetDateTime.parse( input , f );
odt.toString(): 2018-02-13T10:20:12.120Z
By the way, here is a tip: I have found that with many protocols and libraries, your life is easier if your offsets always have the colon, always have both hours and minutes (even if minutes are zero), and always use a padding zero (-05:00 rather than -5).
DateTimeFormatterBuilder
For a more flexible formatter, created via DateTimeFormatterBuilder, see this excellent Answer on a duplicate Question.
Instant
If you want to work with values that are always in UTC (and you should), extract an Instant object.
Instant instant = odt.toInstant();
ZonedDateTime
If you want to view that moment through the lens of some region’s wall-clock time, apply a time zone.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );
See this code run live at IdeOne.com.
All of this has been covered many times in many Answers for many Questions. Please search Stack Overflow thoroughly before posting. You would have discovered many dozens, if not hundreds, of examples.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Short: Not a bug, just your pattern is wrong.
Please use the type OffsetDateTime which is especially designed for time zone offsets and use a pattern this way:
OffsetDateTime odt =
OffsetDateTime.parse(
"2018-02-13T10:20:12.120+0000" ,
DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSZZZ" )
)
Problems in detail:
a) 12-hour-clock versus 24-hour-clock
"h" indicates the hour of AM/PM on a 12-hour-clock but you obviously need "H" for the 24-hour-clock as required by ISO-8601.
b) The form of zero offset
If you want to parse zero offset like "+0000" instead of "Z" (as described in ISO-paper) you should not use the pattern symbol "X" but "ZZZ". Citing the pattern syntax:
Offset Z: This formats the offset based on the number of pattern
letters. One, two or three letters outputs the hour and minute,
without a colon, such as '+0130'. The output will be '+0000' when the
offset is zero.
c) Your input is NOT ISO-8601-compatible therefore no bug in Java
Your assumption that "2018-02-13T10:20:12.120+0000" shall be valid ISO is wrong because you are mixing basic format (in the offset part) and extended format which is explicitly prohibited in ISO-paper (see sections 4.3.2 (example part) and 4.3.3d). Citing ISO-8601:
[...]the expression shall either be completely in basic format, in which
case the minimum number of separators necessary for the required
expression is used, or completely in extended format[...]
The statement of B. Bourque that java.time has a bug is based on the same wrong expectation about ISO-compatibility. And the documentation of let's say ISO_OFFSET_DATE_TIME describes the support of the extended ISO-format only. See also the related JDK issue. Not all ISO-8601-variants are directly supported hence a pattern-based construction of the parser in the right way is okay.
if offset +0000 try this
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" )
LocalDate from =LocalDate.parse("2018-02-13T10:20:12.120+0000",f);
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
1) If I print out a calendar object I get:
java.util.GregorianCalendar[time=1567535353679,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="GMT",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2019,MONTH=8,WEEK_OF_YEAR=36,WEEK_OF_MONTH=1,DAY_OF_MONTH=3,DAY_OF_YEAR=246,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=6,HOUR_OF_DAY=18,MINUTE=29,SECOND=13,MILLISECOND=679,ZONE_OFFSET=0,DST_OFFSET=0]
2) If I print out a Date object I get:
Tue Sep 03 18:29:13 GMT 2019
3) However I am examining the XML generated and I observe this format:
2014-02-28T08:00:00.000Z
Which format am I seeing in the XML ?
Date-time objects have no “format”
How to identify date format?
Date-time objects do not have a “format”. Each class defines its own mechanism for internally storing the date-time value. That mechanism is generally none of our business. The API of the class, the promises made by that class, are all that matters.
You may be conflating the text generated by a date-time object with the date-time object itself. Date-time classes can parse text as part of their instantiation. And date-time classes can generate text to represent their value. But the text and the object are separate and distinct.
Avoid Calendar
If I print out a calendar object I get:
The Calendar::toString method is just a data-dump of many of its internal fields. Meant only for debugging obviously, not useful otherwise.
The Calendar class and its commonly-used subclass GregorianCalendar are both now legacy. They were supplanted years ago by the java.time classes as of the adoption of JSR 310. Never use them. GregorianCalendar was specifically replaced by ZonedDateTime.
Avoid Date
If I print out a Date object I get:
The Date::toString method lies. That method dynamically applies the JVM’s current default time zone while generating text. A java.util.Date actually represents a moment in UTC, not the time zone seen in the result of toString. This anti-feature is one of many reasons to never use Date.
The java.util.Date class was replaced by java.time.Instant, representing a moment in UTC as well but with a finer resolution of nanoseconds versus milliseconds.
ISO 8601
However I am examining the XML generated and I observe this format:
2014-02-28T08:00:00.000Z
The format of that text is defined in the ISO 8601 standard. This standard is wisely designed to represent a variety of date-time values textually for data-exchange. This standard supplants earlier poorly-defined date-time text formats, such as seen in the early email protocols.
The java.time classes use ISO 8601 formats by default when parsing/generating strings.
Current moment in UTC
To capture the current moment in UTC, use Instant.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
Generate text representing that value in standard ISO 8601 format. The Z on the end means UTC, and is pronounced “Zulu”.
2020-01-23T12:34:56.123456Z
Parse such a string.
Instant instant = Instant.parse( "2020-01-23T12:34:56.123456Z" );
Time zone
See that same moment through the wall-clock time used by the people of a particular region, a time zone.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Generate a string in a format that wisely extends the ISO 8601 standard by appending the name of the time zone in square brackets.
String output = zdt.toString() ;
See this code run live at IdeOne.com.
instant.toString(): 2020-01-23T12:34:56.123456Z
zdt.toString(): 2020-01-23T07:34:56.123456-05:00[America/Montreal]
Date-time types in Java
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Which format am I seeing in the XML ?
The XML format is inspired by ISO 8601, as specified by the XML schema documentation.
3.2.7.1 Lexical representation
The ·lexical space· of dateTime consists of finite-length sequences of characters of the form: '-'? yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?
String formatA ="yyyy-MM-dd'T'HH:mm:ss'Z'";
String formatB = "dd/MM/yyyy HH:mm:ss.SSS";
try {
XMLGregorianCalendar gregFmt = DatatypeFactory.newInstance().newXMLGregorianCalendar(new SimpleDateFormat(formatB).format(new Date()));
System.out.println(gregFmt);
} catch (DatatypeConfigurationException e) {
};
I am trying to formate XMLGregorianCalendar date .
The above code formats well for format "yyyy-MM-dd'T'HH:mm:ss'Z'"
But for formatB dd/MM/yyyy HH:mm:ss.SSS it throws error
java.lang.IllegalArgumentException
Do advice on how to fix it. Thank you so much!
log
Exception in thread "main" java.lang.IllegalArgumentException: 23/08/2017 16:13:04.140
at com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl$Parser.parseAndSetYear(XMLGregorianCalendarImpl.java:2887)
at com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl$Parser.parse(XMLGregorianCalendarImpl.java:2773)
at com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl.<init>(XMLGregorianCalendarImpl.java:435)
at com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl.newXMLGregorianCalendar(DatatypeFactoryImpl.java:536)
at test.test.main(test.java:19)
line19 is line 4 , in the above code 'XMLGregorianCalendar gregFmt...'
The format that newXMLGregorianCalendar(string) accept is described in the XML specs and is different from the formatB you are trying to use.
tl;dr
Date-time objects do not have a “format”. They parse & generate String objects representing textually their value.
Use the modern java.time that replaced terrible old classes Date & XMLGregorianCalendar classes.
Example:
myXMLGregorianCalendar // If you must use this class… but try to avoid. Use *java.time* classes instead.
.toGregorianCalendar() // Converting from `javax.xml.datatype.XMLGregorianCalendar` to `java.util.GregorianCalendar`.
.toZonedDateTime() // Converting from `java.util.GregorianCalendar` to `java.time.ZonedDateTime`, from legacy class to modern class.
.format( // Generate a `String` representing the moment stored in our `ZonedDateTime` object.
DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss.SSS" ) // Define a formatting pattern as you desire. Or better, automatically localize by calling `DateTimeFormatter.ofLocalized…` methods.
) // Returns a `String` object, distinct from our `ZonedDateTime` object.
07/07/2018 15:20:14.372
Date-time objects do not have a format
Do not conflate date-time objects with the strings they generate to represent their value. Date-time values, including the classes discussed below, are not a String, do not use text as their internal value, and do not have a “format”. All of them can generate, and parse, strings to represent their date-time value.
java.time
The modern approach uses the java.time classes that supplanted the troublesome old legacy date-time classes such as XMLGregorianCalendar.
The use of java.util.Date should be replaced with java.time.Instant. Both represent a moment in UTC. Instant uses a finer resolution of nanoseconds rather than milliseconds.
You can easily convert between the modern and legacy classes. Notice the new conversion methods added to the old classes, in this case java.util.GregorianCalendar::toZonedDateTime.
First convert from javax.xml.datatype.XMLGregorianCalendar to java.util.GregorianCalendar.
GregorianCalendar gc = myXMLGregorianCalendar.toGregorianCalendar() ;
Now get out of these legacy classes, and into java.time.
ZonedDateTime zdt = gc.toZonedDateTime() ;
All three types so far, the XMLGregorianCalendar, the GregorianCalendar, and the ZonedDateTime all represent the same moment, a date with time-of-day and an assigned time zone.
With a ZonedDateTime in hand, you can generate a String in standard ISO 8601 format extended to append the name of the time zone in square brackets.
String output = zdt.toString() ; // Generate string in standard ISO 8601 format extended by appending the name of time zone in square brackets.
2018-07-07T15:20:14.372-07:00[America/Los_Angeles]
You can generate strings in other formats using DateTimeFormatter class. For the formatting pattern listed second in your question, define a matching DateTimeFormatter object.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu HH:mm:ss.SSS" ) ;
String output = zdt.format( f ) ;
07/07/2018 15:20:14.372
The first formatting pattern listed in your Question has a Z on the end, which means UTC and is pronounced “Zulu”. To adjust our ZonedDateTime to UTC, simply extract a Instant object. An Instant is always in UTC by definition.
Instant instant = zdt.toInstant() ; // Extract an `Instant` object, always in UTC.
Generate a String in the pattern shown first in the Question.
String output = instant.toString() ; // Generate string in standard ISO 8601 format.
2018-07-07T22:20:14.372Z
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
This question already has answers here:
Java / convert ISO-8601 (2010-12-16T13:33:50.513852Z) to Date object
(4 answers)
Closed 6 years ago.
I am trying to parse a String using SimpleDateFormat.
This is my current code:
public String getCreatedDateTime() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-ddEHH:mm:ss.zzzz");
try {
Date date = simpleDateFormat.parse("2015-06-27T13:16:37.363Z");
return date.toString();
} catch (ParseException e) {
return "Error parsing date";
}
}
As you can see, I just put a constant in the parse() method for testing purposes.
So, this is what I am trying to parse:
2015-06-27T13:16:37.363Z
This is the SimpleDateFormat pattern that I am using:
yyyy-MM-ddEHH:mm:ss.zzzz
I keep getting the ParseException.
I know that it is proably because of the .zzzz at the end but I have no idea what .363Z might stand for so I just used some random letters. Bad idea.
I'll appreciate your help a lot. Thank you!
Try with this pattern (note the X at the end and the 'T' in the middle):
"yyyy-MM-dd'T'HH:mm:ss.SSSX"
From Java's SimpleDateFormat's documentation:
ISO 8601 Time zone:
...
For parsing, "Z" is parsed as the UTC time zone designator.
And, from the part where it describes the different characters:
X - Time zone - ISO 8601 time zone
EDIT
If using Android, then "X" is not supported.
You can use this pattern (note Z is a literal now):
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
But then you'll get the date on your current timezone and would need to convert it to UTC if needed.
tl;dr
Skip the formatting pattern. Standard ISO 8601 format is used by default.
Instant.parse( "2015-06-27T13:16:37.363Z" )
ISO 8601
Your string format is formally defined by the ISO 8601 standard.
Basically your Question is a duplicate of this one, Converting ISO 8601-compliant String to java.util.Date.
Alternatives
The Answer by eugenioy is correct.
But you should know that the old java.util.Date/.Calendar/java.text.SimpleDateFormat classes bundled with Java are notoriously troublesome and should be avoided.
Outmoded Classes
Those old classes are now outmoded, first by the third-party Joda-Time library, and now by the new java.time package (Tutorial) built into Java 8 and later (inspired by Joda-Time, defined by JSR 310, extended by the ThreeTen-Extra project).
Both java.time and Joda-Time use the ISO 8601 standard as their defaults when parsing/generating string representations of date-time values. So the code is simple, no need for custom formatter objects. No need for all that format twiddling that caused your Exception.
Time Zone
Both java.time and Joda-Time have a zoned date-time class that understands its assigned time zone (unlike java.util.Date). If you do not assign one, the JVM’s current default time zone is assigned.
Beware that the JVM’s current default time zone can change at any time. It can change at deployment, defaulting to whatever the host OS setting is. And it can change at any moment during runtime when any code in any thread of any app within the JVM calls TimeZone.setDefault. So better to explicitly assign a desired/expected time zone.
java.time
The Z on the end of your string is short for Zulu and means UTC. The Instant class can directly parse that format, to represent a moment on the timeline in UTC with a resolution in nanoseconds.
String input = "2015-06-27T13:16:37.363Z";
Instant instant = Instant.parse( input );
Change the time zone from UTC to some desired/expected time zone.
ZoneID zone = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdtMontréal = instant.atZone( zone ) ;
If you really need a java.util.Date for interoperability, convert.
java.util.Date utilDate = Date.from( zdtMontréal.toInstant() ) ;
Joda-Time
The Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Example code using Joda-Time 2.8.1.
String input = "2015-06-27T13:16:37.363Z" ;
DateTimeZone zone = DateTimeZone.UTC ; // Or: DateTimeZone.forID( "America/Montreal" ) ;
DateTime dateTime = new DateTime( input, zone ) ;
If you really need a java.util.Date for interoperability, convert.
java.util.Date date = dateTime.toDate();
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
I am trying to convert the date in milliseconds to the following ISO 8601 format:
But I am getting the following using SimpleDateFormat:
/**
* It converts the time from long to the ISO format
*
* #param timestampMillis
* #return isoDate
*/
public String convertTimeMillisToISO8601(String timestampMillis)
{
long timeInLong= Long.parseLong(timestampMillis);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
String isoDate = df.format(new java.util.Date(timeInLong));
return isoDate;
}
OUTPUT:
"ts":"2015-06-18T09:56:21+0000"
I know I can use substring to append the extra colon but Is there any better way to do so ?
For Java 7 and higher, you might use XXX (ISO 8601 time zone) in the date format String. According to the documentation, the result of X can be:
X => -08
XX => -0800
XXX => -08:00
but for all of those, it might as well return Z!
For Java 6 and earlier, there is no X (J6 doc), and since the result of X may or may not do what you want, I strongly recommend you just insert that colon yourself.
You can always use a StringBuilder:
new StringBuilder(
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.format(date))
.insert(22,':')
.toString();
For Java 8 if you use one of the standard ISO_DATE_* format patterns then the output formatted String will be truncated when the offset is +00:00 (UTC typically just appends Z).
OffsetDateTime utcWithFractionOfSecond = ZonedDateTime.parse("2018-01-10T12:00:00.000000+00:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME);
utcWithFractionOfSecond.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME); // 2018-01-10T12:00:00Z ... not what you want!
The only solution I have found is using the outputPattern (shown below) that uses lowercase `xxx' to ensure that a colon is included in the timezone offset.
I have included an example with factions-of-a-second for completeness (you can remove the SSSSSS in your case)
DateTimeFormatter inputPattern = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
DateTimeFormatter outputPattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSxxx");
OffsetDateTime utcWithFractionOfSecond = OffsetDateTime.parse("2018-01-10T12:00:00.000000+00:00", inputPattern);
OffsetDateTime utcNoFractionOfSecond = OffsetDateTime.parse("2018-01-10T12:00:00+00:00", inputPattern);
OffsetDateTime utcWithZ = OffsetDateTime.parse("2018-01-10T12:00:00Z", inputPattern);
OffsetDateTime utcPlus3Hours = OffsetDateTime.parse("2018-01-10T12:00:00.000000+03:00", inputPattern);|
utcWithFractionOfSecond.format(outputPattern ); // 2018-01-10T12:00:00.000000+00:00
utcNoFractionOfSecond.format(outputPattern); // 2018-01-10T12:00:00.000000+00:00
utcWithZ.format(outputPattern); // 2018-01-10T12:00:00.000000+00:00
utcPlus3Hours.format(outputPattern); // 2018-01-10T12:00:00.000000+03:00
In these examples I have used ISO_OFFSET_DATE_TIME only to create the input values for the test cases. In all cases it is the outputPattern yyyy-MM-dd'T'HH:mm:ss.SSSSSSxxx that controlling how to include a colon character in the timezone portion of your resulting formatted string.
Note that if your input data included the Zone ID like [Europe/London] then you would create your input data using ZonedDateTime instead of OffsetDateTime
Can you use Java 8?
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("YYYY-MM-dd'T'HH:mm:ssXXX");
System.out.println(formatter.format(ZonedDateTime.now()));
2015-04-15T17:24:19+09:00
tl;dr
OffsetDateTime.parse( "2014-06-18T09:56:21+00:00" )
2014-06-18T09:56:21Z
Details
Some other answers are close, correct in using the modern java.time classes that supplanted the terrible old legacy classes (Date, Calendar, SimpleDateFormat). But they are either working too hard or chose the wrong class.
ISO 8601
Your format is in standard ISO 8601 format. The java.time classes use these standard formats by default when parsing/generating text representing their date-time values. So you need not specify any formatting pattern at all. Works by default.
OffsetDateTime
Your input indicates an offset-from-UTC of zero hours and zero minutes. So we should use the OffsetDateTime class.
String input = "2014-06-18T09:56:21+00:00";
OffsetDateTime odt = OffsetDateTime.parse( input );
Zulu time
We can generate a string in standard ISO 8601 format by merely calling toString. The Z on the end means UTC, and is pronounced “Zulu”.
odt.toString(): 2014-06-18T09:56:21Z
ZonedDateTime
If your input indicated a time zone, rather than merely an offset, we would have used ZonedDateTime class. An offset is simply a number of hours, minutes, and seconds – nothing more. A time zone is much more. A time zone is a history of past, present, and future changes to the offset used by the people of a particular region.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.