자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

관련지식
javascript, node.js, date

moment 라이브러리를 사용하지 않는다면 javascript 내장 객체인 Date객체는 꽤 자주 사용하게 될 것입니다. 날짜 포맷팅 또는 날짜 계산을 위해서 말이죠. 그런데 문자열로 된 날짜를 Date 객체로 편리하게 변환 방법을 모르는 분들이 많아서 간단하게 정리해봤습니다.

2020.03.19 라는 값의 문자열이 있다고 할때, 해당값을 가진 Date 객체를 만들기 위해서 대부분의 개발자는 아래처럼 할 것입니다.(substring 함수를 썼다고 가정합시다.)

자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

그런데 월(月)에 해당하는 인자는 0~11의 값으로 이루어지기 때문에 문자열의 월 부분을 잘라내고 빼기까지 해야하는 경우가 발생합니다. 굉장히 불편하죠. 이렇기 때문에 moment 라이브러리를 이용하거나 날짜 관련 공통함수를 만드는 것이지만, 지금은 그러한것들이 없다고 가정하겠습니다. 또는 공통함수를 어떻게 만들지 고민하는 중이라고 하죠.

만약 제한된 환경, 예를들어 최신 브라우저에서만 동작하면 될경우 날짜 문자열을 그대로 파싱할수도 있습니다.

자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

Date 객체나 Date.parse() 함수에는 datestring을 인자값으로 사용할수가 있습니다. 다만 RFC2822 또는 ISO8601 형태로 이루어진 날짜만을 사용할수 있을 뿐입니다. 또한 브라우저마다 문자열 구문 분석이 조금씩 다를수 있기 때문에 ES5까지는 권장되진 않습니다. 한번 브라우저 별로 비교해보겠습니다.

자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

왼쪽부터 크롬, 파이어폭스, 인터넷 익스플로러11 입니다. ‘년.월.일’ 포맷에 대해서 파싱이 되는것은 크롬이 유일한것을 보실수 있습니다. 버전별로 정리해보겠습니다.

크롬파이어폭스IE11IE9IE8특이사항
2020.03.19 O X X X X
2020-03-19 O O O O X 9시 디폴트 세팅
2020/03/19 O O O O O

만약 사이트에서 ‘년/월/일’ 포맷을 사용한다면 브라우저 버전을 걱정하지 않아도 됩니다. ‘년-월-일’ 일때도 크게 걱정하지 않아도 됩니다. IE8에서는 사용할수 없지만 곧 윈도우7도 공식지원이 종료되니 특별한 이유가 없다면 IE8은 배제해도 될것 같습니다. ‘년.월.일’ 포맷을 사용하는 경우는 거의 모든 브라우저가 지원하지 않아서 사용이 어려워 보입니다.

  1. Node.js에서는 사용가능
  2. 개발 규칙을 정해두면 사용가능

Node.js는 크롬V8엔진 기반이기 때문에 ‘년.월.일’ 포맷도 문제 없습니다. 그리고 아래와 같은 개발 규칙을 따른다면 다른 브라우저에서도 문제없이 사용 가능합니다.

공통함수)

  1. if(!Date.parse || !Date.parse('2001.01.01')) { //if조건은 생략해도 상관없음. 날짜는 파싱 가능 여부 확인용으로 날짜 자체는 의미없음
  2. Date.parse = function(datestring) {
  3. return new Date(datestring.replace(/\./g, '/')).getTime();
  4. }
  5. }

함수 사용)

  1. new Date(Date.parse('2020.03.19'))

new Date()는 timestamp 를 인자로 사용 가능하므로, Date 객체를 생성할때는 항상 parse() 함수를 통해 한다는 규칙을 따르면 모든 브라우저에서 동작하도록 할수 있습니다. timestamp 값은 다양한곳에서 사용하기 좋으므로, parse()함수를 재정의 하는 방법은 Date 생성을 위한 별도의 함수를 작성하는 것보다 더 좋은 결과를 얻을수 있습니다. 이제는 편리하게 날짜 변환을 하시죠!

대부분의 개발 언어가 그렇지만 기본으로 표시되는 날짜 포맷이 우리나라나 동양권의 날짜 표시 방법과는 차이가 있습니다.

자바스크립트의 많은 라이브러리들과 날짜 관련 UI 프레임워크들도 마찬가지로 날짜 포맷 표현에서 우리의 년.월.일 표현 방식과는 다른 방식으로 기본적인 날짜 표현을 합니다.

그리서 간단한 것은 날짜 포맷 함수를 직접 만들어 쓰기도 하고, 널리 알려진 날짜 포매팅 라이브러리의 도움을 받기도 합니다.

자바스크립트로 날짜 포매팅을 하는 방법은 크게 3가지로 나눌 수 있습니다.

  1. 직접 날짜 포매팅 함수를 만들기
  2. 날짜 라이브러리 사용(Moment.js)
  3. Internationalization API 사용

