본문 바로가기
기타/기타

[기타] 날짜와 시간 표현의 국제 표준인 ISO 8601에 대해서 자세히 알아보자. (RFC3339, ISO8601, JavaTime)

by 사바라다 2024. 7. 2.
반응형

개요

먼저 표준화라는것은 사물, 개념, 방법 및 절차 등에 대하여 합리적인 기준을 설정하여 그 기준에 맞추는 것을 말합니다. 표준이 필요한 이유는 생산, 소비, 서비스 등 다양한 분야에서 생산성과 경제성을 높이고자함입니다. 표준화가 되어있는 요소에 대해서는 재활용이 가능하고 서로 이해하는것도 좋습니다. 최근의 좋은 표준의 예시는 in/out port로써 C-Type으로 통일되어가고 있습니다. 기존에 각 제품마다 표준이 달라서 불편했던 생산과 소비에 이제 단일화된 표준으로 편리함을 제공해주고 있지요. 이것이 바로 표준화가 필요한 이유입니다.

오늘은 날짜와 시간 표현의 국제 표준인 ISO 8601과 RFC 3339에 대해서 알아보는 시간을 가져보려고합니다. 인터넷 표준에 비추어 볼때 우리가 따라야하는 표준은 ISO 8601과 RFC 3339가 있습니다. 두 표준은 어떤 차이가 있고 어떻게 사용하면 될까요 ? 그리고 오늘은 시간 표현의 표준에 대해서 두 각기 다른 표준의 차이를 이해하고 익혀보도록 하겠습니다.

간단한 ISO와 RFC의 정리

IT 업계의 표준화와 관련하여 영향을이 큰 기구 2가지를 본다면 ISO와 RFC 일것입니다. ISO는 International Standard Organization의 약자입니다. 즉, 국제 표준화 기구입니다. 그리고 RFC는 Request for Comments의 약자입니다. 이는 IETF라고 불리는 Internet Engineering Task Force 에서 표준화한 것입니다. ISO와 RFC 표준의 주요한 보면 아래와 같습니다.

ISO(Internation Standard Organization)

  • 국제적인 비정부 기구. IT 뿐만 아니라 다양한 산업 및 기술 분야에서 사용되는 광범위한 국제 표준을 제정
    • 제조, 통신, 안전 등 대부분의 산업 분야를 포괄
  • ISO 표준은 대부분 유료로 판매되며, 공식 사이트를 통해서 구매할 수 있습니다.

IETF의 RFC(Request for Comments)

  • IT와 관련된 프로토콜과 기준 표준을 다루는 조직이며 주로 IT 적인 아키텍처와 운영, 그리고 Application의 개발에 초점
  • 공개적으로 누구나 제안을 할 수 있으며 커뮤니티 검토와 피드백을 거칩니다.
  • 무료로 접근할 수 있으며 어디서든 접근할 수 있습니다.

ISO 8601 스펙과 실질 사용

ISO 8601은 날짜와 시간을 표현하는 국제 표준으로, 날짜와 시간을 인간이 읽기 쉬운 형식으로 제공하는 것을 목표로 합니다. 이 표준은 전 세계적으로 날짜와 시간 데이터를 명확하고 일관되게 교환하고 사용할 수 있도록 지원하기 위해 설계되었습니다. RFC에서는 ISO 8601을 차용하여 RFC 3339를 제작하였고 이는 인터넷에서의 프로토콜 및 기타 Application에서 날짜와 시간을 표현하여 일관되게 하기 위한 목적으로 설계되었습니다.

ISO와 RFC의 차이를 알았으니 이제 ISO 표준에서 날짜와 시간의 표준인 ISO 8601를 이해해보도록 하겠습니다. 해당 표준은 날짜와 시간을 읽기 쉬운 형식으로 제공하는 목표를 가진 표준화 형식입니다. 1719504294380(milliseconds from the epoch)와 같은 단순한 number로 구성되어있는 timestamp와 비교하는것을 떠올려보면 더 이해가 쉬우실 겁니다. 비교하면 특히 다양한 데이터 형식과 통신 프로토콜에 대해서 일관된 형식으로 날짜와 시간을 표현할 수 있습니다. 기본적인 날짜와 시간의 표현 케이스부터 기간, 특별한 표현들을 모두 실제 사용과 함께 알아보도록 하겠습니다.

