2

I am trying to convert a string into an ISO 8601 date-time format. Currently, this code

String s1 = "2001-05-03T00:00:00+00:00"; Date firstAvailableDateTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").parse(s1);

gives me this result

2001-05-03T00:00:00.000+0000

However, this output is missing a colon in the timezone. The desired output is:

2001-05-03T00:00:00.000+00:00

According to https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html, using "XXX" for the timezone should output a colon in the final date but it does not for me.

What am I missing?

I've looked at this solution but do not want to use Joda-Time since it may cause complications in the future moving between two date types.

Ryan
  • 53
  • 1
  • 1
  • 7
  • 1
    `Date` does not have an internally assignable format. – Elliott Frisch Feb 25 '19 at 20:13
  • Does that mean that I can't get a colon included in that date then? – Ryan Feb 25 '19 at 20:16
  • 3
    Are you on Java 8? Can you use LocalDateTime? – Roddy of the Frozen Peas Feb 25 '19 at 20:25
  • 2
    @RoddyoftheFrozenPeas I'm on Java 8 and can use LocalDateTime. Right now I have `DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX"); LocalDateTime lastAvailableDateTime = LocalDateTime.parse("2011-05-03T00:00:00+00:00", dtf);` but the output comes out to just `"2011-05-03T00:00:00"`. So now there isnt even a timezone listed. – Ryan Feb 25 '19 at 21:08
  • 1
    You need to use ZonedDateTime, not LocalDateTime. – Roddy of the Frozen Peas Feb 25 '19 at 21:17
  • 1
    @RoddyoftheFrozenPeas Yup that worked. Thanks! – Ryan Feb 25 '19 at 21:20
  • Sorry about the confusion. `OffsetDateTime` is the best fit when the string has an offset in is (`+00:00`) and no time zone (like Asia/Kolkata or Mountain Time). – Ole V.V. Feb 25 '19 at 22:48
  • @RoddyoftheFrozenPeas As Ole V.V. commented, `ZonedDateTime` class is for values with a time zone (a history of past, present, and future changes to the offset used by the people of a particular region), while `OffsetDateTime` is appropriate for mere offset-from-UTC (simply a number of hours-minutes-seconds). – Basil Bourque Feb 26 '19 at 00:52
  • Without knowing the full use case I cannot recommend one or the other and ZonedDateTime is more broadly applicable, hence why I suggested it and why I have no regrets in doing so. – Roddy of the Frozen Peas Feb 26 '19 at 03:48
  • I’m a little bit confused because I cannot reproduce. From your code I get an old-fashioned `java.util.Date` object of `Thu May 03 02:00:00 CEST 2001`. – Ole V.V. Feb 26 '19 at 08:24

2 Answers2

7

tl;dr

OffsetDateTime.parse( "2001-05-03T00:00:00+00:00" )

Avoid legacy date-time classes

Never use SimpleDateFormat, Date, Calendar, etc. These terrible classes were supplanted years ago by the java.time classes.

ISO 8601

trying to convert a string into an ISO 8601 date-time format

String s1 = "2001-05-03T00:00:00+00:00"

Your Question is quite confused. Your input string is in standard ISO 8601 format. The T in the middle separates the year-month-day from the hour-minute-second, and the +00:00 at the end indicates an offset-from-UTC of zero hours and zero minutes, that is, UTC itself. All standard, all proper.

Perhaps you are conflating strings representing date-time values and date-time objects containing date-time values. A date-time object has no “format”; it has its own internally-defined representation of a date-time value. Only text has a format. A date-time class can parse a formatted string as input, and a date-time class can generate a formatted sting as output, but within the date-time there is no format at all.

OffsetDateTime

The java.time classes use the ISO 8601 formats by default when parsing/generating strings representing date-time values. So no need to specify a formatting pattern for such inputs.

OffsetDateTime odt = OffsetDateTime.parse( "2001-05-03T00:00:00+00:00" ) ;  

See this code run live at IdeOne.com.

odt.toString(): 2001-05-03T00:00Z

Z

There is a common abbreviation for an offset of zero: a simple Z letter, meaning UTC, and pronounced “Zulu”. Example: 2019-02-26T00:44:28Z

The Z is quite commonly used. But if for some reason you prefer the numeric +00:00, use DateTimeFormatter options.

COLON character

By the way, you mentioned the COLON character omitted from the offset: +0000. That is actually tolerated by the ISO 8601 standard. But I do not advise it. I have seen libraries and systems break on such inputs. Best to use full-length, hours and minutes, padding zeros, and the colon character: +00:00 rather than +0000, and -07:00 rather than -7.


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?

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
2

The solution that was found ended up being to use ZonedDateTime along with a DateTimeFormatter.

DateTimeFormatter dtf = DateTimeFormatter.ISO_OFFSET_DATE_TIME; ZonedDateTime lastAvailableDateTime = ZonedDateTime.parse("2011-05-03T00:00:00+05:00", dtf);

The output from this code is:

2011-05-03T00:00:00+05:00

Ryan
  • 53
  • 1
  • 1
  • 7
  • 1
    Still better and simpler: `OffsetDateTime lastAvailableDateTime = OffsetDateTime.parse("2011-05-03T00:00:00+05:00");`. No need for any explicit formatter. – Ole V.V. Feb 25 '19 at 22:51
  • 1
    `ZonedDateTime` class is for values with a time zone. When working with a mere offset-from-UTC rather than a time zone, use `OffsetDateTime`. – Basil Bourque Feb 26 '19 at 00:42