3

Hi I want to convert String value 2020-12-16T19:20:30+01:00 UTC to either LocalDateTime or ZonedDateTime in java

I tried solution:

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("YYYY-MM-DDThh:mm:ssTZD", Locale.ENGLISH);
final String responseTimeStamp = "2020-12-16T19:20:30+01:00 UTC";
ZonedDateTime zdt = ZonedDateTime.parse(responseTimeStamp, dtf);

Which gives me the error

Exception in thread "main" java.lang.IllegalArgumentException: Unknown pattern letter: T at java.base/java.time.format.DateTimeFormatterBuilder.parsePattern(DateTimeFormatterBuilder.java:1815) at java.base/java.time.format.DateTimeFormatterBuilder.appendPattern(DateTimeFormatterBuilder.java:1712) at java.base/java.time.format.DateTimeFormatter.ofPattern(DateTimeFormatter.java:588) at learning/learning.SpringDemo.main(SpringDemo.java:21)

Anthony Accioly
  • 21,918
  • 9
  • 70
  • 118
lucky
  • 331
  • 6
  • 14
  • What is wrong with `ZonedDateTime zdt = ZonedDateTime.parse(responseTimeStamp);`? The format is standard. Your error was that you needed to quote the T: `...'T'...` and hh (12 hours) must be `HH` (24 hours). and YYYY (week year) yyyy (calendar year) and dd – Joop Eggen Feb 09 '22 at 21:47
  • As per your suggestion, i tried DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssTZD", Locale.ENGLISH); final String responseTimeStamp = "2020-12-16T19:20:30+01:00 UTC"; ZonedDateTime zdt = ZonedDateTime.parse(responseTimeStamp, dtf); System.out.println(zdt); But i am still getting the same error – lucky Feb 09 '22 at 21:59
  • TZD is suspicious. Just look into the javadoc on the internet for [DateTimeFormatter](https://docs.oracle.com/javase/10/docs/api/java/time/format/DateTimeFormatter.html) – Joop Eggen Feb 09 '22 at 22:44

2 Answers2

2

There are a few things wrong with your code. I suggest you to take a look at the DateTimeFormatter documentation.

  1. YYYY -> This means week-based-year, you can have a look here to see the difference between year-of-era. So you should be using yyyy.
  2. DD -> This means day-of-year, so December 16 is equal to 350. In your case you want to use dd, day-of-month.
  3. T -> There isn't a pattern for T, so you can put it like a text to formmat you date 'T'
  4. TZD -> I don't know what you are trying to use here and I couldn't find the patter +03:00 UTC, you can try to use O

So your final pattern should be "yyyy-MM-dd'T'HH:mm:ssO". It doens't work for UTC and I couldn't find it on ZoneId list, maybe because UTC is +00:00 already, so UTC+01:00 is equal to +01:00.

After a lot of working understanding the pattern, I found out that you are looking for ISO_ZONED_DATE_TIME, so you could just change your code like below:

DateTimeFormatter dtf = DateTimeFormatter.ISO_ZONED_DATE_TIME;
final String responseTimeStamp = "2020-12-16T19:20:30+01:00";
ZonedDateTime zdt = ZonedDateTime.parse(responseTimeStamp, dtf);
ouflak
  • 2,458
  • 10
  • 44
  • 49
Maickeen
  • 99
  • 6
  • Thank you, Maickeen I have done so as of now, as i don't have production data to test. In sample data, UTC was mentioned, so i was trying that. ALso, what about String 2020-10-21 03:59:00 ? – lucky Feb 10 '22 at 05:00
2

tl;dr

OffsetDateTime
.parse( 
    "2020-12-16T19:20:30+01:00 UTC"
    .replace( " UTC" , "" )
)
.withZoneSameInstant( 
    ZoneId.of( "America/Edmonton" ) 
) 

ISO 8601

Your input string:

2020-12-16T19:20:30+01:00 UTC

… nearly complies with the ISO 8601 standard for data-exchange date-time formats. To fully comply, delete the SPACE and UTC from the end. The +01:00 at the end means “one hour ahead of UTC", so the UTC at the end is redundant.

String input = "2020-12-16T19:20:30+01:00 UTC".replace( " UTC" , "" ) ;

Offset versus time zone

Parse as an OffsetDateTime because your input indicates small offset from UTC, not a time zone.

An offset is merely a number of hours-minutes-seconds ahead/behind the prime meridian of UTC. A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region as decided by their politicians. A time zone has a name in format of Continent/Region, such as Europe/Paris and Africa/Tunis.

OffsetDateTime

So the other Answer’s suggestion to use ZonedDateTime for parsing is misguided as no time zone is indicated. Your input has only an offset, therefore use OffsetDateTime.

No need to specify a formatting pattern. Our modified input complies with ISO 8601, and the java.time classes use those standard formats by default when parsing/generating strings.

OffsetDateTime odt = OffsetDateTime.parse( input ) ;

LocalDateTime

You asked how to get a LocalDateTime. That class lacks any concept of offset or time zone. So beware, if you convert from OffsetDateTime, you are discarding valuable information.

So while I don’t recommend doing this, here is the code.

LocalDateTime ldt = odt.toLocalDateTime() ;

ZonedDateTime

You asked how to adjust into a time zone.

To adjust from our offset to a time zone, merely specify the desired time zone.

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = odt.withZoneSameInstant( z ) ;
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154