JavaScript Intl API 사용하기

서나무·2022년 12월 16일
0

JavaScript

목록 보기
3/3
post-thumbnail

Intl 개체는 ECMAScript 국제화 API의 네임스페이스로, 언어 구분 문자열 비교, 숫자 형식, 날짜 및 시간 형식을 제공합니다.
출처: [MDN] Intl

Intl API를 사용하면 각 나라의 언어와 표현에 맞게 날짜 혹은 시간 등을 표시해줄 수 있다.

RelativeTimeFormat

RelativeTimeFormat를 이용하면 각 나라의 언어에 맞게 N일 전 N days age 이렇게 시간을 나타낼 수 있다.

// 인스턴스 생성할 때 언어 설정
const formatter = new Intl.RelativeTimeFormat('ko');

// 오늘과 1년 전 날짜의 차이를 구한다.
// month는 index로 설정해야해서 12월 달의 index인 11을 넣어줘야한다.
const passed = new Date() - new Date(2021, 11, 16); 

// passed를 하루 단위로 나눔
const passedForDay = Math.floor(passed / (1000 * 60 * 60 * 24));

const diff = formatter.format(
  -passedForDay, // 음수는 지난 날짜, 양수는 남은 날짜로 표현한다.
  'day', // 포맷을 'day'로 설정한다.
);

console.log(diff); // 365일 전

지금과 1년 전의 날짜 차이를 콘솔에 한국어로 출력하도록 했다.

// 언어를 영어로 설정
const formatter = new Intl.RelativeTimeFormat('en-US'); // 365 days ago

// 날짜를 양수로 설정
const diff = formatter.format(passedForDay, 'day'); // 365일 후

이렇게 간단하게 옵션을 변경해보면서 출력되는 결과를 확인해볼 수 있다.

generateTimeString

라이브러리를 사용하지 않고 RelativeTimeFormat를 사용해서 지나간 날짜를 똑똑하게 나타내는 함수를 만들어보자!

참고로 날짜 관련된 라이브러리는 Moment.js Day.js 등이 있으며 Moment.js는 더 이상 업데이트가 이루어지지 않을 것이라고 한다.

const generateTimeString = (time, lang = 'ko') => {
  const formatter = new Intl.RelativeTimeFormat(lang, {
    numeric: 'always',
  });
  const passed = new Date() - new Date(time);
}

generateTimeString 함수는 시간과 언어를 파라미터로 받는다. 언어는 한국어를 기본 값으로 설정했다.

nemeric 옵션은 날짜 형식을 어떻게 표현할지 설정할 수 있다.

nemeric 옵션 설정에 따른 결과

  • auto : 어제, 그저께
  • always : 1일 전, 2일 전

시간 표현 형식

시간을 어떻게 표현할지 형식을 정해서 해당 구간에 맞는 결과를 줘야한다.

구간표현
1분 미만s초 전
1분 이상 ~ 1시간 미만m분 전
1시간 이상 ~ 1일 미만h시간 전
1일 이상 ~ 1달 미만d일 전
1달 이상yyyymmdd

한 달의 기준이 29일, 30일, 31일 이렇게 다양하니, 한 달이 지나가면 연월일로 표시하도록 했다.

시간 단위 체크하기

시간 표현 형식에 맞게 날짜를 표현하려면 각 시간의 단위를 체크해야 한다.

JavaScript는 시간의 단위가 millisecond인 점을 유의해야 한다.

시간millisecond로 계산결과
1초10001000
1분1000 * 6060000
1시간1000 * 60 * 603600000
1일1000 * 60 * 60 * 2486400000

우선 1달은 30이라고 가정했으며, 구간의 조건을 파악해보자.

구간표현조건1조건2
1분 미만s초 전60000(1분) 미만-
1분 이상 ~ 1시간 미만m분 전60000(1분) 이상3600000(1시간) 미만
1시간 이상 ~ 1일 미만h시간 전3600000(1시간) 이상86400000(1일) 미만
1일 이상 ~ 1달 미만d일 전86400000(1일) 이상2592000000(1달) 미만
1달 이상yyyymmdd2592000000(1달) 이상-

시간 단위를 체크하기 위해 객체를 만들고, 객체 안에 함수를 선언했다.