날짜와 시간

java에서 1.8 버전 이상부터 시간을 관장하는 패키지가 생겼고 그중 Instant를 사용하면 아래와 같은 결과를 얻을 수 있습니다.

System.out.println(Instant.now()) // 2024-06-27T11:41:32.311141Z

2024-06-27T11:41:32.311141Z 이것은 ISO 8601 스펙에 부합하고 있으며 확장 형식을 사용하고 있습니다. 현재 표현으로 나온 이것을 우리는 2024년 6월 27일 UTC 기준 11시 41분 32.311141초라고 해석할 수 있습니다. 카테고리를 나눠서 보면 날짜 표현, 연결부, 시간 표현, 그리고 TimeZone에 대한 영역이 있습니다. 각 표현에 대해서 알아보면 아래와 같습니다.

날짜 표현
ISO 8601은 기본 형식과 확장 형식 두 가지를 제공합니다. 기본 형식에서는 구분자 없이 날짜와 시간을 표현하며 YYYYMMDD(예: 20240615)로 표현할 수 있습니다. 확장 형식에서는 구분자를 사용하여 더 명확하고 읽기 좋게 YYYY-MM-DD(예: 2024-06-15)로 각 구분 사이에 -를 추가하여 표현합니다.

  • YYYY는 년도를 나타냅니다. 0000(기원전 1년) ~ 9999 까지 사용가능합니다. YY와 같은 축약형은 권장하지 않습니다. 그 이유는 20으로 하면 1920인지 2020인지 표현이 모호해지기 때문입니다. 이는 다른 표현에서도 동일하게 적용됩니다.
  • MM은 월, DD는 일을 나타냅니다. 이 또한 M, D 처럼 줄여서 쓰는것은 허용되지 않습니다. MM의 1월은 01, DD의 1일은 01을 나타냅니다.
  • YYYY-MM-DD이 기본적인 형식이며 이 순서를 바꿀수는 없습니다. 그리고 YYYY을 생략하고 MM, DD만 쓸 수 없습니다. 단, 반대로 YYYY-MM 등으로 일을 빼고 년월만 작성, YYYY로 년도만 작성등은 가능합니다.

시간 표현
ISO 8601은 24시간제를 사용하여 표현합니다. 시간 표현 또한 날짜표현처럼 기본 표현과 확장 형식 표현이 있습니다. 기본 표현은 hhmmss.sss이고 확장 표현은 구분자 :를 추가해서 hh:mm:ss.sss 입니다.

  • hh는 시간, mm은 분, ss.sss는 초를 각각 나타냅니다. 이 또한 각각에 대해서 축약해서 사용하는것을 지원하지 않습니다.
  • hh는 00 ~ 24까지 가능하며 24는 다음날 00시와 동일합니다. 즉, 2024-06-24T24는 2024-06-25T00입니다.
  • mm은 00 ~ 59, ss.sss는 00 ~ 60 까지 허용하며 ss.sss에서 60은 윤년초에 해당합니다.
  • 초에 대해서 소수부는 정밀도를 높여주는 역할을 합니다.
  • 날짜 표현과 마찬가지로 ss를 생략, mm:ss를 생략 등의 뒷 부분은 생략이 가능하며 앞부분생략은 어렵습니다.

날짜와 시간의 결합
날짜와 시간을 각각도 지원하지만 날짜와 시간을 결합하는 것도 지원합니다. T를 사용하려 결합할 수 있습니다. 예를 들어, 2024년 6월 15일 오후 3시 30분은 2024-06-15T15:30으로 표현됩니다.

TimeZone 표현
ISO 8601의 표준 시간대는 지역 시간(local time), UTC 혹은 UTC의 오프셋으로써 표현할 수 있습니다. 지역 시간이라는 것은 말 그대로 사용자가 살고 있는 지역 시간을 따라가는 것입니다. 2024-06-27T11:41:32.311라는 표현이 바로 지역 시간을 따라가는 표현입니다. 하지만 이 경우 서로 다른 시간대 간의 통신이 일어날 때 표현이 애매해질 수 있습니다. 즉 내 PC의 시간이 한국 시간으로 표현되고 2024-06-27T11:41:32.311 라면 통신하는 상대방이 미국 시간으로 받으려면 어떻게 해야하는지에 대한 고민이 추가로 필요하게됩니다.

