컴포넌트/필드 컴포넌트

DateTimePicker (일자시각선택)

VanillaFront 2026. 9. 10. 15:44

Va.DateTimePicker — 날짜 + 시간을 한 필드에 입력받는 캘린더 팝업

Va.DatePicker에 시간(시:분:초)까지 추가된 컴포넌트. 2024-12-25 14:30:00 형태로 날짜와 시간을 하나의 필드에서 다룹니다. 캘린더 팝업 UI + 마스킹된 필드 입력, 화면-저장 포맷 분리까지 DatePicker의 특성을 전부 계승합니다.

  • 클래스: Va.DateTimePicker  va_component.js:7470
  • short name: dateTimePicker
  • 상속: Va.PureField (DatePicker와 형제)
  • isContainer: true
  • 베이스 CSS: va-input (팝업 va-menu-pop, 달력 calendar-inner)
  • 소스 크기: 약 828줄


1. 기본 사용

{
    tagName: 'dateTimePicker',
    value: '20241225143000',           // 저장 값: YYYYMMDDHHMMSS 14자리
    dateFormat: 'ymd',
    timeFormat: 'hhmmss',
    onSelect: 'onDateTimeChange'
}
  • 화면 표시: 2024-12-25 14:30:00
  • 저장 값(getValue()): 20241225143000
  • 필드에 직접 타이핑 가능 (마스킹 적용)

2. Va.DatePicker와의 차이

항목Va.DatePickerVa.DateTimePicker

입력 대상 날짜만 날짜 + 시간
저장 값 길이 8자리 (YYYYMMDD) 14자리 (YYYYMMDDHHMMSS) 또는 12자리 (YYYYMMDDHHMM)
마스킹 ____-__-__ ____-__-__ __:__:__
timeFormat ✓ (hhmmss / hhmm / hm)
timeSeperator ✓ (: 기본)
dateTimeSeperator ✓ ( 기본, 날짜-시간 사이)
additionalInfo ✓ (추가 정보)
팝업 UI 캘린더만 캘린더 + 시분초 입력

한 줄 요약: "DatePicker + 시간(HH:MM:SS)까지."


3. 주요 속성

날짜 포맷 (DatePicker 계승)

속성기본값설명

dateFormat 'ymd' 화면 날짜 순서
dateSeperator '-' 화면 날짜 구분자
valueDateFormat 'ymd' 저장 날짜 순서
valueDateSeperator '' 저장 날짜 구분자

시간 포맷 (신규)

속성기본값설명

timeFormat 'hhmmss' 시간 표시 형식. hhmmss(초 포함) / hhmm(분까지) / hm(분까지 축약)
timeSeperator ':' 시간 구분자
valueTimeFormat 저장 시간 형식
valueTimeSeperator 저장 시간 구분자

날짜-시간 결합

속성기본값설명

dateTimeSeperator ' ' (공백) 화면에서 날짜와 시간 사이 구분자
valueDateTimeSeperator '' 저장 값에서 날짜와 시간 사이 구분자

범위

속성설명

min / max 최소/최대 날짜시간

팝업

속성기본값설명

expanded false 팝업 초기 상태
popWidth 260 팝업 폭

추가

속성설명

additionalInfo 팝업에 부가 정보 표시

4. 저장 값 길이 — 핵심 개념

timeFormat에 따라 저장 값 길이가 달라집니다:

timeFormat저장 값 형태길이

hhmmss (기본) YYYYMMDDHHMMSS 14자리
hhmm / hm YYYYMMDDHHMM 12자리

valueDateSeperator / valueTimeSeperator / valueDateTimeSeperator 지정 시 각 자리에 구분자 삽입:

{
    valueDateSeperator: '-',
    valueTimeSeperator: ':',
    valueDateTimeSeperator: ' '
}
// 저장 값: '2024-12-25 14:30:00'

5. 포맷 조합 예시

한국 표준 (기본)

{ tagName: 'dateTimePicker' }
// 화면: 2024-12-25 14:30:00
// 저장: 20241225143000

분까지만

{
    tagName: 'dateTimePicker',
    timeFormat: 'hhmm'
}
// 화면: 2024-12-25 14:30
// 저장: 202412251430

