[JavaScript] Date 객체
서론
날짜, 시계열 데이터를 다룰 때 유용한 Date객체에 대해 알아보려합니다. 날짜는 정말 다양한 곳에서 사용됩니다. 가장 일반적으로 웹페이지, 어플리케이션 등에서 조회를 할 때도 사용되고, 시계열 데이터가 들어간 자료를 만들때도 활용됩니다. 제대로 정리를 해놓으면 저 스스로에게도 다시 찾아와서 참고할 수 있는 글이 될테니 꼼꼼히 적을 생각입니다. 아래 소개할 내용으로 Date 객체생성, 메소드(내장함수), 날짜표현 형식변경, 날짜계산 등에 대해 다룰 예정입니다.
목차
- Date 객체
- 메소드
- get메소드 : getFullYear(), getMonth(), getDate(), getDay(), getHour(), getMinutes(), getSeconds(), getMilliseconds()
- 날짜 Format표현 (YYYY-MM-DD, YYYYMMDD 등)
- n일전 날짜구하는 함수 만들기
Date 객체 생성
date객체는 아래와 같이 new Date()를 변수에 할당하여 생성하며, 아래와 같이 객체생성시 인수를 공백으로 두면 현재 컴퓨터에 표기되는 로컬시간을 나타냅니다. 만약 구체적인 날짜정보를 입력하면 입력정보를 표기합니다.
let now = new Date(); // Date 객체 생성
console.log(now); // 로컬 컴퓨터에 설정된 날짜 기준으로 표기됨
let d = new Date(2022, 4, 29, 19, 34, 20, 0);
// year, month, day, hour, minute, second, millsecond 순으로 입력
// 단, 월은 1월이 0, 2월이 1, 3월이 2 순으로 1씩 차이가 남
console.log(d);
메소드(내장함수)
Date객체의 년,월,일,요일,시간,분,초,밀리초(1000밀리초 = 1초)를 구하는 메소드는 아래와 같습니다.
- getFullYear(), getMonth(), getDate(), getDay(), getHour(), getMinutes(), getSeconds(), getMilliseconds()
// get 함수들
const year = now.getFullYear(); // 년도
let month = now.getMonth(); // 월, 1월이 0
const day = now.getDate(); // 날짜
const dayIndex = now.getDay(); //요일, 일요일이 0, 월요일이 1
console.log(year, month, day, dayIndex);
const hour = now.getHours(); // 시간
const minute = now.getMinutes(); // 분
const second = now.getSeconds(); // 초
const millsecond = now.getMilliseconds(); //밀리초
위 메소드에서 주의할 점은 월을 구하는 getMonth()와 요일을 구하는 getDay() 입니다.
getMonth의 경우 0은 1월을 의미하고 1은 2월을 의미합니다 이런식으로 값과 실제 월과 1씩 차이가 나므로, 필요에 따라 1씩 가감을 해야겠습니다. 마찬가지로 getDay또한 일요일을 0으로 시작하여 토요일은 6이 되는 구조이니 유의하셔야 겠습니다.
날짜표현(예시 : YY-MM-DD)
위에서 배운 메소드를 활용해서 날짜를 YY-MM-DD 형식으로 바꾸는 방법에 대해 알아보겠습니다. 꽤나 단순한 문제입니다. date객체에 toString()을 적용하여 문자열 객체로 변환한 뒤, 문자열 내장함수를 적용하면 됩니다.
const year = now.getFullYear(); // 년도
let month = now.getMonth(); // 월, 1월이 0
const day = now.getDate(); // 날짜
month = month + 1; // 1월이 0부터 시작하다 보니 1 더해줌
console.log(
year +
'-' +
month.toString().padStart(2, 0) +
'-' +
day.toString().padStart(2, 0)
);
위 예시에서 연도, 월, 일을 메소드를 통해 추출하였습니다. 하지만 이 값들은 Date객체이므로 문자열 객체 내장함수를 사용하지 못합니다.
따라서 toString()을 사용하여 문자열 객체로 변경을 하고, 문자열 내장함수 padStart와 문자열 합연산을 이용하여 날짜표현 포맷을 구현합니다.
(참고) padStart 메소드란? 2개의 파라미터를 받는 문자열 메소드입니다. 첫 번째 자리에는 표현할 문자 자릿수, 두 번째 자리에는 표현할 문자 자릿수만큼 문자가 충분하지 않을 때 대신 채워넣을 문자 또는 숫자를 입력합니다.
n일 이전/이후 날짜 구하는 함수 만들기
마지막으로, n일 이전 또는 이후 날짜를 표현하는 함수를 만들어보려 합니다. 단순히 생각해서 getDate()로 할당한 날짜 변수에 n일을 가감하면 될 것 같지만, 실제 매달의 일수가 다르기도 하고 윤달이 포함되어있는 해는 2월이 29일까지 있기 때문에 위 방식으로는 년, 월 등을 알맞게 표현할 수 없습니다. 이럴때 Milliseconds개념을 활용하면 해결할 수 있습니다.
- 밀리세컨즈를 통해 알아보는 Date객체 기준점
let d2 = new Date(0);
console.log(d2); // 1970/01/01 이때를 기준으로 계산됨
// 1초 1000밀리초
// 하루 24 * 60 * 60 *1000
console.log(new Date(24 * 60 * 60 * 1000)); // 1970/01/02 딱 하루만큼 지남
위에 코드에서 객체에 0 milliseconds를 주면 1970년 1월 1일이 나옵니다. 이게 무슨 날인진 모르겟지만... date객체에 0값을 주었을 때 저 날이 표현되는 걸로 보아 1970.01.01이 계산의 기준점이 됩니다. 확인을 하기 위해 1일을 밀리세컨즈로 표현을 해보면 24시간 x 60분 x 60초 x 1000밀리세컨즈 이므로 해당값을 date 객체 안에 넣어봅니다.
역시나 기준값으로 부터 하루 뒤인 1970년 1월 2일이 나옵니다.
- 밀리세컨즈로 날짜구하는 함수 만들기
위에서 하루를 밀리세컨즈로 계산한것 처럼, 모든 시간은 밀리세컨즈로 표현할 수 있습니다. 이 방식으로 날짜계산을 진행하고 그 이후 year, month, day를 분리 표현해주면 우리가 원하는 값을 쉽게 얻을 수 있습니다.
참고로 Date객체를 밀리세컨즈로 계산해주는 메소드는 getTime() 메소드입니다. 그럼 아래 코드를 살펴보겠습니다.
function getIntervalDate(day) {
let now = new Date(); // date 객체생성
let dayMilliseconds = 24 * 60 * 60 * 1000; // 하루를 밀리세컨즈로 계산
let currentMilliseconds = now.getTime(); // 현재 시간을 밀리세컨드로 표현해주는 메소드
let intervalDate = currentMilliseconds + day * dayMilliseconds;
// 밀리세컨즈로 단위가 통일된 변수들을 계산
return new Date(intervalDate);
console.log(getIntervalDate(-7));
console.log(getIntervalDate(-30));
console.log(getIntervalDate(5));
먼저 사용자가 원하는 n일 전/후 값을 위해 n값을 파라미터로 받는 함수를 만들겠습니다.
now 변수에 date객체를 형성하고, 하루시간을 밀리세컨즈로 표현한 dayMilliseoconds 변수를 할당합니다.
여기에 now변수에 밀리세컨즈로 변환해주는 getTime메소드를 사용합니다.
이제 밀리세컨즈로 계산할 변수들의 단위를 모두 통일시켰으니, 위 코드와 같이 계산해서 intervalDate변수에 넣어주기만 하면 됩니다. 그리고 date객체 안에 밀리세컨즈값을 갖고 있는 intervalDate 값을 넣으면 아래 콘솔표현 처럼 날짜가 출력됩니다.
위 식에 사용자가 원하는 format으로 출력하는 기능까지 추가해보겠습니다. 함수가 이젠 사용자가 원하는 날짜 수뿐만 아니라 날짜형식도 입력토록 변경하였습니다.
function getIntervalDateFormat(day, format) {
let now = new Date();
let dayMilliseconds = 24 * 60 * 60 * 1000;
let currentMilliseconds = now.getTime();
let intervalDate = currentMilliseconds + day * dayMilliseconds;
let d = new Date(intervalDate);
// 여기까진 위 예시와 똑같습니다
// 이제 date객체 값을 toString()를 통해 String객체로 변환한 뒤, 문자열 메소드를 사용하도록 합니다
let year = d.getFullYear();
let month = (d.getMonth() + 1).toString().padStart(2, 0);
let date = d.getDate().toString().padStart(2, 0);
//사용자한테 입력받은 문자열 포맷을 replace 메소드를 통해 변수들과 교체해 줍니다.
// YY => year, MM => month, DD => date
return format
.replace('YYYY', year)
.replace('MM', month)
.replace('DD', date);
}
console.log(getIntervalDateFormat(5,"DD-MM-YYYY"));
위 코드를 보면 밀리세컨즈로 계산한 날짜 값을 getFullyear(), getMonth(), getDate() 메소드를 활용하여 변수 year, month, date에 각각 할당해주고 이를 replace 함수를 활용하여 사용자가 입력한 날짜 포맷값의 각 요소값에 대응을 해줍니다. 즉, 사용자가 yyyy.mm.dd를 입력하든 dd-yy-mm 으로 이질적인 방식의 날짜타입을 입력하든 replace함수를 통해 모두 대응할 수 있습니다.
코드에서 입력한 대로 5일 뒤의 날짜인 16일 그리고 "날짜 - 월 - 연도"의 포맷으로 출력이 된걸 확인할 수 있습니다.
결론
Date객체는 배울 때는 어렵지 않아서 쉽게 넘어갔다가, 막상 쓸라고 하면 정확히 기억이 나지 않아 다시 인터넷을 검색하게 만드는 그런 녀석인 것 같습니다. 하지만 날짜를 다룬다는 점에서 어떠한 개발을 하던 간에 실무에서 자주 쓰일 수 밖에 없습니다. 날짜의 각 요소를 파악하는 메소드들에 대해 파악하고, 날짜계산을 할때는 밀리세컨즈 단위로 낮춰서 계산을 하면 수월해진다는 점, 그리고 날짜관련 포맷을 구현할 때는 문자열 객체로 변환한 뒤, padStart(), replace() 등 과 같은 문자열 메소드를 활용하면 쉽게 해결이 된다는 점을 유의하면 좋을 것 같습니다.