How to format LocalDate object using Jackson?

We have a Recording class which has a Java 8 java.time.LocalDate property. We need to deserialize and serialize this property from and to JSON string. To do this we can use the @JsonDeserialize and @JsonSerialize annotations to annotate the LocalDate property of the Recording class.

@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate releaseDate;

To use the annotation we need to create a class to deserialize and serialize the value. To create a deserializer class we create a class that extends StdDeserializer. The serializer class extends the StdSerializer class. Below is the definition of the LocalDateSerializer and LocalDateDeserializer class.

package org.kodejava.example.jackson;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class LocalDateSerializer extends StdSerializer<LocalDate> {

    public LocalDateSerializer() {
        super(LocalDate.class);
    }

    @Override
    public void serialize(LocalDate value, JsonGenerator generator, SerializerProvider provider) throws IOException {
        generator.writeString(value.format(DateTimeFormatter.ISO_LOCAL_DATE));
    }
}
package org.kodejava.example.jackson;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

import java.io.IOException;
import java.time.LocalDate;

public class LocalDateDeserializer extends StdDeserializer<LocalDate> {

    protected LocalDateDeserializer() {
        super(LocalDate.class);
    }

    @Override
    public LocalDate deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        return LocalDate.parse(parser.readValueAs(String.class));
    }
}

And here is the complete definition of the Recording class.

package org.kodejava.example.jackson;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.time.LocalDate;
import java.util.Objects;

public class Recording {
    private Long id;
    private String title;

    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate releaseDate;

    private Artist artist;
    private Label label;

    public Recording() {
    }

    public Recording(Long id, String title, LocalDate releaseDate) {
        this.id = id;
        this.title = title;
        this.releaseDate = releaseDate;
    }

    // Getters and Setters
}

Maven Dependencies

<!-- http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.8.6/jackson-databind-2.8.6.jar -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.8.6</version>
</dependency>

How to convert java.time.LocalDate to java.util.Date?

The following code snippet demonstrate how to convert java.time.LocalDate to java.util.Date and vice versa. In the first part of the code snippet we convert LocalDate to Date and back to LocalDate object. On the second part we convert LocalDateTime to Date and back to LocalDateTime object.

package org.kodejava.example.datetime;

import java.time.*;
import java.util.Date;

public class LocalDateToDate {
    public static void main(String[] args) {
        // Convert java.time.LocalDate to java.util.Date and back to
        // java.time.LocalDate
        LocalDate localDate = LocalDate.now();
        System.out.println("LocalDate = " + localDate);

        Date date1 = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
        System.out.println("Date      = " + date1);

        localDate = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        System.out.println("LocalDate = " + localDate);
        System.out.println();

        // Convert java.time.LocalDateTime to java.util.Date and back to
        // java.time.LocalDateTime
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println("LocalDateTime = " + localDateTime);

        Date date2 = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        System.out.println("Date          = " + date2);

        localDateTime = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        System.out.println("LocalDateTime = " + localDateTime);
    }
}

The result of the code snippet:

LocalDate = 2017-02-14
Date      = Tue Feb 14 00:00:00 WITA 2017
LocalDate = 2017-02-14

LocalDateTime = 2017-02-14T10:34:49.562
Date          = Tue Feb 14 10:34:49 WITA 2017
LocalDateTime = 2017-02-14T10:34:49.562

How do I manipulate LocalDate object using TemporalAdjuster?

In the previous example we manipulate the value of LocalDate by adding or subtracting the value of date object by days, months, years using methods like plusMonths() or minusDays(). Or by changing the year or the month of the date object using methods like withYear() or withMonth().

But there are times that we want to manipulate the date object so that we can get the first day of the month or the last day of the month. We want to manipulate the date value to advance the date to the first Monday after the current day or the last the of the year.

To manipulate the date object in this way we can use the with() method and pass a TemporalAdjuster object as an argument. Fortunately, the Date and Time API already provide some commonly used TemporalAdjuster. These TemporalAdjuster are provided as a static factory methods that we can find in the java.time.temporal.TemporalAdjusters class.

The following example is a code snippet to manipulate the date object using TemporalAdjuster / TemporalAdjusters class.

package org.kodejava.example.datetime;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

public class DateManipulationWithTemporalAdjuster {
    public static void main(String[] args) {
        LocalDate date = LocalDate.now();
        System.out.println("Current date       = " + date);

        LocalDate date1 = date.with(TemporalAdjusters.firstDayOfMonth());
        System.out.println("First day of month = " + date1);

        LocalDate date2 = date.with(TemporalAdjusters.lastDayOfMonth());
        System.out.println("Last day of month  = " + date2);

        LocalDate date3 = date.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
        System.out.println("Next Monday        = " + date3);

        LocalDate date4 = date.with(TemporalAdjusters.lastDayOfYear());
        System.out.println("Last day of year   = " + date4);
    }
}

The result of the code snippet are:

Current date       = 2016-03-06
First day of month = 2016-03-01
Last day of month  = 2016-03-31
Next Monday        = 2016-03-07
Last day of year   = 2016-12-31

The table below shows the complete of static factory method provided by the TemporalAdjusters class.