ISO 8601 스타일 저장

{
    tagName: 'dateTimePicker',
    valueDateSeperator: '-',
    valueTimeSeperator: ':',
    valueDateTimeSeperator: 'T'
}
// 화면: 2024-12-25 14:30:00
// 저장: 2024-12-25T14:30:00

미국식 화면 + 한국식 저장

{
    tagName: 'dateTimePicker',
    dateFormat: 'mdy',
    dateSeperator: '/',
    timeFormat: 'hhmm',
    valueDateFormat: 'ymd'
}
// 화면: 12/25/2024 14:30
// 저장: 202412251430

6. 이벤트

DatePicker와 동일:

이벤트시그니처발생 시점

select (component, element, value, evt) 팝업에서 값 선택
beforePop / afterPop / hidePop 팝업 표시/숨김  
expand / collapse 팝업 확장/축소  
focus / blur 표준  
change / keydown / keyup 표준  

7. 메서드 — 두 벌의 setter/getter

DatePicker와 마찬가지로 값 변환 로직이 두 벌:

메서드설명

setValue(value) valueDateFormat/valueTimeFormat 규약 값 세팅
getValue() 위 규약 형태로 반환. 마스킹 언더스코어가 남아 있으면 '' 반환 (아직 다 안 입력)
setRawValue(value) 항상 YYYYMMDDHHMMSS(또는 YYYYMMDDHHMM) 원시 값 세팅
getRawValue() 항상 원시 값 반환

팝업 제어

메서드설명

showDateTimePickerPop(evt) / hideDateTimePickerPop() 팝업 열기/닫기
showPop() (레거시)
hidePop() expanded=false + update()
expand() / collapse() 팝업 상태 토글
drawCalendar() 캘린더 재렌더링

상태

메서드설명

setDisabled(bool) / setReadOnly(bool) PureField 상속
focus() / blur() 포커스

8. getValue()의 특별한 동작 — 부분 입력 방어

timeFormat: 'hhmmss'일 땐 저장 값 총 19자리(구분자 포함), hhmm/hm이면 16자리가 완전한 형태.

필드에 마스킹 언더스코어가 남아 있으면(_) getValue()가 '' 반환 (va_component.js:8202, 8215):

if(tempValue.replaceAll('_', '').length !=19){
    return '';
}

의미: 사용자가 2024-12-25 14:__:__처럼 완성 안 된 상태로 폼을 제출해도 getValue()가 부분 값이 아니라 빈 문자열을 돌려줌 → 서버로 이상한 값 전송 방지.

⚠️ 완성됐다고 판단하는 기준이 마스킹 언더스코어 제거 후 길이라서, 사용자가 잘못된 형식으로 완성해도(예: 9999-99-99 99:99:99) getValue()가 그 값을 반환합니다. 별도 검증 필요.


9. 팝업 UI 구조

drawCalendar()가 렌더링:

  • 날짜 그리드 (DatePicker와 동일)
  • 시간 입력 영역 — 시:분:초 (또는 시:분)
  • 오늘/지금 버튼 (buttonToday)
  • 년월 이동 (buttonLeft, buttonRight)
  • min/max 범위 밖 비활성화

시간 부분은 스피너 또는 텍스트 입력 형태로 조작.


10. 내부 구조

DatePicker와 거의 동일:

<div elname="element" class="va-input [size]..." tag-name="dateTimePicker" field="true">
  <div elname="fieldWrapper" class="field-wrapper">
    <input elname="field" type="text" placeholder="____-__-__ __:__:__"
           style="border:0px">
    <div elname="focusLine" class="focus-line"></div>
    <div elname="calendarIconWrapper">
      <span elname="calendarIcon" class="icon menu ico_calender_ltr">📅</span>
    </div>
  </div>
  <div elname="popDiv" class="menu-button-pop-div">
    <div elname="pop" class="va-menu-pop" style="position:absolute; display:none">
      <div elname="popInner" class="calendar-inner">
        <!-- 캘린더 + 시분초 입력 -->
      </div>
    </div>
  </div>
</div>

11. Va.DateTimePicker vs 관련 컴포넌트

