akaliza
akaliza

Reputation: 3911

How to parse a date string containing a numerical zone offset

I have this date in string "Fri, 14 Jul 2023 11:53:06 -0400"

and I am unable to convert it in LocalDateTime I have tried this pattern "EEE, dd MMM yyyy HH:mm:ss z" and I have date format exception

any idea ?

Thanks

Upvotes: 1

Views: 113

Answers (4)

bhspencer
bhspencer

Reputation: 13560

The issue is the zone offset. You are using a lowercase 'z' which is for a named time zone e.g. "PST" or "EST". Try with a capital 'Z' as shown below for a numerical zone offset:

    String date = "Fri, 14 Jul 2023 11:53:06 -0400";
    String pattern = "EEE, dd MMM yyyy HH:mm:ss Z"; //Note the capital 'Z'
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
    ZonedDateTime zonedDateTime = ZonedDateTime.parse(date, formatter);
    System.out.println(zonedDateTime);

Upvotes: 3

Vinit More
Vinit More

Reputation: 77

With below code I am able to get result without error in date format. Not sure if this is what you needed. Or comment here and will explore options.

Code

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("E, d LLL u HH:mm:ss Z");
LocalDateTime date = LocalDateTime.parse("Fri, 14 Jul 2023 11:53:06 -0400", fmt);
System.out.println(date);

Result

2023-07-14T11:53:06

Upvotes: 0

OscarRyz
OscarRyz

Reputation: 199195

Updated with code

You have to combine a couple of things:

  1. Parse the date into an OffsetDateTime (which has the timezone part)
  2. Convert that into an Instant which like an "absolute" time.
  3. Get your local offset, so you see what that would be in your local time
  4. Convert the instant into LocalDateTime using that offset.

Code

import java.time.*;
import java.time.format.*;


/* 1 */ var odt = OffsetDateTime.parse("Fri, 14 Jul 2023 11:53:06 -0400",
                               DateTimeFormatter.RFC_1123_DATE_TIME);
/* 2 */ var instant = odt.toInstant();
/* 3 */ var localOffset = OffsetDateTime.now().getOffset();
/* 4 */ var result = LocalDateTime.ofInstant(instant, localOffset);


/*
Result
odt ==> 2023-07-14T11:53:06-04:00
instant ==> 2023-07-14T15:53:06Z
localOffset ==> -05:00
result ==> 2023-07-14T10:53:06
*/

Upvotes: -1

Basil Bourque
Basil Bourque

Reputation: 338171

The Answer by bhspencer identifies part of the problem, needing a tweak to your formatting pattern. However, you may also need to specify a Locale with your DateTimeFormatter.

But FYI, there is a simpler approach. No need to specify a formatting pattern at all.

tl;dr

OffsetDateTime.parse( 
    "Fri, 14 Jul 2023 11:53:06 -0400" , 
    DateTimeFormatter.RFC_1123_DATE_TIME 
)

RFC 1123 / RFC 822

Your input string "Fri, 14 Jul 2023 11:53:06 -0400" complies with the outdated standard format defined in RFC 1123 & RFC 822.

java.time comes with a formatter predefined for that format. See class DateTimeFormatter.RFC_1123_DATE_TIME.

String input = "Fri, 14 Jul 2023 11:53:06 -0400" ;
OffsetDateTime odt = OffsetDateTime.parse( input , DateTimeFormatter.RFC_1123_DATE_TIME );

See this code run at Ideone.com.

odt.toString() = 2023-07-14T11:53:06-04:00


Tip: Educate the publisher of your data about using the modern ISO 8601 standard formats rather than these troublesome outmoded formats.

And educate them on using a fully-formed offset, including the optional COLON. I have seen multiple protocols and libraries that do not tolerate the omitted COLON. And easier to read by humans if included.

Upvotes: 4

Related Questions