Method Name Method Description
dayOfWeekInMonth Returns a new date in the same month with the ordinal day-of-week.
firstDayOfMonth Returns a new date set to the first day of the current month.
firstDayOfNextMonth Returns a new date set to the first day of the next month.
firstDayOfNextYear Returns a new date set to the first day of the next year.
firstDayOfYear Returns a new date set to the first day of the current year.
firstInMonth Returns a new date in the same month with the first matching day-of-week.
lastDayOfMonth Returns a new date set to the last day of the current month.
lastDayOfYear Returns a new date set to the last day of the current year.
lastInMonth Returns a new date in the same month with the last matching day-of-week.
next Returns the next day-of-week adjuster.
nextOrSame Returns the next-or-same day-of-week adjuster.
ofDateAdjuster Returns user-written adjuster.
previous Returns the previous day-of-week adjuster.
previousOrSame Returns the previous-or-same day-of-week adjuster.

How do I manipulate the value of LocalDate object?

In the following example we will learn how to manipulate a LocalDate object. There are many methods available for us to change the value of a LocalDate object. For example we can change the year, month and day of LocalDate object. We can use methods like withYear(), withDayOfMonth(), plusYears(), minusMonths(), etc. All these methods will return a new LocalDate object, the original LocalDate will stay unchanged.

Let’s see the following code example for demonstration on how to manipulate the value of LocalDate object.

package org.kodejava.example.datetime;

import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;

public class LocalDateManipulation {
    public static void main(String[] args) {
        absoluteAttributeManipulations();
        relativeAttributeManipulations();
    }

    private static void relativeAttributeManipulations() {
        System.out.println("LocalDateManipulation.relativeAttributeManipulations");
        LocalDate date1 = LocalDate.of(2015, Month.AUGUST, 17);
        LocalDate date2 = date1.minusYears(70);
        LocalDate date3 = date2.plusMonths(10);
        LocalDate date4 = date3.minusDays(15);
        LocalDate date5 = date4.plusWeeks(52);
        LocalDate date6 = date5.minus(52, ChronoUnit.WEEKS);

        System.out.println("of(2015, Month.AUGUST, 17)        => " + date1);
        System.out.println("date1.minusYears(70)              => " + date2);
        System.out.println("date1.plusMonths(10)              => " + date3);
        System.out.println("date3.minusDays(15)               => " + date4);
        System.out.println("date4.plusWeeks(52)               => " + date5);
        System.out.println("date5.minus(52, ChronoUnit.WEEKS) => " + date6);

    }

    private static void absoluteAttributeManipulations() {
        System.out.println("LocalDateManipulation.absoluteAttributeManipulations");
        LocalDate date1 = LocalDate.of(2016, Month.JANUARY, 1);
        LocalDate date2 = date1.withYear(2010);
        LocalDate date3 = date2.withMonth(Month.DECEMBER.getValue());
        LocalDate date4 = date3.withDayOfMonth(15);
        LocalDate date5 = date4.with(ChronoField.DAY_OF_YEAR, 100);

        System.out.println("of(2016, Month.JANUARY, 1)                 => " + date1);
        System.out.println("date1.withYear(2010)                       => " + date2);
        System.out.println("date2.withMonth(Month.DECEMBER.getValue()) => " + date3);
        System.out.println("date3.withDayOfMonth(15)                   => " + date4);
        System.out.println("date4.with(ChronoField.DAY_OF_YEAR, 100)   => " + date5);
    }
}

The results of this code snippet are:

LocalDateManipulation.absoluteAttributeManipulations
of(2016, Month.JANUARY, 1)                 => 2016-01-01
date1.withYear(2010)                       => 2010-01-01
date2.withMonth(Month.DECEMBER.getValue()) => 2010-12-01
date3.withDayOfMonth(15)                   => 2010-12-15
date4.with(ChronoField.DAY_OF_YEAR, 100)   => 2010-04-10

LocalDateManipulation.relativeAttributeManipulations
of(2015, Month.AUGUST, 17)        => 2015-08-17
date1.minusYears(70)              => 1945-08-17
date1.plusMonths(10)              => 1946-06-17
date3.minusDays(15)               => 1946-06-02
date4.plusWeeks(52)               => 1947-06-01
date5.minus(52, ChronoUnit.WEEKS) => 1946-06-02

How do I get the date of the first particular day after a specific date?

In this example we will learn how to get the date of the first particular day that fall after a specific date. In the code snippet below we will find the first Friday that fall after the new year of 2016. First let’s create a LocalDate object that represent the new year of 2016. We can use LocalDate.of() factory method to create the date object.

To get the first occurrence of a specific day-of-week from a date we create a TemporalAdjuster using the TemporalAdjusters.next() method and pass the day-of-week, in this case we pass DayOfWeek.FRIDAY.

After that we create another LocalDate that will hold the next Friday date. The get the date for the next Friday we call newYear.with() method and pass the TemporalAdjuster that we have created earlier.

Now, let’s try the code snippet below.

package org.kodejava.example.datetime;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;

public class GetFirstDayAfterDate {
    public static void main(String[] args) {
        //
        // Obtains the current date.
        //
        LocalDate newYear = LocalDate.of(2016, Month.JANUARY, 1);
        System.out.println("New Year = " + newYear);

        //
        // Gets the next Friday.
        //
        TemporalAdjuster nextFriday = TemporalAdjusters.next(DayOfWeek.FRIDAY);
        LocalDate nextFridayDate = newYear.with(nextFriday);
        System.out.printf("The first Friday after the new year of %s is %s%n", 
                newYear, nextFriday);
    }
}

The code snippet will print out the following result:

New Year = 2016-01-01
The first Friday after the new year of 2016-01-01 is 2016-01-08