HTML의 날짜와 시간 형식

HTML의 특정 요소는 날짜 와/또는 시간 값을 사용합니다. 이러한 값을 지정하는 문자열의 형식은 본 문서에서 설명합니다.

이러한 형식을 사용하는 요소로는 사용자가 날짜, 시간 또는 둘 다 선택하거나 지정할 수 있는 <input> 요소의 특정 형태와, 내용 삽입 또는 삭제 시점을 나타내는 datetime 속성을 포함한 <ins><del> 요소가 있습니다.

<input> 요소의 경우, 날짜 및/또는 시간을 나타내는 문자열을 포함하는 value 속성의 type 값은 다음과 같습니다.

예제

HTML에서 사용되는 날짜 및 시간 문자열의 세부 형식을 다루기 전에, 자주 사용되는 형식의 예제를 통해 문자열이 어떤 형태로 작성되는지 확인해 봅시다.

HTML 날짜 및 시간 문자열 예제
문자열 날짜 및/또는 시간
2005-06-07 2005년 6월 7일 [자세히 보기]
08:45 오전 8시 45분 [자세히 보기]
08:45:25 오전 8시 45분 25초 [자세히 보기]
0033-08-04T03:40 33년 8월 4일 오전 3:40 [자세히 보기]
1977-04-01T14:00:30 1977년 4월 1일 오후 2시 0분 30초 [자세히 보기]
1901-01-01T00:00Z 1901년 1월 1일 UTC 자정 [자세히 보기]
1901-01-01T00:00:01-04:00 1901년 1월 1일, 동부 표준시(EST) 기준 자정 이후 1초 [자세히 보기]

기본 정보

HTML에서 사용하는 날짜 및 시간 문자열 형식을 살펴보기 전에, 이를 정의하는 기본적인 사실을 이해하는 것이 유용합니다. HTML은 날짜와 시간 문자열에 ISO 8601 표준을 변형한 형식을 사용합니다. HTML 사양은 ISO 8601보다 더 구체적인 파싱 알고리즘을 포함하고 있으므로, HTML과 호환되는 문자열인지 확인하기 위해 사용하는 형식의 설명을 검토하는 것이 좋습니다.

문자 집합

HTML의 날짜 및 시간은 항상 ASCII 문자 집합을 사용하는 문자열로 작성됩니다

연도 표기

HTML에서 날짜 문자열의 기본 형식을 단순화하기 위해, 명세서는 모든 연도를 현대(또는 역산 그레고리력) 그래고리력으로 표기하도록 요구합니다. 사용자 인터페이스는 다른 달력을 사용하여 날짜를 입력할 수 있도록 할 수 있지만, 기본 값은 항상 그레고리력을 사용합니다.

그레고리력은 1582년에 만들어져 기존의 율리우스력을 대체했지만, HTML의 목적상 그레고리력은 기원후 1년까지 확장하여 사용됩니다. 따라서 이보다 이전의 날짜를 사용할 경우, 이를 고려해야 합니다.

HTML에서 날짜를 표기할 때 연도는 항상 최소 네 자릿수여야 하며, 1000년 이전의 연도는 앞에 (0)으로 채워야 합니다. 예를 들어, 72년은 0072로 작성합니다. 또한 기원전 1년(B.C.E. 1년) 이전의 연도는 지원하지 않으므로, HTML에서는 기원전 연도(예: B.C.E. 1년 또는 그 이전)는 사용할 수 없습니다.

한 해는 일반적으로 365일로 구성되지만, 윤년 에는 예외적으로 하루가 추가됩니다.

윤년

윤년은 400으로 나누어떨어지는 해 또는 4로 나누어떨어지지만 100으로는 나누어떨어지지 않는 해를 말합니다. 달력상 1년은 일반적으로 365일이지만, 지구가 태양을 한 바퀴 도는 데 실제로 걸리는 시간은 약 365.2422일입니다. 윤년은 달력을 지구의 실제 공전 주기와 동기화하기 위해 조정하는 역할을 합니다. 4년마다 하루를 추가함으로써 평균적인 1년의 길이를 약 365.25일로 만들어 실제와 비슷하게 맞춥니다.

윤년 알고리즘에 추가된 조정(연도가 400으로 나누어떨어질 때 윤년으로 계산하고, 100으로 나누어떨어질 때 윤년을 제외)은 평균 1년의 길이를 더욱 정확한 365.2425일에 가깝게 조정합니다. 과학자들은 남은 약 0.0003일을 보완하고 지구 자전의 점진적인 자연적 감속을 고려하기 위해 가끔씩 윤초(leap second)를 추가하기도 합니다(실제로 그렇습니다).

02월 즉 2월은 일반적으로 28일이지만, 윤년에는 29일이 됩니다.