const checkTime = {
  isSecond: (time) => time < 60000,
  isMinute: (time) => 60000 <= time && time < 3600000,
  isHour: (time) => 3600000 <= time && time < 86400000,
  isDay: (time) => 86400000 <= time && time < 2592000000,
  isOverOneMonth: (time) => 2592000000 <= time,
};

그리고 각 조건을 체크해서 각 시간대에 맞는 문자열을 return 해도록 했다.

const generateTimeString = (time, lang = 'ko') => {
  const formatter = new Intl.RelativeTimeFormat(lang, {
    numeric: 'always',
  });
  const passed = new Date() - new Date(time);
  // 조건 추가
  if (checkTime.isSecond(passed)) {
    return '1분 미만';
  }
  if (checkTime.isMinute(passed)) {
    return '1시간 미만';
  }
  if (checkTime.isHour(passed)) {
    return '1일 미만';
  }
  if (checkTime.isDay(passed)) {
    return '1달 미만';
  }
  if (checkTime.isOverOneMonth(passed)) {
    return '1달 이상';
  }
};

테스트 해보기

const second = new Date();
second.setSeconds(second.getSeconds() - 1);
console.log(generateTimeString(second)); // 1분 미만

const minute = new Date();
minute.setMinutes(minute.getMinutes() - 1);
console.log(generateTimeString(minute)); // 1시간 미만

const hour = new Date();
hour.setHours(hour.getHours() - 1);
console.log(generateTimeString(hour)); // 1일 미만

const yesterday = new Date();
yesterday.setHours(yesterday.getHours() - 24);
console.log(generateTimeString(yesterday)); // 1달 미만

const dayBeforYesterday = new Date();
dayBeforYesterday.setHours(dayBeforYesterday.getHours() - 48);
console.log(generateTimeString(dayBeforYesterday)); // 1달 미만

const month = new Date();
month.setMonth(month.getMonth() - 1);
console.log(generateTimeString(month)); // 1달 이상

계산하기

이제는 시간대에 맞게 계산을 해줘야한다.

시간 차이가 1초대인데, 1시간 단위로 시간을 계산해서 출력하면 안되기 때문이다.

이번에도 객체를 선언하고, 객체 안에 시간단위에 맞게 계산해주는 함수들을 선언했다.

const calcTime = {
  second: (time) => Math.floor(time / 1000),
  minute: (time) => Math.floor(time / 60000),
  hour: (time) => Math.floor(time / 3600000),
  day: (time) => Math.floor(time / 86400000),
};

이제 각 단위에 맞게 시간을 계산한 결과를 return 해주면 끝이다!

const generateTimeString = (time, lang = 'ko') => {
  const formatter = new Intl.RelativeTimeFormat(lang, {
    numeric: 'always',
  });
  const passed = new Date() - new Date(time);
  if (checkTime.isSecond(passed)) {
    // 초 단위
    return formatter.format(-calcTime.second(passed), 'second');
  }
  if (checkTime.isMinute(passed)) {
    // 분 단위
    return formatter.format(-calcTime.minute(passed), 'minute');
  }
  if (checkTime.isHour(passed)) {
    // 시간 단위
    return formatter.format(-calcTime.hour(passed), 'hour');
  }
  if (checkTime.isDay(passed)) {
    // 일 단위
    return formatter.format(-calcTime.day(passed), 'day');
  }
  if (checkTime.isOverOneMonth(passed)) {
    // yyyy년 mm월 dd일
    return new Intl.DateTimeFormat(lang, {
      year: 'numeric',
      month: 'short',
      day: 'numeric',
    }).format(new Date(time));
  }
};

테스트 해보기에 있는 코드를 실행시켜보자!

1초 전
1분 전
1시간 전
1일 전
2일 전
2022년 11월 16일

콘솔 출력 결과다. 의도한 대로 시간대에 맞게 잘 출력해주고 있다.

const formatter = new Intl.RelativeTimeFormat(lang, {
  numeric: 'auto',
});

numericauto로 바꿔보고 다시 실행해보자.

1초 전
1분 전
1시간 전
어제
그저께
2022년 11월 16일

1일 전을 어제, 2일 전을 그저께로 표현해주고 있다.

profile
주니어 프론트엔드 개발자

0개의 댓글