사용자 로케일에 맞게 시간 형식을 지정하는 방법
JavaScript를 사용하여 각 사용자의 지역 규칙에 따라 시간 표시하기
소개
시간은 전 세계적으로 다르게 표시됩니다. 미국인들은 일반적으로 오후 3시 30분을 3:30 PM으로 표시하는 반면, 대부분의 유럽인들은 15:30을 기대합니다. 시간 형식을 하드코딩하면 모든 사용자가 동일한 규칙을 따른다고 가정하는 것입니다.
익숙하지 않은 형식으로 시간을 표시하면 혼란이 생깁니다. 24시간제에 익숙한 사용자가 3:30 PM을 보면 이것이 오전인지 오후인지 이해하기 위해 정신적으로 변환해야 합니다. 이러한 인지적 부담은 애플리케이션의 모든 시간 표시에 걸쳐 누적됩니다.
JavaScript는 시간 형식을 자동으로 처리하는 Intl.DateTimeFormat API를 제공합니다. 이 강의에서는 시간 형식이 문화권마다 다른 이유, API 작동 방식, 그리고 모든 로케일에 맞게 시간을 올바르게 형식화하는 방법을 설명합니다.
로케일별로 시간 형식이 다른 이유
서로 다른 지역에서는 시간을 표시하는 다양한 규칙이 발전해왔습니다. 이러한 규칙은 역사적 관행, 교육 시스템 및 문화적 선호도를 반영합니다. 어떤 단일 형식도 보편적이지 않습니다.
미국, 캐나다, 호주 및 필리핀에서는 AM과 PM 표시기가 있는 12시간 형식을 사용합니다. 오후 3시 30분은 3:30 PM으로 표시됩니다.
대부분의 유럽 국가, 라틴 아메리카 및 아시아에서는 AM 또는 PM 표시기 없이 24시간 형식을 사용합니다. 같은 시간이 15:30으로 표시됩니다.
시간과 분 사이의 구분 문자도 다양합니다. 영어권 국가에서는 콜론을 사용하지만, 일부 로케일에서는 마침표나 다른 구두점을 사용합니다.
AM과 PM이 표시되는 방식도 다릅니다. 영어는 AM과 PM을 사용하고, 스페인어는 a.m.과 p.m.을 사용하며, 일부 로케일에서는 이러한 표시기를 시간 뒤가 아닌 앞에 배치합니다.
시간을 표시할 때는 시간 형식과 특정 형식 지정 규칙 모두에 대해 사용자의 기대에 맞춰야 합니다.
Intl.DateTimeFormat을 사용하여 시간 형식 지정하기
'Intl.DateTimeFormat' 생성자는 지역별 규칙을 적용하는 포맷터를 생성합니다. 시간을 형식화하려면 첫 번째 인수로 로케일 식별자를 전달하고 두 번째 인수로 시간 관련 옵션을 지정하세요.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
const date = new Date('2025-03-15T15:30:00');
console.log(formatter.format(date));
// 출력: "3:30 PM"
이것은 시간과 분을 표시하는 미국 영어용 포맷터를 생성합니다. 'hour'와 'minute' 옵션은 포맷터에게 이러한 구성 요소를 포함하도록 지시합니다. 'format()' 메서드는 Date 객체를 적절한 형식의 문자열로 변환합니다.
Date 생성자는 '2025-03-15T15:30:00'과 같은 ISO 8601 날짜/시간 문자열을 받습니다. 이는 2025년 3월 15일 오후 3시 30분을 나타내는 Date 객체를 생성합니다. 그런 다음 포맷터가 이를 지역별 시간 문자열로 변환합니다.
동일한 시간을 다른 로케일로 형식화하기
생성자에 전달되는 로케일 식별자를 변경하여 동일한 시간을 다른 로케일로 형식화할 수 있습니다.
const date = new Date('2025-03-15T15:30:00');
const usFormatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
console.log(usFormatter.format(date));
// 출력: "3:30 PM"
const gbFormatter = new Intl.DateTimeFormat('en-GB', {
hour: 'numeric',
minute: 'numeric'
});
console.log(gbFormatter.format(date));
// 출력: "15:30"
const deFormatter = new Intl.DateTimeFormat('de-DE', {
hour: 'numeric',
minute: 'numeric'
});
console.log(deFormatter.format(date));
// 출력: "15:30"
const frFormatter = new Intl.DateTimeFormat('fr-FR', {
hour: 'numeric',
minute: 'numeric'
});
console.log(frFormatter.format(date));
// 출력: "15:30"
각 포맷터는 서로 다른 규칙을 적용합니다. 미국 포맷터는 AM/PM이 있는 12시간 형식을 사용합니다. 영국, 독일, 프랑스 포맷터는 모두 AM/PM 표시 없이 24시간 형식을 사용합니다.
각 로케일이 어떤 형식을 사용하는지 알 필요가 없습니다. API는 로케일 식별자를 기반으로 이러한 세부 사항을 자동으로 처리합니다.
시간 표시에 초 포함하기
시간과 분과 함께 초를 표시하기 위해 second 옵션을 추가할 수 있습니다.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
const date = new Date('2025-03-15T15:30:45');
console.log(formatter.format(date));
// 출력: "3:30:45 PM"
second 옵션은 hour와 minute과 동일한 방식으로 작동합니다. 출력에 초를 포함하려면 'numeric'으로 설정하세요.
2-digit로 숫자 패딩 제어하기
hour, minute, second 옵션은 두 가지 값을 허용합니다: 'numeric'과 '2-digit'. 'numeric' 값은 패딩 없이 숫자를 표시하고, '2-digit'은 항상 앞에 0을 붙여 두 자리 숫자로 표시합니다.
const date = new Date('2025-03-15T09:05:03');
const numericFormatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
console.log(numericFormatter.format(date));
// 출력: "9:05:03 AM"
const twoDigitFormatter = new Intl.DateTimeFormat('en-US', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
console.log(twoDigitFormatter.format(date));
// 출력: "09:05:03 AM"
숫자 포맷터는 시간을 한 자리 숫자로 표시하여 9:05:03 AM을 표시합니다. 두 자리 포맷터는 시간에 앞에 0을 붙여 09:05:03 AM을 표시합니다. 분과 초는 설정에 관계없이 일반적으로 패딩되므로 두 경우 모두 두 자리로 표시됩니다.
12시간제 또는 24시간제 강제 설정
기본적으로 API는 로케일이 선호하는 시간 형식을 사용합니다. hour12 옵션으로 이를 재정의할 수 있습니다.
const date = new Date('2025-03-15T15:30:00');
const hour12Formatter = new Intl.DateTimeFormat('en-GB', {
hour: 'numeric',
minute: 'numeric',
hour12: true
});
console.log(hour12Formatter.format(date));
// 출력: "3:30 pm"
const hour24Formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
hour12: false
});
console.log(hour24Formatter.format(date));
// 출력: "15:30"
hour12: true로 설정하면 일반적으로 24시간제를 사용하는 로케일에서도 12시간제를 강제로 사용합니다. hour12: false로 설정하면 일반적으로 12시간제를 사용하는 로케일에서도 24시간제를 강제로 사용합니다.
로케일은 여전히 구두점과 간격과 같은 다른 서식 세부 사항을 결정합니다. hour12: true가 있는 영국 포맷터는 소문자 pm으로 3:30 pm을 표시하는 반면, 미국 포맷터는 대문자 PM으로 3:30 PM을 표시합니다.
사용자 로케일에 맞는 시간 형식 지정
특정 로케일을 하드코딩하는 대신 브라우저에서 사용자가 선호하는 언어를 사용할 수 있습니다. navigator.language 속성은 사용자의 최상위 언어 선호도를 반환합니다.
const userLocale = navigator.language;
const formatter = new Intl.DateTimeFormat(userLocale, {
hour: 'numeric',
minute: 'numeric'
});
const date = new Date('2025-03-15T15:30:00');
console.log(formatter.format(date));
// 출력은 사용자의 로케일에 따라 다름
// en-US의 경우: "3:30 PM"
// en-GB의 경우: "15:30"
// de-DE의 경우: "15:30"
// fr-FR의 경우: "15:30"
이 접근 방식은 사용자가 수동으로 로케일을 선택할 필요 없이 각 사용자의 기대에 맞게 시간을 표시합니다. 브라우저가 언어 선호도를 제공하고 Intl API가 적절한 형식 지정 규칙을 적용합니다.
대체 동작을 활성화하기 위해 선호하는 언어의 전체 배열을 전달할 수도 있습니다.
const formatter = new Intl.DateTimeFormat(navigator.languages, {
hour: 'numeric',
minute: 'numeric'
});
const date = new Date('2025-03-15T15:30:00');
console.log(formatter.format(date));
API는 배열에서 지원하는 첫 번째 로케일을 사용합니다. 이는 사용자의 최상위 선호도를 사용할 수 없을 때 더 나은 대체 처리를 제공합니다.
형식을 지정할 시간 생성하기
여러 방법으로 시간 정보가 포함된 Date 객체를 생성할 수 있습니다. 가장 신뢰할 수 있는 접근 방식은 ISO 8601 날짜-시간 문자열을 사용하는 것입니다.
const time1 = new Date('2025-03-15T09:00:00');
const time2 = new Date('2025-03-15T15:30:00');
const time3 = new Date('2025-03-15T23:45:30');
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
console.log(formatter.format(time1));
// 출력: "9:00 AM"
console.log(formatter.format(time2));
// 출력: "3:30 PM"
console.log(formatter.format(time3));
// 출력: "11:45 PM"
ISO 8601 날짜-시간 문자열은 YYYY-MM-DDTHH:MM:SS 형식을 사용합니다. T는 날짜와 시간을 구분합니다. 이 형식은 모호하지 않으며 모든 로케일과 시간대에서 일관되게 작동합니다.
타임스탬프에서 시간 형식 지정하기
Unix 타임스탬프에서 Date 객체를 생성할 수도 있습니다. Unix 타임스탬프는 1970년 1월 1일 UTC 이후의 밀리초 수를 나타냅니다.
const timestamp = 1710515400000; // 2025년 3월 15일 오후 3시 30분
const date = new Date(timestamp);
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
console.log(formatter.format(date));
// 출력: "3:30 PM"
이 방법은 API, 데이터베이스 또는 시간을 숫자로 표현하는 다른 시스템에서 타임스탬프를 받을 때 유용합니다.
Date 객체를 먼저 생성하지 않고 타임스탬프를 직접 format() 메서드에 전달할 수도 있습니다.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
const timestamp = 1710515400000;
console.log(formatter.format(timestamp));
// 출력: "3:30 PM"
API는 Date 객체와 타임스탬프를 모두 허용합니다. 코드에 더 적합한 방식을 사용하세요.
현재 시간 형식 지정하기
현재 시간의 형식을 지정하려면 인수 없이 Date 객체를 생성하세요. 이렇게 하면 현재 시점을 나타내는 Date 객체가 생성됩니다.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
const now = new Date();
console.log(formatter.format(now));
// 출력: "3:45:12 PM" (실행 시 현재 시간)
현재 타임스탬프를 숫자로 반환하는 Date.now()를 직접 전달할 수도 있습니다.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
console.log(formatter.format(Date.now()));
// 출력: "3:45:12 PM" (실행 시 현재 시간)
두 접근 방식 모두 동일한 결과를 생성합니다.
성능을 위한 포맷터 재사용
새로운 Intl.DateTimeFormat 인스턴스를 생성하는 것은 로케일 데이터를 로드하고 옵션을 처리하는 작업을 포함합니다. 동일한 로케일과 설정으로 여러 시간의 형식을 지정해야 할 때는 포맷터를 한 번 생성하고 재사용하세요.
const formatter = new Intl.DateTimeFormat('en-US', {
hour: 'numeric',
minute: 'numeric'
});
const times = [
new Date('2025-03-15T09:00:00'),
new Date('2025-03-15T12:30:00'),
new Date('2025-03-15T18:45:00')
];
times.forEach(time => {
console.log(formatter.format(time));
});
// 출력:
// "9:00 AM"
// "12:30 PM"
// "6:45 PM"
이 방법은 각 시간마다 새 포맷터를 생성하는 것보다 더 효율적입니다. 수백 또는 수천 개의 시간 값이 있는 배열의 형식을 지정할 때 성능 차이가 크게 나타납니다.
템플릿에서 시간 형식 지정하기
Intl.DateTimeFormat은 사용자에게 시간을 표시하는 모든 곳에서 사용할 수 있습니다. 여기에는 HTML 템플릿에 형식이 지정된 시간 삽입, 테이블에 시간 표시 또는 사용자 인터페이스에 타임스탬프 표시 등이 포함됩니다.
const formatter = new Intl.DateTimeFormat(navigator.language, {
hour: 'numeric',
minute: 'numeric'
});
const eventStart = new Date('2025-03-15T14:00:00');
const eventEnd = new Date('2025-03-15T16:30:00');
document.getElementById('start-time').textContent = formatter.format(eventStart);
document.getElementById('end-time').textContent = formatter.format(eventEnd);
형식이 지정된 문자열은 다른 문자열 값과 같이 작동합니다. 텍스트 내용, 속성 또는 사용자에게 정보를 표시하는 다른 컨텍스트에 삽입할 수 있습니다.