본문 바로가기

javaScript&jQurey/REACT

[React] React Datepicker 시간 선택 커스텀

 

조건은 다음과 같다

 

 

- 예약 시간은 9:30-5:30 사이에 결정 (임시)
- 사용 시간은 최소 30분에서 최대 2시간
* 즉, 5:00 시작이라면 5:30까지 사용 가능

 


정리하면, 종료 시간의 최대값은 시작 시간의 2시간 이후로 하되, 5:30을 넘어가면 안된다

 

 

 

React Datepicker crafted by HackerOne

 

reactdatepicker.com

 

다행히도 React Datepicker의 공식문서(?)는 매우 친절해서, 수십 가지 경우의 수에 맞는 예제를 볼 수 있었다

결론적으로 구현한 코드는 다음과 같다

(SDatePicker는 DatePicker를 커스텀 한 것이고, 한글화 및 set(get)Hours 등의 함수들은 import해주면 된다)

 

 

const ReserveMain = () => {
    // 시작 시간
    const [startTime, setStartTime] = useState(null);
    // 종료 시간
    const [endTime, setEndTime] = useState(null);
    // 시작 시간을 선택했는지
    const [isSelected, setIsSelected] = useState(false);

    // 시작 시간이 선택되면 해당 시간 적용 및 isSelected를 true, endTime을 null로
    const onSelect = (time) => {
        setStartTime(time);
        setIsSelected(true);
        setEndTime(null);
    };

    return (
        <>
            <div><SDatePicker
                selected={startTime}
                onChange={onSelect}
                locale={ ko }
                showTimeSelect
                showTimeSelectOnly
                timeIntervals={30}
                minTime={setHours(setMinutes(new Date(), 30), 9)}
                maxTime={setHours(setMinutes(new Date(), 0), 17)}
                timeCaption="Time"
                dateFormat="aa h:mm 시작"
                placeholderText="시작 시간"
                className="mt-4"
            /></div>

            {isSelected ? // 시작 시간을 선택해야 종료 시간 선택 가능
                <div><SDatePicker
                selected={endTime}
                onChange={(time) => setEndTime(time)}
                locale={ ko }
                showTimeSelect
                showTimeSelectOnly
                timeIntervals={30}
                minTime={startTime}
                maxTime={setHours(setMinutes(new Date(), getMinutes(startTime)), getHours(startTime)+2)} // 시작 시간부터 2시간
                excludeTimes={[
                    // 시작 시간 제외
                    startTime,
                    // 5:00 선택 기준 최대 7:00까지 예외처리
                    setHours(setMinutes(new Date(), 0), 18),
                    setHours(setMinutes(new Date(), 30), 18),
                    setHours(setMinutes(new Date(), 0), 19)
                ]}
                timeCaption="Time"
                dateFormat="aa h:mm 종료"
                placeholderText="종료 시간"
                className="mt-3"
            /></div>
                
                : null 
            }
        </>
    );
};

 

다음 3가지 기능들을 묶어 onSelect함수를 임의로 만들었다

  • 입력받은 값을 시작 시간으로 저장함
  • 삼항 연산자로 종료 시간을 숨겼다가 시작 시간을 선택 하면 드러나도록 함
  • 종료 시간 선택 후에 다시 시작 시간을 변경하면 종료 시간을 null로 되돌림


minTime과 maxTime으로 최소/최대 시간을 설정하는데, startTime에서 시간과 분을 추출해 종료 시간의 최대값을 정의하고 시작 시간 5:00 기준 7:00까지 예외처리 하기위해 excludeTimes에 넣어줬다
(이미 예약된 시간 예외처리도 useEffect로 받아와서 excludeTimes에 넣어주면 될 듯 하다)

다음과 같이 잘 구현되었다!

 

 

 

+++

filterPassedTime으로 이미 지나간 시간을 선택하지 못하도록 해주자

 

    // 현재 시간 기준 지나간 시간 선택 불가
    const filterPassedTime = (time) => {
        const currentDate = new Date();
        const selectedDate = new Date(time);
    
        return currentDate.getTime() < selectedDate.getTime();
    };
    
    
    <SDatePicker
    	filterTime={filterPassedTime}
    />

 

 

출처 : https://programming-oddments.tistory.com/215

 

========================실습===================

 

                <div className="input_bx" style={{ float: "left"}}>
                        <div className="input_bx" style={{ float: "left"}}>
                        <p className="tit">일시</p>
                        <DatePicker
                            locale={ko} //한국 달력 표시
                            dateFormat="yyyy년 MM월 dd일 HH:mm" // 표시 양식
                            timeIntervals={10}// 시간 간격
                            showTimeSelect // 시간선택 노출
                            wrapperClassName='datePicker'

                            selected={dto.testdate}
                            onChange={(date) =>
                                setDamage_details_dto((_info: DamageDetailDTO) => {
                                    return {
                                        ..._info,
                                        testdate: date!
                                    }
                                })
                            }
                        />

                    </div>

 

 

달력에 데이터 포맷을 맞추는데만 오래걸렸다 날짜가 디비에 저장되는 형태랑 프론트에서 받는 형태가 달라서 포맷이랑 타입만 맞춰주면 쉽게 커스텀 가능함

 

Date date = new Date();
date.setTime(System.currentTimeMillis());

String datePattern1 = "yyyyMMdd";
SimpleDateFormat format1 = new SimpleDateFormat(datePattern1);
System.out.println(format1.format(date));

String datePattern2 = "EE MMM d, yy";
SimpleDateFormat format2 = new SimpleDateFormat(datePattern2);
System.out.println(format2.format(date));

String datePattern3 = "h:mm a EE MMM d, yy";
SimpleDateFormat format3 = new SimpleDateFormat(datePattern3);
System.out.println(format3.format(date));

String datePattern4 = "yyyyy.MMMMM.dd GGG hh:mm aaa";
SimpleDateFormat format4 = new SimpleDateFormat(datePattern4);
System.out.println(format4.format(date));

String datePattern5 = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
SimpleDateFormat format5 = new SimpleDateFormat(datePattern5);
System.out.println(format5.format(date));

결과 -

20210329
Mon Mar 29, 21
9:33 AM Mon Mar 29, 21
02021.March.29 AD 09:33 AM
2021-03-29T09:33:30.976+0900

 

 

출처 :&nbsp;https://hbase.tistory.com/79

대소문자에 따라서 의미가 달라질 수 있으니 주의해야한다. 예를 들어 대문자 'M'은 Month를 의미하고, 소문자 'm'은 Minute를 의미한다.

'yyyyMMdd' 패턴을 위 표에서 해석해보면

  • yyyy : 년도를 4글자로 표현
  • MM : 월 단위를 2글자로 표현
  • dd : 일 단위를 2글자로 표현