Parse ISO8601 date string to date with UTC Timezone
tl;dr
OffsetDateTime.parse( "2015-10-27T16:22:27.605-07:00" )
.toInstant()
.toString()
2015-10-27T23:22:27.605Z
Details
Your question is not clear and specific. Perhaps these little examples will help. Mixing the old java.util.Date and .Calendar classes with Joda-Time may be confusing you. Joda-Time completely replaces those classes rather than augments.
java.time
The modern java.time classes supplant both the legacy date-time classes in Java as well as the Joda-Time library which provided their inspiration.
OffsetDateTime
The OffsetDateTime
class represents a moment on the timeline with a particular offset-from-UTC determining its wall-clock time.
The java.time classes use the standard ISO 8601 formats by default when parsing/generating strings. So no need to specify a formatting pattern.
OffsetDateTime odt = OffsetDateTime.parse( "2015-10-27T16:22:27.605-07:00" ) ;
Instant
To adjust from the offset of seven hours behind UTC to UTC itself, we need to add seven hours to the time-of-day and rollover the date if need be. The OffsetDateTime
class can do this work for us. Specify UTC using the ZoneOffset.UTC
constant.
OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC ) ;
odtUtc.toString(): 2015-10-27T23:22:27.605Z
If you are using this UTC value much in your code, and generally you should be, then you may find it more clear to use Instant
objects. An Instant
is always in UTC by definition. We can extract an Instant
from the OffsetDateTime
.
Instant instant = odt.toInstant() ;
instant.toString(): 2015-10-27T23:22:27.605Z
Note that all three of our objects above (odt
, odtUtc
, instant
) all represent the very same simultaneous moment, the same point on the timeline. The only thing different is their wall-clock time.
ZonedDateTime
By the way, if you want to see that same moment adjusted to the wall-clock time in use by the people of a certain region, specify a time zone via ZoneId
to get a ZonedDateTime
object.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
zdt.toString(): 2015-10-27T19:22:27.605-04:00[America/Montreal]
Use concrete classes in java.time
The Answer by always_a_rookie_to_learn is similar to the above approach but uses the interface TemporalAccessor
. Generally, using the higher interfaces and superclasses is a good idea in Java. But not here. The java.time documentation explains that their design intends us to use the lower more concrete classes in our apps. The abstractions are for internal use only within the framework, generally.
In the specific case of this Question, the class OffsetDateTime
is appropriate rather than TemporalAccessor
.
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.
Joda-Time
UPDATE: The Joda-Time project in is maintenance mode, and it advises migration to the java.time classes. This section is left intact for history.
Joda-Time defaults to ISO 8601 for strings, both parsing and generating. Joda-Time has built-in default parsers for ISO 8601, so simply pass your compliant string to the constructor or to the static parse
method.
java.util.Date date = new DateTime( "2010-01-01T12:00:00+01:00Z" ).toDate();
When possible, avoid java.util.Date and .Calendar, and stick with Joda-Time and it's classes such as DateTime
. Use .Date only where required by other classes.
DateTime dateTimeUtc = new DateTime( someJavaDotUtilDotDate, DateTimeZone.UTC ); // Joda-Time can convert from java.util.Date type which has no time zone.
String output = dateTime.toString(); // Defaults to ISO 8601 format.
DateTime dateTimeUtc2 = new DateTime( output, DateTimeZone.UTC ); // Joda-Time can parse ISO 8601 strings.
For presentation, adjust to time zone expected by the user.
DateTime dateTimeMontréal = dateTimeUtc.withZone( DateTimeZone.forID( "America/Montreal" ) );
If you are using Java 7 or earlier you can refer to this post.
If you are using Java 8 you could do:
DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME;
TemporalAccessor accessor = timeFormatter.parse("2015-10-27T16:22:27.605-07:00");
Date date = Date.from(Instant.from(accessor));
System.out.println(date);
Update
As pointed out by @BasilBourque in the comment, TemporalAccessor is java framework level interface, and is not advisable to use in the application code and it is advisable to use concrete classes rather than the interfaces.
This interface is a framework-level interface that should not be widely used in application code. Instead, applications should create and pass around instances of concrete types, such as LocalDate. There are many reasons for this, part of which is that implementations of this interface may be in calendar systems other than ISO. See ChronoLocalDate for a fuller discussion of the issues.
There a few concrete classes available to use, like LocalDate, LocalDateTime, OffsetDateTime, ZonedDateTime and etc..
DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME;
OffsetDateTime offsetDateTime = OffsetDateTime.parse("2015-10-27T16:22:27.605-07:00", timeFormatter);
Date date = Date.from(Instant.from(offsetDateTime));
System.out.println(date);