따라서 timezone을 사용해서 이를 표현할 수 있습니다. timezone은 UTC(협정 세계시[Coordinated Universal Time/Universal Time Coordinated])를 기본으로하며 UTC인 경우에는 Z 표현할 수 있습니다. 2024-06-27T11:41:32.311Z 라고 표현할 수 있으며 이는 한국 지역 시간으로 표현하면 2024-06-27T20:41:32.311와 동일합니다.

UTC에서 경도의 차이에 따라 시간이 다른것을 오프셋으로 표현합니다. 즉, 한국시간은 오후 1시인데, 중국시간이 오후 12시로 시차가 있는것을 말하는데요. 이는 위에서 Z를 붙였던것과 동일한 방법으로 ±[hh]:[mm], ±[hh][mm], 혹은 ±[hh] 형식의 시간 뒤에 덧붙여서 표현합니다. 00:00는 영국의 그리니치 천문대를 기준으로한다. 한국은 +09:00을 할당 받았는데 timezone이 포함된 시간을 표현하면 2024-06-27T20:41:32.311+09:00 입니다. 이는 2024-06-27T11:41:32.311Z와 동일한 날짜와 시간을 나타내는 표현입니다.

따라서 아래의 2개의 날짜 시간 표현식은 동일한것을 알 수 있습니다.

System.out.println(Instant.now()) // 2024-06-27T11:41:32.311141Z
System.out.println(Instant.now()) // 2024-06-27T20:41:32.311141+09:00

Week Date와 Ordinal Date, Period

기본적인 날짜와 시간의 표현만이 아닌 ISO 8601은 서수 날짜, 주 날짜 그리고 기간을 표현할 수 있습니다.

서수 날짜(연중 일자)(Ordinal Date)
서수 날짜라는것은 연도에서 지금이 몇일째인지 빠르게 알 수 있는 표현방식입니다. YYYY-DDD의 형식을 가집니다. YYYY는 년도를 가리키며 DDD는 날짜를 가리킵니다. DDD의 경우 000 ~ 366까지이며 366은 윤년의 케이스입니다. 예를 들어 2024-060이라고 하는것은 2024년도에서 60일째 되는날을 가리키며 이는 2024-02-29와 동일한 값을 나타냅니다.

System.out.println(
    LocalDate.from(DateTimeFormatter.ISO_ORDINAL_DATE.parse("2024-060")) // 2024-02-29
)

해당 계산법은 날짜의 기간을 비교할 때 간단히 할 수 있는 방법입니다.

주 날짜(Week Date)
주 날짜는 주를 기준으로 한 날짜 표현 방식입니다. 이 표현방법은 주에 번호를 메겨 사용하며 해당 스펙에서는 월요일을 주의 첫번째 날로 봅니다. 표현식으로는 YYYY-Www-D 형식을 사용합니다. YYYY는 년도, Www는 주 번호, 그리고 D는 해당 주에서 몇번째 요일(날)인지를 나타냅니다. 에를 들어 2024-W12-3는 2024년도의 12번째주의 3번째 날(수요일)을 뜻하며 이는 2024-03-20라고 해석할 수 있습니다.

System.out.println(
    LocalDate.from(DateTimeFormatter.ISO_WEEK_DATE.parse("2024-W12-3")) // 2024-03-20
)

기간(Period)과 반복

기간 특정 날짜 시간 A와 B 사이의 기간을 P로 시작하고 이를 기간으로 나타낼 수 있습니다. 만약 2024-06-27T11:41:32.311Z2024-06-30T11:41:32.311Z을 간격에 대해서 나타내면 아래처럼 표현할 수 있습니다.

2024-06-27T11:41:32.311Z/2024-06-30T11:41:32.311Z 이는 두 시간 사이의 간격을 나타냅니다. 그리고 이는 P로 나타내면 P3D 입니다. 이러한 표현 방식을 기간 표현방식이라고 합니다. 각 요소는 아래와 같습니다.