한해의 달들

1년은 12개월로 구성되며, 각 월은 1부터 12까지 번호가 지정됩니다. 월은 항상 01부터 12 사이의 값을 가지는 두 자리의 ASCII 문자열로 표현됩니다. 월 번호와 해당 월의 이름(및 일 수)에 대한 자세한 내용은 달의 일 수 섹션의 표를 참조하세요.

달의 일 수

월 번호 1, 3, 5, 7, 8, 10, 12는 각각 31일입니다. 월 번호 4, 6, 9, 11은 각각 30일입니다. 월 번호 2, 즉 2월은 대부분의 해에 28일이지만, 윤년에는 29일입니다. 아래 표에 자세히 정리되어 있습니다.

연도의 월과 각 월의 일 수
월번호 이름 (한국어) 일 수
01 1월 31
02 2월 28 (윤년에는 29)
03 3월 31
04 4월 30
05 5월 31
06 6월 30
07 7월 31
08 8월 31
09 9월 30
10 10월 31
11 11월 30
12 12월 31

주 문자열

주 문자열은 특정 연도의 주를 지정합니다. 유효한 주 문자열은 유효한 연도 번호, 하이픈 문자(-, 또는 U+002D), 대문자 W(U+0057), 그리고 두 자리 숫자로 이루어진 연도의 주 번호로 구성됩니다.

연도의 주 번호는 01에서 53 사이의 두 자리 문자열입니다. 각 주는 월요일에 시작해 일요일에 끝납니다. 따라서 1월 초의 며칠은 이전 주-연도의 일부로 간주될 수 있으며, 12월 말의 며칠은 다음 주-연도의 일부로 간주될 수 있습니다. 연도의 첫 번째 주는 해당 연도의 첫 번째 목요일이 포함된 주입니다. 예를 들어, 1953년의 첫 번째 목요일은 1월 1일이었으므로, 해당 주는 월요일인 12월 29일부터 시작하며 연도의 첫 번째 주로 간주됩니다. 따라서 1952년 12월 30일은 1953-W01 주에 해당합니다.

연도가 53주를 가지려면 다음 조건 중 하나를 만족해야 합니다.

  • 달력 연도의 첫째 날(1월 1일)이 목요일일 경우 또는
  • 연도의 첫째 날(1월 1일)이 수요일이며, 해당 연도가 윤년일 경우

위의 조건을 만족하지 않는 연도는 모두 52주로 구성됩니다.

주 문자열 주와 연도 (날짜 범위)
2001-W37 2001년 37주 (2001년 9월 10일-16일)
1953-W01 1953년 1주 (1952년 12월 29일-1953년 1월 4일)
1948-W53 1948년 53주 (1948년 12월 27일-1949년 1월 2일)
1949-W01 1949년 1주 (1949년 1월 3일-9일)
0531-W16 531년 16주 (531년 4월 13일-19일)
0042-W04 42년 4주 (42년 1월 21일-27일)

주 번호와 연도 번호 모두 앞에 0으로 채워져야 하며, 연도는 네 자리, 주 번호는 두 자리로 표현됩니다.

월 문자열

월 문자열은 특정 월을 나타내며, 단순히 "1월" 같은 일반적인 월이 아니라 특정 연도와 연결된 월을 나타냅니다. 즉, HTML 월 문자열은 "1972년 1월"과 같은 연도와 월이 짝지어진 형식을 표현합니다.

유효한 월 문자열은 유효한 연도 번호(최소 네 자리 숫자로 이루어진 문자열), 하이픈 문자(-, 또는 U+002D), 두 자리 숫자로 된 월 번호로 구성됩니다. 여기서 01은 1월을, 12는 12월을 나타냅니다.

월 문자열 월과 연도
17310-09 17310년 9월
2019-01 2019년 1월
1993-11 1993년 11월
0571-04 571년 4월
0001-07 1년 7월

모든 연도는 최소 네 자리 숫자로 표현됩니다. 네 자리가 되지 않는 연도는 앞에 0으로 채워야 합니다.

날짜 문자열

유효한 날짜 문자열은 월 문자열 뒤에 하이픈 문자(-, 또는 U+002D), 그리고 두 자리 숫자로 된 달의 일수가 이어진 형태로 구성됩니다.

날짜 문자열 전체 날짜
1993-11-01 1993년 11월 1일
1066-10-14 1066년 10월 14일
0571-04-22 571년 4월 22일
0062-02-05 62년 2월 5일

시간 문자열

