Parse string date to OffsetDateTime when time zone information is missing - java

I'm receiving a string time object from a third party that looks like this: 12/12/2021 3:34:30 PM. The time zone information is missing but I know it is UTC.
I'm using Jackson to parse the csv and have been playing around with the annotations to try and get it to parse correctly. Here is what I currently have:
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "M/d/yyyy h:mm:ss a", timezone = "UTC", lenient = OptBoolean.TRUE)
protected OffsetDateTime shareDate
which gives me the error:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.OffsetDateTime` from String "12/12/2021 3:34:30 PM": Failed to deserialize java.time.OffsetDateTime: (java.time.DateTimeException) Unable to obtain OffsetDateTime from TemporalAccessor: {InstantSeconds=1639323270},ISO,UTC resolved to 2021-12-12T15:34:30 of type java.time.format.Parsed
I can change the OffsetDateTime to LocalDateTime and it works. I would rather save it as an OffsetDateTime since I do know it is always UTC. Anyone out there know how to set the annotation to get that to work? Or is it not possible that way?

Related

deserializing error with date - JSON decoding error

I am getting a response from an api and it is failing to deserialize a date which looks like this "2021-09-10T21:48:35.352+0000". I have set up attribute in my class like below
#JsonProperty("processedAt")
private LocalDateTime processedAt;
org.springframework.core.codec.DecodingException: JSON decoding error: Cannot deserialize value of type java.time.LocalDateTime from String "2021-09-10T21:48:35.352+0000": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2021-09-10T21:48:35.352+0000' could not be parsed, unparsed text found at index 23;
what format of date should I be using in class to get the date out and not fail on deserializing. thanks in advance
By default Jackson does not support this date time format pattern. Therefore you need to explicitly mention that using #JsonFormat annotation. Like this,
#JsonProperty("processedAt")
#JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
private LocalDateTime processedAt;
Looking at your datetime format, you should probably use OffsetDateTime instead of LocalDateTime. Otherwise your timezone will be ignored (If you local timezone is +0000, then LocalDateTime should be fine).
#JsonProperty("processedAt")
#JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
private OffsetDateTime processedAt;
Update
If you use OffsetDateTime, then you don't need to explicitly mention the pattern using #JsonFormat annotation. Something like this sufficient.
#JsonProperty("processedAt")
private OffsetDateTime processedAt;
I did not check but you are using LocalDateTime and are trying to deserialize a ZonedDateTime. Maybe change the type?
That is also in agreement with the error message that states that the error is at position 23. Exactly where the unexpected zone information starts.

How to Parse Any Datetime format to yyyy-MM-dd in java

I have a date field that is populated dynamically, and I need that field in the format yyyy-MM-dd
For a input date of format 1994-08-01 14:37:44 this is giving a Exception
java.time.format.DateTimeParseException: Text '1994-08-01 14:37:44' could not be parsed, unparsed text found at index 10
This is one of the many other ways I tried LocalDateTime.parse("1994-08-01 14:37:44",DateTimeFormatter.ofPattern(yyyy-MM-dd));
Is there a way to convert all date/datetime to yyyy-MM-dd format?
please help
Thanks
You have a date and time component but you're only using a date format to parse it to a LocalDateTime value, this will fail because LocalDateTime needs the time component in order to work
Start by parsing the full text
String input = "1994-08-01 14:37:44";
LocalDateTime ldt = LocalDateTime.parse(input, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
Then use a DateTimeFormatter to format it the way you want
String formatted = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(ldt);
System.out.println(formatted);
which prints
1994-08-01
Depending on your needs, you could also convert the LocalDateTime value to a LocalDate and format it, it's the same result, but you might have need of the LocalDate for other things, who knows...
String formatted = ldt.toLocalDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
Try it like this. You can extract the LocalDate part.
LocalDate ldt = LocalDateTime.parse("1994-08-01 14:37:44",
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(ldt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
Prints
1994-08-01

How to convert an Epoch timestamp into an object of type java.time.Instant Accurately in Java?

I have a Spring Boot JPA Application that interacts with a 3rd party API.
The response payload of the API has a key
"created_at": 1591988071
I need to parse this field into java.time.Instant so that I can do some comparisons with the value I have in the Database.
I have learned that I can use the below mentioned piece of code.
Instant instant = Instant.ofEpochSecond(1591988071);
Output :
2020-06-12T18:54:31Z
But to be honest, this output is off by a couple of hours.
I found another approach, wherein if I use
String dateAsText = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(new Date(1591988071 * 1000L));
System.out.println(dateAsText);
I get the desired output but in String format.
2020-06-13 00:24:31
Can someone tell me how to obtain the above String output but converted into type java.time.Instant ?
It is likely you're in a different timezone than UTC. The instant is giving you time in UTC. That's indicated by the Z at the end of your first output.
You would want to look at atZone
Instant instant = Instant.ofEpochSecond(1591988071);
System.out.println(instant);
final ZonedDateTime losAngeles = instant.atZone(ZoneId.of("America/Los_Angeles"));
System.out.println(losAngeles);
final ZonedDateTime mumbai = instant.atZone(ZoneId.of("UTC+0530"));
System.out.println(mumbai);
This gives you something you might expect
2020-06-12T18:54:31Z
2020-06-12T11:54:31-07:00[America/Los_Angeles]
2020-06-13T00:24:31+05:30[UTC+05:30]

Jackon 2.4.2 failing to deserialize valid date, even after specifying date format

I am attempting to deserialize a JSON with a custom date format. It is failing, even though I have set a date format on the object mapper:
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
mapper.setDateFormat(dateFormat);
Then I attempt to deserialize the following JSON using that mapper:
{
"id": 11,
"confirmed": false,
"creationDate": "2015-04-20T22:27:41Z",
"lastUpdateDate": "2015-04-20T22:27:41Z",
"name": "test"
}
Using the line:
Test test = mapper.readValue(jsonString, Test.class);
and it fails with:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of java.util.Date from String value '2015-04-20T22:27:41Z': not a valid representation (error: Failed to parse Date value '2015-04-20T22:27:41Z': Unparseable date: "2015-04-20T22:27:41Z")
Any ideas what am I doing wrong? I can't seem to figure out what I am missing...
Thank you!
Use yyyy-MM-dd'T'HH:mm:ssX. Z is for an RFC 822 time zone, and Z is not such a timezone. X is for a ISO 8601 time zone, and Z is such a timezone.
https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

Joda DateTime,, Formatting, and Mysql Timestamp

After a week of going through so many examples, and moving from Java Date,
to Calendar, to Joda. I have decided to seek help from other sources.
The problem:
Our table has two fields Date (Timestamp), and TZ (String). The idea is to store
the user's UTC in timestamp, and timezone, well, you get the idea. So basically
we think in UTC, and present the user with the time converted to their
timezone on the front end (ie, using the value store in table.TZ)
Another requirement is to use the proper Object (Date, DateTime whatever).
And not pass a String representation of the date around. The best would
be a valid Long that will be correctly translated by MySQL, without having
to use the FROM_UNIXTIME mysql function in our query.
Code we are using:
public DateTime convertTimezone(LocalDateTime date, DateTimeZone srcTZ, DateTimeZone dstTZ, Locale l) {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").withLocale(l);
DateTime srcDateTime = date.toDateTime(srcTZ);
DateTime dstDateTime = srcDateTime.toDateTime(dstTZ);
System.out.println(formatter.print(dstDateTime));
System.out.println(formatter.parseDateTime(dstDateTime.toString()));
return formatter.parseDateTime(formatter.print(dstDateTime));
}
The String output is exactly what we need (ie UTC time, 2013-08-23 18:19:12),
but the formatter.parseDateTime(dstDateTime.toString() is crashing with the following
error. Probably because of the UTC timezone independent info, and milleseconds?:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid format: "2013-08- 23T18:19:12.515Z" is malformed at "T18:19:12.515Z"
at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:873)
at com.example.business.rate.RateDeck.convertTimezone(RateDeck.java:75)
at com.example.business.rate.RateDeck.WriteData(RateDeck.java:143)
at com.example.business.rate.RateDeck.main(RateDeck.java:64)
Search engine enriched question:
How to format UTC for Joda DateTime.
PS My first SO post, and it feels nice? :)
Thanks in Advance,
The new fixed version:
public Timestamp convertTimezone(LocalDateTime date, DateTimeZone srcTZ, DateTimeZone dstTZ, Locale l) {
DateTime srcDateTime = date.toDateTime(srcTZ);
DateTime dstDateTime = srcDateTime.toDateTime(dstTZ);
return new Timestamp(dstDateTime.getMillis());
}
Nick.
It's simply crashing because the format of the parsed string doesn't match with the format of the formatter.
The formatter parses using the format yyyy-MM-dd HH:mm:ss, and the toString() method of DateTime formats the date it using (as documented) the ISO8601 format (yyyy-MM-ddTHH:mm:ss.SSSZZ).

Categories