기획자가 오늘 내게 요구했던 사항 중 하나다.
개발 데드라인이 오늘이었는데, 마지막 개발자 테스트를 하던 중 요구했던 스펙 중 하나가 의도와 다르게 구현하기가 어렵게 되자 차선책으로 얘기를 꺼냈다.
어려운 일은 아니니, 알겠다고 하고 라이브러리를 쓸 정돈 아닌 것 같아서 Date
객체를 이용해서 뚱땅뚱땅 만들고, 2자리 숫자의 시간은 10미만일 때 숫자 0을 앞자리에 붙여주었다.
개발 완료하고 코드리뷰를 받는데 리뷰어가 코멘트를 달아줬다.
Intl.DateTimeFormat
을 쓰는건 어때요?솔직히 처음보는 메서드라, 이게 뭔고 싶어서 검색해봤더니 정말 간단한 날짜 표시에 제격인 녀석이였다.
Intl
이 뭐예요..?Intl 객체는 각 언어에 맞는 문자비교, 숫자, 시간, 날짜비교를 제공하는, ECMAScript 국제화 API를 위한 이름공간(
namespace
)입니다.
사용할 때는 어떤 언어(locales
)로 보여줄 지 정해야 하는데, 생략하게 되면 구현된 기본 locales
가 사용된다고 한다(아마 사용하는 기본 언어 설정에 따른다는 소리 같다 🤔).
언어 식별자(locale identifier)는 아래 순서대로 lookup
혹은 best fit
방식으로 찾아서 사용한다.
- a language subtag,
- (optionally) a script subtag,
- (optionally) a region (or country) subtag,
- (optionally) one or more variant subtags
- (all of which must be unique),
- (optionally) one or more BCP 47 extension sequences, and
- (optionally) a private-use extension sequence
subtag
은 하이픈으로 구별되는데, 제일 익숙한걸로 예시를 들자면 ko-kr
중 하이픈 뒤에 있는 kr
이 subtag
이다.
script subtag이 뭔지 궁금하긴 하지만, MDN 예시를 보니 다른 나라 언어를 쓸 게 아니고 한국어만 쓸 거라면 참고만 하면 될 것 같다.
출처: MDN - Intl
Intl.DateTimeFormat
에 관한 문서는 한글화가 아주 잘되어 있고, 예제도 상당히 많아서 MDN 문서를 보면 그리 어렵지만은 않다.
이 API를 알기 전 구현했던 코드는 아래와 같았다.
const getLastUpdateTime = () => {
const date = new Date();
const month = date.getMonth + 1
return `${date.getFullYear()}.${addZero(month)}.${addZero(date.getDate()) ${addZero(date.getHours())}:${addZero(date.getMinutes())}:${addZero(date.getSeconds())}`;
};
const addZero = (num:number):string => {
return num < 10 ? '0' + num : '' + num;
}
이게 대체 무슨 코드람
구현이야 했지만 얼마나 더러운지.. 🤦🏻♂️
하지만 Intl.DateTimeFormat
을 사용하면..?
const getLastUpdateTime = () => {
const option = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
}
return new Intl.DateTimeFormat('ko-KR', option).format(new Date());
}
console.log(getLastUpdateTime()); // 2023. 01. 20. 01:32:38
훨씬, 훨씬 깔끔해졌다!! 🧚🏼♂️
사실 이 기능을 Next.js에서 만들다보니, 새로운 에러를 발견했었다. Text content does not match server-rendered HTML
란 에러 메세지였다.
말그대로 서버에서 렌더링 했을 때의 텍스트와 실제 클라이언트의 렌더링 텍스트가 일치하지 않아서 생기는 문젠데, new Date()
를 바로 사용했기 때문에 발생한 문제였다.
React의 useState
를 사용해서 상태값으로 관리하면, 에러가 발생하지 않는다.
const [ lastUpdateTime, setLastUpdateTime ] = useState<string>('');
const getLastUpdateTime = () => {
const option = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
}
return new Intl.DateTimeFormat('ko-KR', option).format(new Date());
}
useEffect(() => {
setLastUpdateTime(getLastUpdateTime());
}, [router]) //next js router 이벤트가 발생할 때마다 실행하도록 했었다.
//...
return (
<div>
//...
<p>마지막 업데이트 시간: {lastUpdateTime}</p>
</div>
)
Intl.RelativeTimeFormat
이 메서드는 상대적인 시간 포맷팅을 해준다. 1시간전, 2일전, 30초전 같은 현재 시간에 상대적인 시간을 계산해서 그 나라 언어로 보여준다.
완전 꿀🍯 기능인듯!
A commitment of appreciation is all together for the information, keep on sharing such a data. ACAeronet Login