시간 문자열은 분, 초 또는 밀리초까지의 정밀도로 특정 시간을 지정할 수 있습니다. 시간 또는 분만 단독으로 지정하는 것은 허용되지 않습니다. 유효한 시간 문자열은 최소한 두 자리 시간 뒤에 콜론(:, U+003A), 그리고 두 자리 분으로 구성됩니다. 선택적으로 분 뒤에 또 다른 콜론과 두 자리 초를 추가할 수 있습니다. 밀리초는 소수점 문자(., U+002E) 뒤에 1~3자리 숫자를 추가하여 선택적으로 지정할 수 있습니다.

추가적인 기본 규칙은 다음과 같습니다.

  • 시간은 항상 24시간제로 지정되며, 00은 자정, 오후 11시는 23으로 표현됩니다. 범위는 00에서 23까지로 한정됩니다.
  • 분은 반드시 00에서 59 사이의 두 자리 숫자로 지정되어야 합니다.
  • 초가 생략된 경우(분까지만 정확히 지정하는 경우) 분 뒤에 콜론을 추가하지 않습니다.
  • 초가 지정된 경우 정수 부분은 00에서 59 사이여야 하며, 초 값으로 60 또는 61과 같은 윤초를 지정할 수 없습니다.
  • 초가 정수로 지정된 경우, 소수점으로 끝날 수 없습니다.
  • 초의 소수 부분(밀리초)을 포함하려면, 초 뒤에 소수점을 추가하고 1~3자리 숫자를 적습니다. 이는 밀리초를 나타냅니다.
시간 문자열 시간
00:00:30.75 오전 12:00:30.75 (자정 이후 30.75초)
12:15 오후 12:15
13:44:25 오후 1:44:25 (오후 1:44 이후 25초)

로컬 날짜 및 시간 문자열

유효한 datetime-local 문자열은 날짜 문자열과 시간 문자열을 연결하고, 이 둘 사이를 문자 T 또는 공백 문자로 구분합니다. 이 문자열에는 시간대에 대한 정보가 포함되지 않으며, 날짜와 시간은 사용자의 로컬 시간대를 기준으로 해석됩니다.

datetime-local 입력의 을 설정하면, 문자열은 표준 형식으로 정규화됩니다. 정규화datetime 문자열은 항상 날짜와 시간을 구분하는 데 문자 T를 사용하며, 가능한 한 짧게 표현됩니다. 이를 위해 초 값이 :00인 경우 초 구성 요소를 생략합니다.

유효한 datetime-local 문자열 예시
날짜/시간 문자열 정규화된 날짜/시간 문자열 실제 날짜와 시간
1986-01-28T11:38:00.01 1986-01-28T11:38:00.01 1986년 1월 28일 오전 11:38:00.01
1986-01-28 11:38:00.010

1986-01-28T11:38:00.01

정규화 후, 이 문자열은 이전의 datetime-local 문자열과 동일합니다. 공백 문자는 문자 T로 대체되었으며, 초의 소수 부분에서 불필요한 끝자리 0이 제거되어 문자열이 가능한 한 짧아졌습니다.

1986년 1월 28일 오전 11:38:00.01
0170-07-31T22:00:00

0170-07-31T22:00

이 날짜의 정규화된 형식에서는 초의 값이 0임을 나타내는 :00이 제거되었습니다. 초 값이 0일 경우 초는 선택 사항이며, 정규화된 문자열은 문자열 길이를 최소화합니다.

170년 7월 31일 오후 10:00

글로벌 날짜 및 시간 문자열

글로벌 날짜 및 시간 문자열은 날짜와 시간뿐만 아니라 해당 시간이 발생한 시간대도 지정합니다. 유효한 글로벌 날짜 및 시간 문자열로컬 날짜 및 시간 문자열과 동일한 형식이지만, 시간 뒤에 시간대 문자열이 추가됩니다.

시간대 오프셋 문자열

시간대 오프셋 문자열은 표준 시간 기준에서의 시간대 오프셋을 양수나 음수로 시간과 분 단위로 지정합니다. 두 가지 표준 시간 기준이 있으며, 거의 같지만 정확히 일치하지는 않습니다.

  • 1960년대 초 조정된 세계 표준시 (UTC))가 설정된 후 날짜의 경우, 시간 기준은 Z이며, 오프셋은 (영국 그리니치 왕립 천문대를 통과하는) 경도 0º 의 본초 자오선 시점의 특정 시간대 오프셋을 나타냅니다.

  • UTC 이전의 날짜에 대해서는 시간 기준이 대신 UT1으로 표현되며, 이는 그리니치 천문대에서의 현대적인 태양 시간입니다.

