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)

표기 추가하기

언제: 카탈로그에 없는 표기가 필요할 때.

절차

  1. 여러 곳에서 통일이 필요한 표기인가. 일회성('M.D' 등)이면 여기서 멈추고 raw dayjs().format()으로 인라인 유지한다 — 이 기준이 없으면 배열이 잡동사니 enum이 된다.
  2. DATE_FORMATS에 추가한다. DateFormat은 배열에서 파생되므로 따로 손댈 곳이 없다.
  3. ddd가 들어 있으면 진입점에 dayjs.locale('ko')가 있는지 확인한다.2

확인: 카탈로그에 있는 표기를 formatDate를 우회해 raw로 다시 쓴 곳이 없는가. 타입은 이걸 못 막는다no-raw-date-format (no-restricted-syntax)이 필요한데 아직 작성하지 않았다. 그 규칙이 없으면 카탈로그의 단일 출처 지위는 관행일 뿐이다.

함정: dayjs.locale('ko') 없이 ddd를 쓰면 Mon·Tue처럼 영어로 조용히 샌다 — 예외도 타입 오류도 없다. YYYY.MM.DD(ddd)는 그래서 다른 표기와 달리 런타임 전제를 가진 항목이다.

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

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

Footnotes

  1. dayjs — Format

  2. dayjs — Loading locale

출처

#576raw