Spring input type date 값 가져오기 - spring input type date gabs gajyeoogi

Programming/Javascript

input type=datetime-local 최솟값 min, 현재값 value 적용하는 방법

Jan92 2021. 8. 8. 16:44

Spring input type date 값 가져오기 - spring input type date gabs gajyeoogi
input type="datetime-local"

프로젝트 중 input을 통해 날짜 외 시간도 함께 받아 오는 것이 필요하여 input type="datetime-loacl"을 사용하였습니다.

그 과정에서 사용한 최솟값 min 설정, 현재값 value 설정 방법에 대해서 알아보겠습니다.

min, value를 설정하기 위해서는 YYYY-MM-DDTHH:mm:ss 형식의 시간이 필요합니다.

Javascript의 날짜와 시간은 Date 객체로 표현할 수 있는데요.

let nowDate = new Date();
console.log('nowDate : ' + nowDate);
// nowDate : Sun Aug 08 2021 11:22:13 GMT+0900 (한국 표준시)


let toISOStringDate = new Date().toISOString();
console.log('toISOStringDate : ' + toISOStringDate);
// toISOStringDate : 2021-08-08T02:22:13.141Z

new Date(); 를 통해 날짜를 생성했을 때는 현재 시간이 출력되지만, toISOSting() 메서드를 사용하게 되면 ISO 형식의 문자열을 반환하는 대신 UTC의 시간대로 반환되게 됩니다.

UTC 시간은 한국 시간과 9시간 차이가 나기 때문에 현재 시간을 사용하기 위해서는 그 차이를 계산하는 과정이 필요합니다.

console.log(new Date(new Date().toString().split('GMT')[0]+' UTC').toISOString());
// 2021-08-08T11:24:48.000Z

console.log(new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000).toISOString());
// 2021-08-08T11:24:48:893Z

UTC 시간으로 출력되는 ISO 형식의 문자열을 현재 시간으로 변환시키는 방법은 위 2가지가 있습니다.

두 번째 방법의 원리는 getTimezoneOffset() 함수를 살펴보면, 

The getTimezoneOffset() method returns the time zone difference. in minutes, from current locale (host system settings) to UTC.

즉, 로컬 시간에서 UTC까지의 차이를 구하여 분으로 반환하는데 이 반환값을 밀리초 단위를 인자로 받는 new Date() 함수에 적용하기 위해 1000(밀리초) * 60(초)를 곱해서 밀리초 단위로 만들어 빼는 것입니다.

<body>
    <div>
        <input type="datetime-local" id="dateTimeLocal">
    </div>

    <script>
        let dateElement = document.getElementById('dateTimeLocal');
        let date = new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000).toISOString().slice(0, -5);
        dateElement.value = date;
        dateElement.setAttribute("min", date);
    </script>
</body>

변환시킨 값을 현재 시간 value, min 값에 적용하는 최종 코드입니다.

* 변환시킨 값은 YYYY-MM-DDTHH:mm:ss.sssz 형식인데 적용시킬 값은 ss 까지만 필요하기 때문에 뒤에 .sssz .slice(0, -5)를 통해 제거하고 YYYY-MM-DDTHH:mm:ss 값만 사용합니다.

현재 시간은 .value 를 통해 적용하고, 최솟값은 setAttribute("min", value)를 통해 적용합니다.

Spring input type date 값 가져오기 - spring input type date gabs gajyeoogi
min, value 적용 된 모습

min 값과 value 값이 적용 된 모습입니다.


저렇게 적용했을 때 문제점은 날짜 부분은 현재 날짜보다 이전의 날짜를 선택할 수 없도록 되어있지만 시간 부분은 현재 시간 이전의 날짜도 선택할 수 있다는 것이었습니다.

<body>
    <div class="m100">
        <h2>input datetime-local value, min, max</h2>
        <input type="datetime-local" id="dateTimeLocal" onchange="setMinValue()">
    </div>

    <script>
        let dateElement = document.getElementById('dateTimeLocal');
        let date = new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60000).toISOString().slice(0, -5);
        dateElement.value = date;
        dateElement.setAttribute("min", date);

        function setMinValue() {
            if(dateElement.value < date) {
                alert('현재 시간보다 이전의 날짜는 설정할 수 없습니다.');
                dateElement.value = date;
            }
        }
    </script>
</body>

해당 문제를 해결하기 위해서 onchange() 함수를 사용하여 시간이 바뀌었을 때 바뀐 value 값과 이전 date 값을 비교하여 value 값이 이전이라면 alert을 띄우고 value=date; 로 적용시키는 function을 추가하였습니다.

Spring input type date 값 가져오기 - spring input type date gabs gajyeoogi
현재 시간보다 이전의 날짜는 설정할 수 없습니다.

Spring

[Spring] @ModelAttribute 사용시 Date 날짜형 처리

yjseo 2016. 2. 2. 13:15

@ModelAttribute를 사용해 파라미터값들을 받을때 Date형의 input값이 비어있으면 오류가 발생한다.

컨트롤러 클래스 상단에 다음과 같이 소스를 넣어주어 해결한다.

@InitBinder
public void initBinder(WebDataBinder binder) {
	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
	binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}

개발을 하다가 컨트롤러에서 yyyy-MM-dd (예: 2019-10-23) 같은 형식의 문자열을 바로 Date 객체로 받을 수 있다는 것을 알게 되었습니다.

이걸 알기 전에는.. 매번 DTO의 값을 String bitrhDate같은 형식으로 줘서 실제 Entity의 값에 맞게 매번 파싱을 해줬는데 그렇게 할 필요가 없었습니다.

코드를 보겠습니다.

DTO

@NoArgsConstructor
@AllArgsConstructor
@Entity
@Getter
@Setter
public class Member extends DateAudit {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;

    private String pw;

    private Date birthDate;  ## 문제의 필드

}

컨트롤러의 회원가입하는 부분을 예제로 보겠습니다.

Controller

    //회원가입
    @PostMapping
    public ResponseEntity<JSONResult> createMember(MemberDTO memberDTO) {
  		//코드부분 ~~~~~
    }

저렇게 MemberDTO가 @ModelAttribute를 통해서 들어오는 경우
String을 Date 객체에 주입 해줄수가 없습니다.

그래서 이 Date 값을 바로 받기 위해서! 이렇게

DTO

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

DTO의 필드에 @DateTimeFormat 을 사용해주면 잘 들어오게 됩니다!


다른 방법

@ModelAttribute 가 아닌 @RequestParam 을 통해서 받는다면
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") Date birthDate
이렇게 사용하시면 됩니다.