val period = Period.parse("P3D")
System.out.println(
    Instant.now().plus(period) // 2024-06-30T11:41:32.311Z
)

기간은 위에서 보이는 것처럼 P[n]Y[n]M[n]DT[n]H[n]M[n]S 혹은 P[n]W 형식으로 표현됩니다. 이와 같은 표현에서, [n]은 [n] 앞에 오는 각각의 날짜와 시간 요소들에 대한 값들로 대체된다고 이해하시면 됩니다.

  • P는 기간 표현의 시작을 알리는 기간(period)
  • Y는 연도 숫자 뒤에 오는 연도(year)
  • M은 월 숫자 뒤에 오는 월(month)
  • W는 주 숫자 뒤에 오는 주(week)
  • D는 일 숫자 뒤에 오는 일(day)
  • T는 시간 표현의 시작을 알리는 시간(time)
  • H는 시간 숫자 뒤에 오는 시간(hour)
  • M는 분 숫자 뒤에 오는 분(minute)
  • S는 초 숫자 뒤에 오는 초(seconds)

예를 들어, "P3Y6M4DT12H30M5S"는 "3년, 6개월, 4일, 12시간, 30분, 5초"의 기간을 나타냅니다.

마지막으로 간격에 대해서 반복을 명시할 수 있습니다. Prefix로 Rnn 또는 R을 사용하고 nn은 반복할 횟수가 들어갑니다. nn 횟수가 없다면 무한히 반복합니다. 예를 들어, "2008-03-01T13:00:00Z"을 시작으로 "P1Y2M10DT2H30M" 간격을 5번 반복하려면, "R5/2008-03-01T13:00:00Z/P1Y2M10DT2H30M"을 사용한다.

java time에는 해당 구현은 없고 찾아본 결과 time4j 라이브러리에서는 구현한것으로 보입니다.

RFC 3339가 ISO 8601과 다른점

이번 포스팅의 마지막으로 RFC 3339에 대해서 간단히 ISO 8601 차이점을 중심으로 알아보도록 하겠습니다. RFC 3339는 ISO 8601의 원칙을 디지털 및 네트워크 커뮤니케이션 환경에 맞추어 조정한 표준입니다. RFC 3339가 ISO 8601과 비교했을 때 강조되는 차이점은 ISO 8601은 다양한 사업군에서 사용하기에 유연성이 있습니다. 하지만 RFC 3339는 유연성 보다는 명확한 스펙으로 형상의 일치를 보장합니다. 예시는 다음과 같습니다.

시간대 표현

  • ISO 8601은 "+HH", "-HH" 형식을 사용하거나 단순히 "Z" (UTC를 의미)를 사용하여 시간대를 표현할 수 있습니다.
  • RFC 3339는 시간대에 대해 좀 더 명확한 규정을 제공하며, "Z"를 사용하거나 "+HH" 형식을 사용해야 한다는 것을 강조합니다. 이는 인터넷 프로토콜에서 시간대의 일관된 해석을 보장하기 위함입니다.
  • 즉, ISO 8601은 시간대 오프셋 표현에서 HHmmss 처럼 : 구분자 생략이 가능합니다. 하지만 RFC 3339는 보다 명확한 표현을 위해서 생략이 불가능합니다. 즉, 기본혀식은 제공하지 않고 확장 형식만 제공한다는 뜻입니다. ISO 8601은 2024-06-27T20:41:32.311141+0900 가능으로 :를 생략하는게 가능하지만 RFC 3339는 불가능합니다.

초의 표현

  • ISO 8601은 초를 선택적으로 포함할 수 있습니다.
  • RFC 3339는 보다 엄격하게 시간 표현을 규정하여 초를 항상 포함하도록 요구합니다. 또한, 필요에 따라 소수점 아래의 초도 표현할 수 있습니다 (예: 23:20:50.52).

RFC 3339는 특히 컴퓨터 시스템과 네트워크에서 사용하기 쉽도록 표준화된 형식을 제공하는 데 중점을 둡니다. 이는 프로그래밍에서 날짜와 시간을 처리할 때 발생할 수 있는 혼란과 버그를 최소화하는 데 도움을 줍니다.

참고

반응형

댓글