@DateTimeFormat을 이용한 날짜 포매팅

Kevin·2024년 2월 12일
2

JAVA

목록 보기
4/4
post-thumbnail

서론

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InsertExcelVO {
		
	private String modelName;
	
	@DateTimeFormat(pattern = "yyyy-MM-dd")	
	private Date openingDate; 
	
	@DateTimeFormat(pattern = "yyyy-MM-dd")	
	private Date deliveryDate;

위 코드는 원본의 코드를 각색한 코드이다.

나는 현재 Excel의 행들을 DB 스키마에 맞춰서 매핑시켜 넣어주는 기능을 구현 중에 있다.

이 때 나는 엑셀에 있는 날짜 데이터들을 DB Date 타입에 맞춰서 넣어주려고 하는데, 이 때 중간에서 타입을 변환 시켜주기 위해서 @DateTimeFormat이라는 어노테이션을 사용하였다.

@DateTimeFormat이 어떤 역할을 하길래 나는 사용했을까?


@DateTimeFormat이란?

/**
 * Declares that a field should be formatted as a date time.
 *
 * <p>Supports formatting by style pattern, ISO date time pattern, or custom format pattern string.
 * Can be applied to {@code java.util.Date}, {@code java.util.Calendar}, {@code java.long.Long},
 * Joda-Time value types; and as of Spring 4 and JDK 8, to JSR-310 <code>java.time</code> types too.
 *
 * <p>For style-based formatting, set the {@link #style()} attribute to be the style pattern code.
 * The first character of the code is the date style, and the second character is the time style.
 * Specify a character of 'S' for short style, 'M' for medium, 'L' for long, and 'F' for full.
 * A date or time may be omitted by specifying the style character '-'.
 *
 * <p>For ISO-based formatting, set the {@link #iso()} attribute to be the desired {@link ISO} format,
 * such as {@link ISO#DATE}. For custom formatting, set the {@link #pattern()} attribute to be the
 * DateTime pattern, such as {@code yyyy/MM/dd hh:mm:ss a}.
 *
 * <p>Each attribute is mutually exclusive, so only set one attribute per annotation instance
 * (the one most convenient one for your formatting needs).
 * When the pattern attribute is specified, it takes precedence over both the style and ISO attribute.
 * When the iso attribute is specified, if takes precedence over the style attribute.
 * When no annotation attributes are specified, the default format applied is style-based
 * with a style code of 'SS' (short date, short time).
 *
 * @author Keith Donald
 * @author Juergen Hoeller
 * @since 3.0
 * @see org.joda.time.format.DateTimeFormat
 */
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DateTimeFormat {

	/**
	 * The style pattern to use to format the field.
	 * <p>Defaults to 'SS' for short date time. Set this attribute when you wish to format
	 * your field in accordance with a common style other than the default style.
	 */
	String style() default "SS";

	/**
	 * The ISO pattern to use to format the field.
	 * The possible ISO patterns are defined in the {@link ISO} enum.
	 * <p>Defaults to {@link ISO#NONE}, indicating this attribute should be ignored.
	 * Set this attribute when you wish to format your field in accordance with an ISO format.
	 */
	ISO iso() default ISO.NONE;

	/**
	 * The custom pattern to use to format the field.
	 * <p>Defaults to empty String, indicating no custom pattern String has been specified.
	 * Set this attribute when you wish to format your field in accordance with a custom
	 * date time pattern not represented by a style or ISO format.
	 */
	String pattern() default "";

	/**
	 * Common ISO date time format patterns.
	 */
	public enum ISO {

		/**
		 * The most common ISO Date Format {@code yyyy-MM-dd},
		 * e.g. 2000-10-31.
		 */
		DATE,

		/**
		 * The most common ISO Time Format {@code HH:mm:ss.SSSZ},
		 * e.g. 01:30:00.000-05:00.
		 */
		TIME,

		/**
		 * The most common ISO DateTime Format {@code yyyy-MM-dd'T'HH:mm:ss.SSSZ},
		 * e.g. 2000-10-31 01:30:00.000-05:00.
		 * <p>This is the default if no annotation value is specified.
		 */
		DATE_TIME,

		/**
		 * Indicates that no ISO-based format pattern should be applied.
		 */
		NONE
	}

}

위 코드는 @DateTimeFormat 어노테이션의 코드이다.


위 설명을 조금 간략화 시켜보면 다음과 같다.

  • Spring에서 지원하는 어노테이션이다.
  • 이 어노테이션은 필드의 형식이 날짜 시간으로 지정되어야 함을 선언할 수 있게 해준다.
  • 날짜 시간 패턴이나 사용자 정의 패턴을 통한 형식을 지원한다.

위 설명이 무슨 말인지 더 쉽게 풀어가보면 아래와 같다.


@DateTimeFormat 어노테이션은 스프링 프레임워크에서 날짜와 시간을 나타내는 문자열을 자바의 java.util.Date, java.util.Calendar, java.time.LocalDate, java.time.LocalTime, java.time.LocalDateTime 등과 같은 날짜 및 시간 객체로 변환할 때 사용된다.


내부적으로 @DateTimeFormat 어노테이션은 문자열을 해당 날짜 또는 시간 객체로 변환하는 데 사용되는 포맷을 지정한다.

즉, 이 어노테이션을 사용하여 속성에 적용된 문자열을 해당하는 자바 날짜 또는 시간 객체로 변환할 때 사용할 포맷을 지정할 수 있다.


예를 들어, 다음과 같이 @DateTimeFormat 어노테이션을 사용하여 문자열을 날짜 객체로 변환하는 방법을 지정할 수 있다.

@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date startDate;

위 예제에서는 startDate 필드의 값이 "yyyy-MM-dd" 형식의 문자열로 제공되어야 하며, 이 문자열은 java.util.Date 객체로 자동 변환된다.


주의점

그러나 @DateTimeFormat 을 사용할 때 중요한 점이 있다.

@DateTimeFormat 은 @RequestBody나 @ResponseBody에서는 동작하지 않는다.

그 이유는 @RequestBody나 @ResponseBody 어노테이션은 Jackson 라이브러리가 사용된다.

Jackson 라이브러리는 Java에서 제공하는 JSON 파싱 라이브러리이다.


여기서 눈치가 빠른 사람들은 알았겠지만, 위 @DateTimeFormat은 Spring 어노테이션이다.

Spring에서 Jackson을 의존하기에 Spring은 Jackson을 알고 있지만, Jackson은 Spring을 알지 못한다.

그렇기에 Jackson 라이브러리가 사용되는 @RequestBody나 @ResponseBody를 이용한 역/직렬화에서는 작동하지 않는 것이다.

그러나 내 코드에서 @DateTimeFormat 이 잘 작동했던 이유는 @ModelAttribute@RequestParam에서는 Jackson 라이브러리가 동작하지 않기 때문이다.


그렇다면 @RequestBody나 @ResponseBody에서는 어떻게 날짜를 역/직렬화 하면 좋을까??

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class InsertExcelVO {
		
	private String modelName;
	
	@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MMM-yyyy", timezone = "Asia/Seoul")
	private Date openingDate; 
  • 이 때는 위와 같이 코드를 작성하면 된다.

추가적으로 Spring에서는 기본으로 사용하는 날짜 패턴(yyyy-MM-ddTHH:mm:ss)의 경우 별도의 어노테이션을 달지 않아도 자동으로 바인딩(==역직렬화)된다.


결론

  1. @RequestBody, @ResponseBody : @JsonFormat 사용하자
  2. @RequestParam, @ModelAttribute : @DateTimeFormat 사용하자
profile
Hello, World! \n

1개의 댓글

comment-user-thumbnail
2024년 8월 21일

꿀팁 감사합니다 : ]

답글 달기