12시간제와 24시간제 시간 형식 간 전환 방법

JavaScript를 사용하여 사용자 환경설정에 따라 AM/PM이 있는 시간 또는 24시간 형식으로 시간 표시하기

소개

시간은 전 세계적으로 다르게 표시됩니다. 미국인들은 일반적으로 2:30 PM을 보는 반면, 독일인들은 14:30을 보며, 둘 다 같은 순간을 나타냅니다. 한 가지 형식으로만 시간을 표시하면 모든 사용자가 같은 규칙을 따른다고 가정하는 것입니다.

익숙하지 않은 형식으로 시간을 표시하면 마찰이 생깁니다. 14:30을 예상하는 사용자가 2:30 PM을 보면 시간을 머릿속으로 변환해야 합니다. 2:30 PM을 예상하는 사용자가 14:30을 보면 같은 문제에 직면합니다. 이러한 인지적 부담은 애플리케이션에 표시되는 모든 시간에 대해 반복됩니다.

자바스크립트는 시간 형식을 자동으로 처리하는 Intl.DateTimeFormat API를 제공합니다. 이 강의에서는 시간 형식이 왜 다양한지, API가 12시간제와 24시간제 표시를 어떻게 제어하는지, 그리고 언제 로케일 기본값을 재정의해야 하는지 설명합니다.

로케일에 따라 시간 형식이 다른 이유

서로 다른 지역에서는 시간을 표시하는 다양한 규칙이 발전했습니다. 이러한 규칙은 문화적 관행, 교육 시스템 및 역사적 선례를 반영합니다. 어떤 단일 형식도 보편적이지 않습니다.

미국, 캐나다, 호주 및 필리핀에서는 AM/PM 표시기가 있는 12시간 형식이 표준입니다. 오후 시간은 2:30 PM으로 표시됩니다.

유럽, 라틴 아메리카 및 아시아 대부분 지역에서는 24시간 형식이 표준입니다. 같은 시간이 AM/PM 표시기 없이 14:30으로 표시됩니다.

일부 지역에서는 상황에 따라 두 형식을 모두 사용합니다. 영국은 교통 일정에는 24시간 형식을 사용하지만 일상 대화에서는 12시간 형식을 사용합니다.

시간을 표시할 때는 사용자의 지역과 상황에 대한 기대에 맞춰야 합니다.

12시간제와 24시간제의 의미

12시간제는 하루를 두 개의 12시간 기간으로 나눕니다. 시간은 12시부터 11시까지 진행된 다음 다시 시작됩니다. 이 시스템은 자정부터 정오까지는 AM(ante meridiem)을, 정오부터 자정까지는 PM(post meridiem)을 사용합니다. 자정은 12:00 AM에 시작되고 정오는 12:00 PM에 발생합니다.

12:00 AM → 자정
1:00 AM → 자정 후 1시간
11:59 AM → 정오 1분 전
12:00 PM → 정오
1:00 PM → 정오 후 1시간
11:59 PM → 자정 1분 전

24시간제는 시간을 0부터 23까지 연속적으로 계산합니다. 자정은 00:00에 시작되고 하루는 23:59에 끝납니다. 각 시간마다 고유한 번호가 있기 때문에 AM/PM 표시기가 필요하지 않습니다.

00:00 → 자정
01:00 → 자정 후 1시간
11:59 → 정오 1분 전
12:00 → 정오
13:00 → 정오 후 1시간
23:59 → 자정 1분 전

다양한 로케일은 기본적으로 다른 형식을 사용합니다. Intl.DateTimeFormat API는 이러한 기본값을 존중하지만 필요할 때 재정의할 수 있게 해줍니다.

hour12 옵션을 사용하여 시간 형식 제어하기

'hour12' 옵션은 12시간 형식을 사용할지 여부를 제어합니다. 오전/오후가 포함된 12시간 형식을 사용하려면 'true'로, 24시간 형식을 사용하려면 'false'로 설정하세요.

const date = new Date('2025-03-15T14:30:00');

const format12 = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: true
});

const format24 = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: false
});

console.log(format12.format(date));
// 출력: "2:30 PM"

console.log(format24.format(date));
// 출력: "14:30"

'hour12' 옵션은 로케일의 기본 동작을 재정의합니다. 미국 영어는 일반적으로 12시간 형식을 사용하지만, 'hour12: false'로 설정하면 24시간 형식을 강제로 사용합니다.

'hour12' 옵션이 적용되려면 옵션에 'hour'를 포함하거나 'timeStyle'을 사용해야 합니다. 출력에 시간 구성 요소가 없으면 이 옵션은 영향을 미치지 않습니다.