컴포넌트역할

Va.DatePicker 날짜만 (YYYYMMDD)
Va.DateTimePicker 날짜 + 시간 (YYYYMMDDHHMMSS)
Va.TimePicker 시간만
Va.YearPicker / Va.MonthPicker 년도/월만
Va.DateRangePicker 시작-종료 날짜 범위
Va.DateTimeField DateTimePicker + Field 래퍼 (라벨/검증)

12. 언제 쓰나

DateTimePicker가 맞을 때

  • 예약·일정 시각 (회의 시작, 배송 시각)
  • 게시글 예약 발행 시각
  • 로그·이벤트 타임스탬프 편집
  • 계약·마감 정확한 시각까지

다른 걸 쓸 때

  • 날짜만 → Va.DatePicker
  • 시간만 → Va.TimePicker
  • 라벨 붙은 폼 필드 → Va.DateTimeField
  • 시작-종료 시각 범위 → Va.DateTimeRangePicker(있다면) 또는 두 개 조합

13. 흔한 조합 예시

// 표준 (초까지)
{ tagName: 'dateTimePicker', value: '20241225143000' }

// 분까지
{
    tagName: 'dateTimePicker',
    timeFormat: 'hhmm',
    value: '202412251430'
}

// ISO 8601 저장
{
    tagName: 'dateTimePicker',
    valueDateSeperator: '-',
    valueTimeSeperator: ':',
    valueDateTimeSeperator: 'T'
    // getValue() → "2024-12-25T14:30:00"
}

// 미국식 화면
{
    tagName: 'dateTimePicker',
    dateFormat: 'mdy',
    dateSeperator: '/',
    timeFormat: 'hhmm'
    // 화면: 12/25/2024 14:30
}

// 범위 제한 (2024년만)
{
    tagName: 'dateTimePicker',
    min: '20240101000000',
    max: '20241231235959'
}

// 오늘 이후만 (예약)
{
    tagName: 'dateTimePicker',
    min: new Date().toISOString().slice(0,19).replace(/[-T:]/g,''),
    onSelect: 'onReservationTime'
}

14. 알아두면 좋을 주의사항

  1. 저장 값 길이가 timeFormat에 따라 달라짐 — 14자리(초) / 12자리(분) 헷갈리지 말 것.
  2. getValue()가 완성 안 된 값에 '' 반환 — 마스킹 언더스코어가 남으면 빈 문자열. 서버 전송 시 유용하지만 검증엔 별도 필요.
  3. 값 유효성 검증 없음  9999-99-99 같은 잘못된 값도 완성되면 그대로 반환.
  4. setValue()가 유효성 검사 안 함 — 부적절한 값도 그대로 파싱 시도.
  5. dateFormat과 valueDateFormat 혼동 — 화면 vs 저장. timeFormat도 마찬가지.
  6. valueDateTimeSeperator가 있어야 저장 값에 구분자 삽입 — 없으면 20241225143000처럼 붙어서 나옴.
  7. setValue() 로직에 버그성 코드  valueDateFormat이 mdy/dmy일 때 조건문이 this.dateFormat을 검사 (va_component.js:8115, 8119). valueDateFormat이어야 정확. 특정 조합에서 오동작 가능.
  8. hm과 hhmm이 같이 취급됨 — 코드에서 두 값 모두 "분까지"로 처리.
  9. 팝업 상태머신 참여 — 다른 팝업과 자동 상호 배타.
  10. min/max는 팝업에만 강제 — 필드 직접 타이핑으로 범위 밖 값도 입력 가능.
  11. 타임존 없음 — 로컬 문자열만. UTC 정확성 중요하면 별도 처리.
  12. value는 문자열 — Date 객체 넘기면 .replaceAll, .substring 호출에서 크래시.
  13. setRawValue() 사용 시 timeFormat 반영 — 원시 값 자릿수도 timeFormat에 따라 12/14 자리.
  14. 팝업 사이즈  popWidth가 260. 시분초까지 넣기엔 좁을 수 있으니 필요하면 확장.
  15. additionalInfo 속성 — properties에 선언은 있으나 실제 사용처는 코드 확인 필요.