세 번째 국제화 API는 많이 사용되지 않다보니 다소 생소할 수 있습니다. 최신 자바스크립트 코딩을 접해보지 못했으면, 처음 보는 개발자도 있을 수 있을겁니다.

두 번째 모멘트(Moment.js)는 자바스크립트 날짜 라이브러리 중 하나로 Moment.js 또는 "모멘트"라고 합니다. 가장 많이 사용하고 또 추천하는 자바스크립트 날짜 라이브러리입니다.

다국어 지원이 잘되며, 한글 및 년.월.일 방식의 어순을 잘 지원하고, "지난주 화요일 10월 5일"과 같은 표현까지 지원합니다.

가볍고 빠른데다 다른 프레임워크와 함께 사용하는데 문제가 없어서 날짜 포매팅 함수를 직접 만들어 쓸 여력이 안되면 이 라이브러리를 사용하는 것을 추천합니다.

https://momentjs.com/

Moment.js | Home

Format Dates moment().format('MMMM Do YYYY, h:mm:ss a'); moment().format('dddd'); moment().format("MMM Do YY"); moment().format('YYYY [escaped] YYYY'); moment().format(); Relative Time moment("20111031", "YYYYMMDD").fromNow(); moment("20120620", "YYYYMMDD"

momentjs.com

간단한 한글 날짜 표현은 Internationalization API(국제화 API)를 사용하는 것을 추천합니다.

브라우저별 호환성 문제도 없고, 브라우저 내장 API로 지원되는 ECMAScript 지원 기능이기 때문에 속도가 가장 빠릅니다. 다양한 포맷 출력을 지원하지는 못하지만 다국어 지원이 잘 되기 때문에 자바스크립트 함수와 적절히 혼용해서 사용하면 효과적인 코딩이 가능합니다.

자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan
Internationalization API 호환성

1. 날짜 포매팅 함수 만들기

날짜 객체에서 년, 월, 일, 시, 분, 초, 요일 정보를 각각 얻어서 문자열 조합으로 원하는 날짜 문자열을 만듭니다.

예를 들어 다음과 같이 원하는 날짜 포매팅 함수를 만들어서 출력할 수 있습니다.

function getYmd10() {
    //yyyy-mm-dd 포맷 날짜 생성
    var d = new Date();
    return d.getFullYear() + "-" + ((d.getMonth() + 1) > 9 ? (d.getMonth() + 1).toString() : "0" + (d.getMonth() + 1)) + "-" + (d.getDate() > 9 ? d.getDate().toString() : "0" + d.getDate().toString());
}
function getFullYmdStr(){
    //년월일시분초 문자열 생성
    var d = new Date();
    return d.getFullYear() + "년 " + (d.getMonth()+1) + "월 " + d.getDate() + "일 " + d.getHours() + "시 " + d.getMinutes() + "분 " + d.getSeconds() + "초 " +  '일월화수목금토'.charAt(d.getUTCDay())+'요일';
}
console.log(getYmd10());
console.log(getFullYmdStr());
자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

날짜 포맷 출력 함수 외에 두 날짜 사이의 차이를 계산하는 함수 등도 만들어서 사용해야 합니다.

국제화 API 도 다국어 날짜 포매팅을 하는 메서드만 제공하기 때문에 이런 연산 기능들은 직접 제작해서 사용해야 합니다.

function calcDateDiff(type, date1, date2){
	//두 날짜 사이의 간격을 type 으로 계산해 출력
    let ret = Math.abs(date1 - date2);
    switch(type){
        case 'day':
            ret /= 24;
        case 'hour':
            ret /= 60;
        case 'min':
            ret /= 60;
        case 'sec':
            ret /= 1000;
    }
    return ret;
}

let date1 = new Date(2021, 9, 1, 9, 0), date2 = new Date(2021, 9, 30, 6, 30), current = new Date();
console.log(Math.round(calcDateDiff('day', date1, date2))+'일 차이');
console.log(Math.round(calcDateDiff('hour', current, date2))+'시간 차이');
자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

2. Moment.js 로 날짜 포매팅

다국어 표시 및 날짜 표현을 사용하려면 기본 moment.js 가 아니라 moment-with-locales.js를 사용해야 합니다.

Moment 홈페이지에서 다운로드 받아 사용할 때 주의해야 합니다.

moment.js 는 영문 출력 및 영문 날짜 어순 표시만 지원합니다.

파일을 다운로드 받아서 링크를 걸면 바로 사용할 수 있습니다.

jsdelivr에 CDN으로 올라가 있는 버전이 있으므로 특별히 Moment를 수정할 일이 없으면 CDN 링크를 가져와 사용해도 됩니다.

버전별 종류별 CDN 링크 URL은 다음 위치에서 확인할 수 있습니다.

https://www.jsdelivr.com/package/npm/moment

jsDelivr - A free, fast, and reliable CDN for Open Source

Supports npm, GitHub, WordPress, Deno, and more. Largest network and best performance among all CDNs. Serving more than 80 billion requests per month. Built for production use.

www.jsdelivr.com

자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

사용 방법은 상당히 직관적이고 편리합니다.

먼저 사용할 로케일을 설정합니다.

moment.locale('ko');         // en - 영어

자바스크립트 최상단에 선언하면 이후에 사용하는 moment 객체의 모든 날짜 출력은 설정한 로케일로 출력됩니다.

우리가 주로 사용할 언어는 한글 날짜 출력 포매팅일 것이므로 "ko"를 로케일 인자로 설정하면 됩니다.

출력 메서드들은 상당히 방대하고 다양합니다.

모멘트 라이브러리의 날짜 출력 메서드는 format()입니다.

인자를 사용해 직접 출력 포맷을 설정할 수도 있고, 내장된 몇몇 가지 기본 포맷을 사용할 수도 있습니다.

몇 가지 예를 들면 다음과 같이 사용할 수 있습니다.

//기본 출력 포맷
console.log(moment().format(''));

//출력 포맷 설정
console.log(moment().format('YYYY년 MMMM Do, a h:mm:ss'));
console.log(moment().format('dddd'));
console.log(moment().format("YY년 MMM Do"));
console.log(moment().format('YYYY 년 MM 월 부터'));

//내장 출력 포맷
console.log(moment().format('LT'));
console.log(moment().format('LTS'));
console.log(moment().format('L'));
console.log(moment().format('l'));
console.log(moment().format('LL'));
console.log(moment().format('ll'));
console.log(moment().format('LLL'));
console.log(moment().format('lll'));
console.log(moment().format('LLLL'));
console.log(moment().format('llll'));
자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

참고로 내장 출력 포맷의 대소문자 구분은 영문 및 알파벳 문화권을 위한 것입니다.

한글에서는 format('LLLL')과 format('llll')이 동일하게 출력되지만, 영문 환경에서는 짧은 요일(소문자)과 긴 요일(대문자)을 구분하며, 표시 순서와 구분자, 그리고 월, 일의 자릿수를 다르게 출력합니다.

내장 출력 포맷 한글 영문
LT 오전 12:25 12:25 AM
LTS 오전 12:25:30 12:25:30 AM
L 2021.10.05 10/05/2021
l 2021.10.05 10/5/2021
LL 2021년 10월 5일 October 5, 2021
ll 2021년 10월 5일 Oct 5, 2021
LLL 2021년 10월 5일 오전 12:25 October 5, 2021 12:25 AM
lll 2021년 10월 5일 오전 12:25 Oct 5, 2021 12:25 AM
LLLL 2021년 10월 5일 화요일 오전 12:25 Tuesday, October 5, 2021 12:25 AM
llll 2021년 10월 5일 화요일 오전 12:25 Tue, Oct 5, 2021 12:25 AM

모멘트는 moment() 메서드로 현재 시각을 호출합니다.

시간을 바꾸려면 moment() 메서드의 문자열 인자로 원하는 시각을 넣어서 변경할 수 있습니다.

moment("20151003", "YYYYMMDD").format('LLLL');

모멘트는 절대 시간이 아닌 상대 시간으로 표시하는 메서드들도 다양하게 지원을 합니다.

예를 들어 fromNow() 메서드는 현재 시각을 기준으로 2015년 10월 5일 날짜를 "6 년 전"과 같이 출력할 수 있습니다.

//상대 시간 표시
console.log(moment("20151003", "YYYYMMDD").fromNow(''));
console.log(moment().startOf('day'));
console.log(moment().startOf('day').fromNow(''));
console.log(moment().endOf('day').fromNow(''));
console.log(moment().startOf('hour').fromNow(''));
console.log(moment().endOf('hour').fromNow(''));
자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

모멘트는 앞서 자바스크립트로 직접 만들어서 구현했던 날짜 연산 함수의 기능과 같은 날짜 연산 기능을 내장 메서드로 제공합니다.

console.log(moment().subtract(100, 'days').calendar(''));
console.log(moment().subtract(6, 'days').calendar(''));
console.log(moment().subtract(1, 'months').calendar(''));
console.log(moment().add(1, 'days').calendar(''));
console.log(moment().add(6, 'days').calendar(''));
console.log(moment().add(1, 'years').calendar(''));
자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

연산 기능으로 연산된 결과 날짜는 calendar() 메서드를 사용하면 좀 더 이해하기 쉬운 문자열로 출력할 수 있습니다.

calendar() 메서드로 출력하면 어제, 내일, 지난주 수요일과 같은 친숙한 문자열로 날짜를 출력할 수 있습니다.

참고로 7일 이상 날짜는 연월일 포맷으로 출력합니다.


3. Internationalization API로 날짜 포매팅

국제화 API는 자바스크립트 내장 객체로 지원되기 때문에 별도의 라이브러리를 포함할 필요가 없습니다.

사용 객체명은 "Intl "입니다.

Moment.js 에 비해 사용 방법이 다소 번거롭고, 다양한 출력 형태를 지원하지 못하는 단점이 있습니다. 더 유연하고 다양한 날짜 출력 포맷을 필요로 하면 Moment.js를 사용하는 것이 좋습니다.

기본적인 사용방법은 다음과 같습니다.

const today = new Date();
const formattedDateKR = new Intl.DateTimeFormat("ko-KR").format(today);
console.log(formattedDateKR);
자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

국제화 API는 2가지 포맷 출력을 지원합니다.

하나는 년-월-일 과 같은 날짜 표기 방법에 따른 로케일을 표시하도록 하는 DateTimeFormat(로케일) 메서드이고, 

다른 하나는 며칠, 몇 시간과 같은 단순 시간 단위 표현을 위한 RelativeTimeFormat(로케일) 메서드입니다.

로케일 인자를 설정할 때 주의할 점이 있는데 DateTimeFormat() 메서드는 로케일 인자로 "KO-kr"과 같이 "언어-국가" 표시로 로케일을 선택하고, RelativeTimeFormat() 메서드는 "ko"와 같이 언어만 인자로 사용합니다.

헷갈리지 않도록 주의해야 합니다.

국제화 API는 어디까지나 Date 객체를 보조하는 수단이기 때문에 날짜 정보와 연산 기능 등은 Date 객체의 것을 사용해야 합니다. 다국어 API의 주요 기능이 표시되는 시간의 표시 순서와 표시 언어를 언어/국가별로 순서를 변경해주는 것이 주요 기능이기 때문에 이 부분만 국제화 API를 활용한다고 생각하면 됩니다.

국제화 API로 날짜 표시

출력할 날짜 문자열을 생성하는 메서드는 format() 메서드입니다.

format() 메서드는 2개의 인자를 받을 수 있습니다.

첫 번째 인자는 날짜 객체입니다.

날짜 객체에 원하는 날짜를 설정한 후 format() 메서드 인자로 넘기면 문자열로 포매팅된 날짜가 출력됩니다.

두 번째 인자는 옵션 객체입니다.

옵션 객체는 정해진 키들이 있으며, 이 키에 값을 표시해서 옵션 객체를 구성한 후 인자로 넘기게 됩니다. 옵션에 대한 것은 뒤에서 설명합니다.

//기본 사용 방법
const today = new Date();
const tIntl1 = new Intl.DateTimeFormat("en-US").format(today);
const tIntl2 = new Intl.DateTimeFormat("ko-KR").format(today);
console.log(tIntl1);
console.log(tIntl2);
//상대 시간 출력
const rtIntl1 = new Intl.RelativeTimeFormat("en").format(calcDateDiff('day', date1, date2), 'day');
const rtIntl2 = new Intl.RelativeTimeFormat("ko").format(calcDateDiff('hour', current, date2), 'hour');
console.log(rtIntl1);
console.log(rtIntl2);
자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

옵션 설정

국제환 API 표시의 옵션 설정은 옵션 객체를 통해 합니다.

옵션 객체에 사용할 수 있는 옵션 값은 미리 정해져 있으며, 다음과 같이 옵션 객체를 만들어서 인자로 넘기게 됩니다.

// 주요 옵션
const options = {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
    hour: 'numeric',
    minute: 'numeric',
    second: 'numeric',
    fractionalSecondDigits: 3,
    hour12: false,
    weekday: 'long',
    timeZone: 'Asia/Seoul',
    calendar: 'korean'
};

//개별 설정
options.timeZone = 'UTC';
options.timeZoneName = 'long';

// 필요한 옵션만 설정
const options2 = {
    hour: 'numeric', minute: 'numeric', second: 'numeric',
    timeZone: 'America/New_york',
    timeZoneName: 'short'
};

const date = new Date();
console.log(new Intl.DateTimeFormat("ko-KR", options).format(date));
console.log(new Intl.DateTimeFormat('en-US', options2).format(date));
자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan

사용할 수 있는 값들도 정해져 있으므로, 사용할 수 있는 값 범위 안에서만 사용해야 합니다.

사용할 수 없는 값이나, 인식하지 못하는 속성 값이 있으면 다음과 같이 자바스크립트 에러를 발생시킵니다.

속성 값을 사용할 때는 사용할 수 있는 값인지 미리 확인해야 합니다.

자바스크립트 문자열 날짜 변환 - jabaseukeulibteu munjayeol naljja byeonhwan