시간대 문자열은 날짜와 시간 뒤에 바로 추가됩니다. 시간이 UTC로 지정된 경우 Z를 시간대 오프셋 문자열로 사용하여 표시할 수 있습니다. 그렇지 않으면 시간대 문자열은 다음과 같이 구성됩니다.

  1. 오프셋의 부호를 나타내는 문자: 그리니치 천문대 동쪽 시간대는 플러스 기호(+, 또는 U+002B), 서쪽 시간대는 마이너스 기호(-, 또는 U+002D)를 사용합니다.
  2. 그리니치 천문대에서 시간대가 오프셋된 두 자릿수 시간 숫자. 이 값은 00에서 23 사이여야 합니다.
  3. 선택적으로 콜론(:) 문자가 올 수 있습니다.
  4. 두 자릿수의 분 단위 숫자인 이 값은 00에서 59 사이여야 합니다.

이 형식은 시간대가 -23:59에서 +23:59 사이일 수 있지만, 현재 시간대 오프셋 범위는 -12:00에서 +14:00 사이이며, 현재는 00, 30, 또는 45분으로만 오프셋된 시간대가 존재합니다. 이는 국가들이 언제든지 원하는 방식으로 시간대를 조정할 수 있기 때문에 변할 수 있습니다.

유효한 글로벌 날짜 및 시간 문자열 예시
글로벌 날짜 및 시간 문자열 실제 글로벌 날짜 및 시간 그리니치 천문대 기준 날짜와 시간
2005-06-07T00:00Z 2005년 6월 7일 자정 UTC 2005년 6월 7일 자정
1789-08-22T12:30:00.1-04:00 1789년 8월 22일 오후 12시 30분 0.1초 (동부 표준시, EDT) 1789년 8월 22일 오후 4시 30분 0.1초
3755-01-01 00:00+10:00 3755년 1월 1일 자정 (호주 동부 표준시, AEST) 3754년 12월 31일 오후 2시

날짜 문제

데이터 저장 및 정확도 문제로 인해 클라이언트 측과 서버 측에서 몇 가지 문제를 인식하는 것이 좋습니다.

Y2K38 문제 (주로 서버 측)

JavaScript는 날짜를 저장할 때 배열의 모든 숫자처럼 부동 소수점 방식을 사용합니다. 이는 Y2K38 문제로부터 JavaScript 코드가 영향을 받지 않는다는 의미입니다. 하지만 정수 강제 변환 또는 비트 연산을 사용할 경우 문제가 발생할 수 있는데, 모든 JavaScript 비트 연산자가 32비트 부호 있는 정수를 사용하기 때문입니다.

이 문제는 서버 측에서 발생합니다. 2^31 - 1보다 큰 날짜를 저장하는 문제입니다. 이를 해결하려면 서버에서 날짜를 부호 없는 32비트 정수, 부호 있는 64비트 정수 또는 배정밀도 부동소수점으로 저장해야 합니다. 서버가 PHP로 작성되었다면, PHP 8 또는 7로 업그레이드하고 하드웨어를 x86_64 또는 IA64로 업그레이드하는 것만으로 해결될 수 있습니다. 만약 다른 하드웨어를 사용해야 한다면, 32비트 가상 머신 내에서 64비트 하드웨어를 에뮬레이션할 수 있지만, 대부분의 가상 머신은 이러한 유형의 가상화를 지원하지 않으며, 안정성 문제와 성능 문제로 인해 추천되지 않습니다.

Y10K 문제 (주로 클라이언트 측)

I많은 서버에서는 날짜를 문자열 대신 숫자로 저장합니다—고정 크기의 숫자로 형식에 관계없이 저장됩니다(단, 엔디언 방식에 따라 다를 수 있음). 10,000년 이후로는 숫자가 그 이전보다 조금 더 커지게 되므로, 많은 서버에서는 10,000년 이후에 제출된 양식에서 문제가 발생하지 않습니다.

문제는 클라이언트 측에서 발생합니다: 4자리 이상의 연도를 가진 날짜를 파싱하는 문제입니다.

html
<!--10000년 1월 1일 자정: Y10K의 정확한 시간-->
<input type="datetime-local" value="+010000-01-01T05:00" />

그것은 매우 간단합니다. 코드를 작성할 때 연도의 자릿수에 대해 유연하게 준비하세요. 5자리 이상에 대해서도 준비해야 합니다. 다음은 JavaScript 코드로 값을 설정하는 방법입니다.

js
function setValue(element, date) {
  const isoString = date.toISOString();
  element.value = isoString.substring(0, isoString.indexOf("T") + 6);
}

Y10K 문제는 왜 걱정해야 할까요? 그것이 여러 세기가 지나고 나서 발생할 일이기 때문입니다. 정확히 말하면, 그때는 이미 여러분은 죽어 있을 것이므로, 여러분의 소프트웨어를 사용하는 회사는 이 문제를 해결할 수 있는 개발자가 없는 상태로 여러분의 소프트웨어를 사용하게 됩니다.

참조