3

application.yml configuration:

jackson:
    date-format: yyyy-MM-dd
    timestamp-format:yyyy-MM-dd HH:mm:ss
    serialization:
      write-dates-as-timestamps: false

Bean properties:

@Entity 
@Column(nullable = false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Temporal(TemporalType.DATE)
private Date date_created;

@Column(nullable = false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Temporal(TemporalType.TIMESTAMP)
private Date reg_date;

I set all Date fields as java.util.Date type which receive date in format yyyy-MM-dd and timestamp type(yyyy-MM-dd HH:mm:ss) according to request param style(yyyy-MM-dd or yyyy-MM-dd HH:mm:ss)

For using timestamp, I found the @Temporal(TemporalType.Date or Timestamp) which is mapping by DB Type.

Date and timestamp format is stored correctly like yyyy-MM-dd or yyyy-MM-dd HH:mm:ss.sss

RestController class:

@PostMapping("/")
public ResponseEntity<Object> create(@RequestBody CreateVO createVO, HttpServletRequest request) {
    System.out.println("planned_date> "+createVO.getDate_planned_start());
    System.out.println("regdate> "+createVO.getReg_date());    
}

Are set to:

planned_date> Wed Mar 20 09:00:00 KST 2019 // Date Result
regdate> Mon Oct 01 16:45:00 KST 2012 //Timestamp Result

However, I receive in RestController Date in different format than i expected.

Is there any solution to receive yyyy-MM-dd and yyyy-MM-dd HH:mm:ss in Controller?

I am wondering about application.yml settings as well. Because I am not sure how to set timestamp-format.

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
Sarah Son
  • 51
  • 1
  • 2
  • 7
  • Are you expecting the `Date` in your entity and/or the `Date` returned from `getDate_planned_start` and `getReg_date` to have the format you have specified? That is not possible. A `Date` cannot have a format. Also you should not want to use the `Date` class. It is poorly designed and long outdated. Don’t you want `LocalDate` and `LocalDateTime` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/) and [jackson-modules-java8](https://github.com/FasterXML/jackson-modules-java8)? – Ole V.V. Mar 20 '19 at 09:08
  • Possible duplicate of [display Java.util.Date in a specific format](https://stackoverflow.com/questions/6262310/display-java-util-date-in-a-specific-format) and/or [want current date and time in “dd/MM/yyyy HH:mm:ss.SS” format](https://stackoverflow.com/questions/8745297/want-current-date-and-time-in-dd-mm-yyyy-hhmmss-ss-format) – Ole V.V. Mar 20 '19 at 13:41

1 Answers1

4

First of all Date.toString method generates misleading output and we should not rely on it. Simple example:

SimpleDateFormat dateToStringFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", new Locale("us"));
Date parsed = dateToStringFormat.parse("Wed Mar 20 09:00:00 KST 2019");
System.out.println("Default toString: " + parsed);

dateToStringFormat.setTimeZone(TimeZone.getTimeZone("Asia/Seoul"));
System.out.println("With 'Asia/Seoul' TZ: " + dateToStringFormat.format(parsed));

dateToStringFormat.setTimeZone(TimeZone.getTimeZone("Chile/Continental"));
System.out.println("With 'Chile/Continental' TZ: " + dateToStringFormat.format(parsed));

prints:

Default toString: Wed Mar 20 01:00:00 CET 2019
With 'Asia/Seoul' TZ: Wed Mar 20 09:00:00 +0900 2019
With 'Chile/Continental' TZ: Tue Mar 19 21:00:00 -0300 2019

As you can see I parsed your example date Wed Mar 20 09:00:00 KST 2019 and print using toString method and formatted with two different timezones. So, everyone sees date combined with his timezone. Read more about:

We can not define date patters in configuration like you proposed. See available Jackson configuration options here.

You can configure format using com.fasterxml.jackson.annotation.JsonFormat annotation. Since Java 8 is available we should use java.time.* classes for time related properties. Example POJO class could like this:

import com.fasterxml.jackson.annotation.JsonFormat;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.MonthDay;

public class RequestPayload {

    @JsonFormat(pattern = "MM/dd")
    private MonthDay md;

    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate date;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime dateTime;

    // getters, setters, toString
}

To make it work we need to register JavaTimeModule module:

@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.modules(new JavaTimeModule());

    return builder;
}

If you can change your Bean properties to java.time.* classes just propagate these dates from Controller to DB. In other case see this question: Converting between java.time.LocalDateTime and java.util.Date.

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
  • Thank you for answering but i don't want to use @JsonFormat or change Field from Date to LocalDate i am looking for solution that Jackson configuration which receive (yyyy-MM-dd (request)> yyyy-MM-dd or yyyy-MM-dd HH:mm:ss (request) > yyyy-MM-dd HH:mm:ss) through configuration in application .yml ..! – Sarah Son Mar 21 '19 at 01:41
  • @SarahSon, I am afraid it is not possible to accept many date formats. You should pick the longest one and in case you want to send time just set zeroes. You can configure `Jackson2ObjectMapperBuilder` with `builder.dateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));` There is no option which allow to set date format for `Jackson` from configuration file like `application.yml`. – Michał Ziober Mar 21 '19 at 06:16