Home > OS >  Jackson desrialize date ignore time/set time to 0
Jackson desrialize date ignore time/set time to 0

Time:10-04

Below is my list of json objects:

[
    {
        "Date": "2022-04-06T00:00:00"
    },
    {
        "Date": "2022-12-06T00:00:00"
    }
]

and my POJO:

@Data
public class MyPojo {

    @JsonProperty("Date")
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-mm-dd")
    private Date date;
}

Deserialization code:

public <T> List<T> toObjList(String json, Class<T> className) {
        try {
            return new ObjectMapper().readValue(json, objectMapper.getTypeFactory().constructCollectionType(List.class, className));
        } catch (Exception ex) {
            log.error("Exception converting json to Object: {}", json);
            throw new AppException("Exception while converting String to Object list", ex, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

My problem is, despite omitting the time in jsonFormat pattern, I see that some random time is added to each date. I printed the serialized dates and following was the output:

(date=Fri Sep 30 05:30:00 IST 2022)

I tried parsing a date with simleDateFormat and it seemed to parse excluding the time.

String input = "2022-09-30T00:00:00";
SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd");
Date date = parser.parse(input);
System.out.println(date);

This gave an expected output

Fri Sep 30 00:00:00 IST 2022

CodePudding user response:

Avoid legacy date-time classes

The terrible java.util.Date class was years ago supplanted by the modern java.time classes defined in JSR 310.

Among the many flaws in that class, the name Date is a misnomer. The class represents a moment as seen with an offset of zero hours-minutes-seconds from UTC. So it always has a time of day, plus the offset of zero.

java.time.LocalDate

If you want to represent a date-only value, without time of day, and without offset or time zone, use the modern class java.time.LocalDate.

Determining a date from a moment

If you want to get a date from an existing java.util.Date object, immediately convert to its modern replacement, java.time.Instant. Use the new conversion methods added to the old classes.

Instant instant = myJavaUtilDate.toInstant() ; 

To determine a date, you must specify a time zone. For any given moment, the date varies around the globe by time zone. “Tomorrow” in Asia/Tokyo is simultaneously “yesterday” in America/Edmonton.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;  // Specify your time zone of interest.
ZonedDateTime zdt = instant.atZone( z ) ;

Extract your desired date-only value.

LocalDate ld = zdt.toLocalDate() ; 

Compare LocalDate objects using isEqual, isBefore, and isAfter methods.

Search to learn more. All this has been covered many times on Stack Overflow.

CodePudding user response:

The root cause of the problem is using m instead of M in pattern = "yyyy-mm-dd". The letter M stands for Month in year while m stands for Minute in hour.

Note that the java.util Date-Time API and their parsing/formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API. Learn about the modern date-time API from Trail: Date Time.

  • Related