Jackson JsonFormat set date with one day day less
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
When using Jackson's @JsonFormat annotation to serialize Java Date or LocalDate objects to JSON, the output date sometimes appears one day earlier than expected. This happens because Jackson defaults to UTC for timezone when no timezone is specified, and the local timezone offset shifts the date across a day boundary. The fix is to explicitly set the timezone attribute on @JsonFormat to match your data's intended timezone, or to use LocalDate (which has no timezone) with proper configuration. This is one of the most common Jackson date-handling surprises.
The Problem
The date shifts back one day because the Date object stores 2026-03-15 00:00:00 in the local timezone (e.g., America/New_York, UTC-5). When Jackson serializes it using UTC (its default), midnight Eastern time becomes 2026-03-14 19:00:00 UTC, which formats as 2026-03-14.
Fix 1: Set timezone on @JsonFormat
Fix 2: Set Timezone Globally on ObjectMapper
Spring Boot Global Configuration
Fix 3: Use Java 8 Date/Time Types
LocalDate has no timezone, so the problem does not arise:
Add the dependency:
Other Java 8 Date Types
Deserialization: Same Problem
The timezone issue affects deserialization too:
Debugging Date Issues
Common Pitfalls
- Not specifying a timezone on
@JsonFormatwhen usingjava.util.Date: Jackson defaults to UTC. If your dates represent local midnight, the UTC conversion shifts them back by your timezone offset, resulting in the previous day. Always settimezoneexplicitly when usingDate. - Using
java.util.Dateinstead ofLocalDatefor date-only fields:Dateincludes time and timezone information, making it inherently problematic for date-only values.LocalDaterepresents a calendar date without time or timezone and avoids this issue entirely. - Forgetting to register
JavaTimeModulefor Java 8 types: Withoutmapper.registerModule(new JavaTimeModule()), Jackson cannot serializeLocalDate,LocalDateTime, orZonedDateTime. Spring Boot auto-registers this module if the dependency is on the classpath. - Setting
timezoneon@JsonFormatbut not on deserialization: The timezone applies to both serialization and deserialization when specified. If you set it only in one direction (e.g., a custom serializer), the other direction still uses UTC. - Confusing
timezonewithlocalein@JsonFormat:timezonecontrols the UTC offset for date conversion.localecontrols formatting conventions (month names, AM/PM). Settinglocaledoes not fix the one-day-off problem — onlytimezonedoes.
Summary
- The one-day-off issue occurs because Jackson defaults to UTC, and local midnight shifts to the previous UTC day
- Fix by setting
timezoneon@JsonFormat, or globally viaObjectMapper.setTimeZone()orspring.jackson.time-zone - Prefer
LocalDateoverjava.util.Datefor date-only fields — it has no timezone and avoids the problem entirely - Register
jackson-datatype-jsr310(JavaTimeModule) for Java 8 date/time type support - Always test date serialization with timezones that are behind UTC (negative offset) to catch this issue early
Related reading
- Jackson serialization ignore empty values or null
- Jackson serializes a ZonedDateTime wrongly in Spring Boot
- Jackson Vs. Gson
- Jackson with JSON Unrecognized field, not marked as ignorable
- Java-R integration?
- Java8 Why is it forbidden to define a default method for a method from java.lang.Object
- Java - Convert integer to string
- Java - escape string to prevent SQL injection

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.