dayjs 날짜 표기 카탈로그

날짜 표기 통일에 매핑 객체가 필요 없다 — dayjs는 포맷 문자열이 곧 키이자 값이다.1 i18n은 이름표(인사)와 내용(Hello)이 달라서 짝지어주는 객체가 필수였다. 그 습관이 여기까지 따라온 것이다.

Schema

이름 형태 역할
DATE_FORMATS readonly string[] (as const) 허용 표기의 단일 출처
DateFormat (typeof DATE_FORMATS)[number] 배열에서 파생된 닫힌 union
formatDate (date, format: DateFormat) => string 유일한 진입점

Examples

import dayjs from 'dayjs'

export const DATE_FORMATS = [
  'YYYY-MM-DD',
  'YYYY-MM-DDTHH:mm:ss',
  'HH:mm',
  'YYYY년 M월',
  'YY년 M월 D일',
  'YYYY.MM.DD',
  'YY.MM.DD',
  'YYYY.MM.DD(ddd)',
  'YYYY.MM.DD HH:mm',
] as const

export type DateFormat = (typeof DATE_FORMATS)[number]

export const formatDate = (
  date: dayjs.ConfigType,
  format: DateFormat,
): string => dayjs(date).format(format)

편입 기준

여러 곳에서 통일이 필요한 표기만 배열에 담는다. 일회성('M.D' 등)은 raw dayjs().format()으로 인라인 유지한다. 이 기준이 없으면 배열이 잡동사니 enum이 된다.

Guard

카탈로그에 있는 표기를 raw로 다시 쓰면 경고 — no-raw-date-format (no-restricted-syntax). 아직 작성하지 않았다. 타입은 formatDate를 우회한 호출을 막지 못하므로, 이 규칙이 없으면 카탈로그의 단일 출처 지위는 관행일 뿐이다.

타입이 못 잡는 전제

ddd(요일)는 진입점에서 dayjs.locale('ko')를 호출해야 한국어로 나온다.2 호출하지 않으면 Mon·Tue처럼 영어로 조용히 샌다 — 예외도 타입 오류도 없다. YYYY.MM.DD(ddd)는 그래서 다른 표기와 달리 런타임 전제를 가진 항목이다.

기각: 빌드타임 hoist / tagged-template 캐시

포맷 문자열을 빌드 때 미리 계산해 상수로 끌어올리거나(hoist) 결과를 캐시해두는 방법을 검토했다. 고유 패턴이 수십 개 규모라 중복 제거로도 컴파일 최적화로도 얻을 게 없다. 닫힌 타입 + 함수 하나로 충분하다. 패턴 수가 수백 단위로 늘면 재검토한다.

Footnotes

  1. dayjs — Format

  2. dayjs — Loading locale

#576