hourCycle 옵션을 사용한 세밀한 제어

'hourCycle' 옵션은 시간을 계산하는 방식을 정확히 지정하여 'hour12'보다 더 세밀한 제어를 제공합니다. 이 옵션은 "h11", "h12", "h23", "h24" 네 가지 값을 허용합니다.

const date = new Date('2025-03-15T00:30:00'); // 오전 12:30

const h11 = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hourCycle: 'h11'
});

const h12 = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hourCycle: 'h12'
});

const h23 = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hourCycle: 'h23'
});

const h24 = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hourCycle: 'h24'
});

console.log(h11.format(date));
// 출력: "0:30 AM"

console.log(h12.format(date));
// 출력: "12:30 AM"

console.log(h23.format(date));
// 출력: "00:30"

console.log(h24.format(date));
// 출력: "24:30"

각 시간 주기 값은 동일한 시간에 대해 서로 다른 출력을 생성합니다. 이러한 차이는 자정과 정오에 가장 뚜렷하게 나타납니다.

네 가지 hourCycle 값 이해하기

네 가지 hourCycle 값은 각 기간 내에서 시간이 어떻게 번호가 매겨지는지 정의합니다.

"h12" 값은 1부터 12까지의 시간을 사용하는 12시간 형식을 사용합니다. 자정은 12:00 AM으로 표시되고 정오는 12:00 PM으로 표시됩니다. 이것은 미국에서 사용되는 표준 12시간 형식입니다.

"h11" 값은 0부터 11까지의 시간을 사용하는 12시간 형식을 사용합니다. 자정은 0:00 AM으로 표시되고 정오는 0:00 PM으로 표시됩니다. 이 형식은 덜 일반적이지만 일부 상황에서 나타납니다.

"h23" 값은 0부터 23까지의 시간을 사용하는 24시간 형식을 사용합니다. 자정은 00:00으로 표시되고 하루는 23:59에 끝납니다. 이것은 유럽과 아시아 대부분에서 사용되는 표준 24시간 형식입니다.

"h24" 값은 1부터 24까지의 시간을 사용하는 24시간 형식을 사용합니다. 자정은 이전 날의 관점에서 24:00으로 표시됩니다. 이 형식은 드물지만 일부 기술적 상황에서 나타납니다.

대부분의 애플리케이션은 12시간 형식에는 "h12"를, 24시간 형식에는 "h23"를 사용합니다.

시간 주기별 자정 시간 비교

자정은 시간 주기 값 간의 차이를 가장 명확하게 보여줍니다.

const midnight = new Date('2025-03-15T00:00:00');

const cycles = ['h11', 'h12', 'h23', 'h24'];

cycles.forEach(cycle => {
  const formatter = new Intl.DateTimeFormat('en-US', {
    hour: 'numeric',
    minute: 'numeric',
    second: 'numeric',
    hourCycle: cycle
  });

  console.log(`${cycle}: ${formatter.format(midnight)}`);
});

// 출력:
// h11: 0:00:00 AM
// h12: 12:00:00 AM
// h23: 00:00:00
// h24: 24:00:00

h12h23 값은 각 형식에 대해 가장 친숙한 표현을 제공합니다.

시간 주기별 정오 시간 비교

Noon은 시간 주기가 어떻게 다른지 보여줍니다.

const noon = new Date('2025-03-15T12:00:00');

const cycles = ['h11', 'h12', 'h23', 'h24'];

cycles.forEach(cycle => {
  const formatter = new Intl.DateTimeFormat('en-US', {
    hour: 'numeric',
    minute: 'numeric',
    second: 'numeric',
    hourCycle: cycle
  });

  console.log(`${cycle}: ${formatter.format(noon)}`);
});

// Output:
// h11: 0:00:00 PM
// h12: 12:00:00 PM
// h23: 12:00:00
// h24: 12:00:00

다시 말하자면, h12h23은 표준 표현을 생성하는 반면 h11은 정오 시간에 0을 사용합니다.

hour12와 hourCycle의 상호작용

hour12hourCycle 모두를 지정하면, hour12 옵션이 우선하고 hourCycle 옵션은 무시됩니다.

const date = new Date('2025-03-15T14:30:00');

const formatter = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: true,
  hourCycle: 'h23'  // 이 설정은 무시됨
});

console.log(formatter.format(date));
// Output: "2:30 PM" (hour12: true에서 오는 12시간 형식)

hour12: true 설정은 12시간 형식을 강제하여, 일반적으로 24시간 형식을 생성하는 hourCycle: 'h23' 설정을 재정의합니다.

실제로는 간단한 제어를 위해 hour12를 사용하거나 정밀한 제어를 위해 hourCycle을 사용하되, 둘 다 함께 사용하지 않는 것이 좋습니다.

로케일 기본값 존중하기

hour12hourCycle 모두를 생략하면, 포맷터는 로케일의 기본 시간 형식을 사용합니다.

const date = new Date('2025-03-15T14:30:00');

const usFormatter = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric'
});

const deFormatter = new Intl.DateTimeFormat('de-DE', {
  hour: 'numeric',
  minute: 'numeric'
});

const jpFormatter = new Intl.DateTimeFormat('ja-JP', {
  hour: 'numeric',
  minute: 'numeric'
});

console.log(usFormatter.format(date));
// Output: "2:30 PM" (미국 기본값: 12시간제)

console.log(deFormatter.format(date));
// Output: "14:30" (독일 기본값: 24시간제)

console.log(jpFormatter.format(date));
// Output: "14:30" (일본 기본값: 24시간제)

미국 로케일은 기본적으로 12시간 형식을 사용하는 반면, 독일과 일본 로케일은 기본적으로 24시간 형식을 사용합니다. 이러한 기본값을 존중하면 각 지역의 사용자에게 가장 친숙한 경험을 제공할 수 있습니다.

로케일 기본값 재정의

명시적으로 hour12 또는 hourCycle을 설정하여 로케일의 기본 시간 형식을 재정의할 수 있습니다.

const date = new Date('2025-03-15T14:30:00');

// 독일 로케일에 12시간 형식 강제 적용
const de12 = new Intl.DateTimeFormat('de-DE', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: true
});

// 미국 로케일에 24시간 형식 강제 적용
const us24 = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  hour12: false
});

console.log(de12.format(date));
// 출력: "2:30 PM"

console.log(us24.format(date));
// 출력: "14:30"

이 접근 방식은 사용자의 로케일에 관계없이 특정 시간 형식을 강제해야 할 때 유용합니다.

로케일 기본값을 존중해야 하는 경우

대부분의 애플리케이션은 로케일 기본값을 존중해야 합니다. 각 지역의 사용자는 익숙한 형식으로 시간이 표시되기를 기대합니다. 이러한 기본값을 재정의하면 혼란이 생길 수 있습니다.

사용자 자신의 지역에 시간을 표시할 때는 포맷터가 로케일의 기본 시간 형식을 사용하도록 하세요.

const formatter = new Intl.DateTimeFormat(navigator.language, {
  hour: 'numeric',
  minute: 'numeric'
});

const time = new Date('2025-03-15T14:30:00');
console.log(formatter.format(time));
// 출력은 사용자의 로케일에 따라 다름
// en-US의 경우: "2:30 PM"
// de-DE의 경우: "14:30"
// ja-JP의 경우: "14:30"

이 접근 방식은 구성이 필요 없이 각 사용자의 기대에 자동으로 적응합니다.

로케일 기본값을 재정의해야 하는 경우

애플리케이션이 모든 사용자에게 일관성을 요구할 때 로케일 기본값을 재정의하세요. 교통 시스템, 군사 애플리케이션 및 기술 도구는 종종 로케일에 관계없이 24시간 형식이 필요합니다.

// 항공편 시간에는 항상 24시간 형식 사용
const formatter = new Intl.DateTimeFormat(navigator.language, {
  hour: 'numeric',
  minute: 'numeric',
  hour12: false
});

const departureTime = new Date('2025-03-15T14:30:00');
console.log(`출발: ${formatter.format(departureTime)}`);
// 출력: "출발: 14:30" (모든 로케일에 대해)

이는 일정, 로그 또는 타임스탬프와 같이 사용자가 정확하게 참조해야 하는 시간을 표시할 때 일관성을 보장합니다.

사용자가 명시적으로 기본 설정을 선택할 때도 기본값을 재정의할 수 있습니다. 애플리케이션이 12시간 및 24시간 형식 중에서 선택할 수 있는 설정을 제공하는 경우, 로케일 기본값 대신 해당 기본 설정을 사용하세요.

function formatTime(date, userPrefers24Hour) {
  const formatter = new Intl.DateTimeFormat(navigator.language, {
    hour: 'numeric',
    minute: 'numeric',
    hour12: !userPrefers24Hour
  });

  return formatter.format(date);
}

const time = new Date('2025-03-15T14:30:00');

console.log(formatTime(time, false));
// 출력: "2:30 PM"

console.log(formatTime(time, true));
// 출력: "14:30"

이 패턴은 구분 문자 및 텍스트 방향과 같은 시간 표시의 다른 측면을 여전히 현지화하면서 사용자 선택을 존중합니다.

timeStyle과 함께 hour12 사용하기

hour12 옵션은 timeStyle 프리셋 스타일과 함께 작동합니다. 이를 통해 편리한 프리셋 스타일을 사용하면서도 시간 형식을 제어할 수 있습니다.

const date = new Date('2025-03-15T14:30:45');

const short12 = new Intl.DateTimeFormat('en-US', {
  timeStyle: 'short',
  hour12: true
});

const short24 = new Intl.DateTimeFormat('en-US', {
  timeStyle: 'short',
  hour12: false
});

const medium12 = new Intl.DateTimeFormat('en-US', {
  timeStyle: 'medium',
  hour12: true
});

const medium24 = new Intl.DateTimeFormat('en-US', {
  timeStyle: 'medium',
  hour12: false
});

console.log(short12.format(date));
// 출력: "2:30 PM"

console.log(short24.format(date));
// 출력: "14:30"

console.log(medium12.format(date));
// 출력: "2:30:45 PM"

console.log(medium24.format(date));
// 출력: "14:30:45"

이 접근 방식은 프리셋 스타일과 명시적 시간 형식 제어를 결합하여 포맷팅을 단순화합니다.

여러 로케일에 대한 시간 포맷팅

애플리케이션이 여러 지역의 사용자를 대상으로 할 때, 각 로케일의 규칙에 따라 시간을 포맷팅하세요.

const date = new Date('2025-03-15T14:30:00');

const locales = [
  { code: 'en-US', name: 'United States' },
  { code: 'en-GB', name: 'United Kingdom' },
  { code: 'de-DE', name: 'Germany' },
  { code: 'ja-JP', name: 'Japan' }
];

locales.forEach(locale => {
  const formatter = new Intl.DateTimeFormat(locale.code, {
    hour: 'numeric',
    minute: 'numeric'
  });

  console.log(`${locale.name}: ${formatter.format(date)}`);
});

// 출력:
// United States: 2:30 PM
// United Kingdom: 14:30
// Germany: 14:30
// Japan: 14:30

각 로케일은 자동으로 선호하는 형식을 사용합니다. 어떤 지역이 어떤 형식을 사용하는지 알 필요가 없습니다.

해결된 시간 주기 확인하기

resolvedOptions()를 호출하여 포맷터가 실제로 사용하는 시간 주기를 확인할 수 있습니다.

const formatter = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric'
});

const options = formatter.resolvedOptions();
console.log(options.hourCycle);
// 출력: "h12"

console.log(options.hour12);
// 출력: true

이 메서드는 모든 로케일 기본값과 명시적 옵션을 해결한 후 포맷터가 사용하는 실제 설정을 반환합니다. 시간 구성 요소가 있을 때 반환된 객체에는 hourCyclehour12 속성이 모두 포함됩니다.

템플릿에서 시간 형식 지정하기

사용자에게 시간 정보를 표시하는 모든 곳에서 형식이 지정된 시간을 사용할 수 있습니다. 여기에는 HTML에 시간 삽입, 로그에 타임스탬프 표시 또는 일정 표시 등이 포함됩니다.

const formatter = new Intl.DateTimeFormat(navigator.language, {
  hour: 'numeric',
  minute: 'numeric'
});

const meetingTime = new Date('2025-03-15T14:30:00');
const deadlineTime = new Date('2025-03-15T17:00:00');

document.getElementById('meeting').textContent = formatter.format(meetingTime);
document.getElementById('deadline').textContent = formatter.format(deadlineTime);

형식이 지정된 문자열은 다른 문자열 값과 같이 작동합니다. 텍스트 내용, 속성 또는 사용자에게 정보를 표시하는 모든 컨텍스트에 삽입할 수 있습니다.

기억해야 할 사항

12시간제와 24시간제 사이를 전환하려면 hour12 옵션을 사용하세요. AM/PM이 있는 12시간제는 true로, 24시간제는 false로 설정하세요.

시간 번호 매기기를 정밀하게 제어하려면 hourCycle 옵션을 사용하세요. "h12" 값은 표준 12시간 형식을 제공하고 "h23" 값은 표준 24시간 형식을 제공합니다.

대부분의 애플리케이션에서는 로케일 기본값을 존중하세요. 사용자는 자신의 지역에 익숙한 형식으로 시간이 표시되기를 기대합니다. 모든 사용자에 대한 일관성이 지역 관습을 존중하는 것보다 더 중요한 경우에만 기본값을 재정의하세요.

hour12timeStyle 프리셋과 결합하여 시간 형식을 제어하면서 다른 시간 구성 요소에 대해 편리한 프리셋 스타일을 사용하세요.