Study JavaScript 0530 - 1hr Date 객체와 날짜

변승훈·2022년 5월 30일
0

Study JavaScript

목록 보기
24/43

Date 객체와 날짜

날짜를 저장할 수 있고, 날짜와 관련된 메소드도 제공해주는 내장 객체 Date에 대해 알아보자.

Date 객체를 활용하면 생성 및 수정 시간을 저장하거나 시간을 측정할 수 있고, 현재 날짜를 출력하는 용도 등으로 활용할 수 있다.

1. 객체 생성하기

new Date()를 호출하면 새로운 Date 객체가 만들어 지는데, new Date()는 다음과 같은 형태로 호출할 수 있다.

1-1. new Date()

인수 없이 호출하면 현재 날짜와 시간이 저장된 Date 객체가 반환된다.

let now = new Date();
console.log( now ); // 현재 날짜 및 시간이 출력

1-2. new Date(milliseconds)

UTC 기준(UTC+0) 1970년 1월 1일 0시 0분 0초에서 milliseconds 밀리초(1/1000 초) 후의 시점이 저장된 Date 객체가 반환된다.

// 1970년 1월 1일 0시 0분 0초(UTC+0)를 나타내는 객체
let Jan01_1970 = new Date(0);
console.log( Jan01_1970 );

// 1970년 1월 1일의 24시간 후는 1970년 1월 2일(UTC+0)
let Jan02_1970 = new Date(24 * 3600 * 1000);
console.log( Jan02_1970 );

1970년의 첫날을 기준으로 흘러간 밀리초를 나타내는 정수는 타임스탬프(timestamp) 라고 부른다.

타임스탬프를 사용하면 날짜를 숫자 형태로 간편하게 나타낼 수 있다. new Date(timestamp)로 타임스탬프를 사용해 특정 날짜가 저장된 Date 객체를 손쉽게 만들 수 있고 date.getTime() 메소드를 사용해 Date 객체에서 타임스탬프를 추출하는 것도 가능하다.

1970년 1월 1일 이전 날짜에 해당하는 타임스탬프 값은 음수다. 예시를 살펴보자!

// 1969 12 31
let Dec31_1969 = new Date(-24 * 3600 * 1000);
console.log( Dec31_1969 );

1-3. new Date(datestring)

인수가 하나인데 문자열이라면 해당 문자열은 자동으로 구문 분석(parsed)된다. 구문 분석에 적용되는 알고리즘은 Date.parse에서 사용하는 알고리즘과 동일하다.

let date = new Date("2022-05-30");
console.log(date);
// 인수로 시간은 지정하지 않았기 때문에 GMT 자정이라고 가정하고
// 코드가 실행되는 시간대(timezone)에 따라 출력 문자열이 바뀐다.
// 따라서 콘솔 창엔
// Thu May 30 2017 11:00:00 GMT+1100 (Australian Eastern Daylight Time)
// 혹은
// Wed May 29 2017 16:00:00 GMT-0800 (Pacific Standard Time)등이 출력된다.

1-4. new Date(year, month, date, hours, minutes, seconds, ms)

주어진 인수를 조합해 만들 수 있는 날짜가 저장된 객체가 반환된다(지역 시간대 기준). 첫 번째와 두 번째 인수만 필수 값이다.

  • year는 반드시 네 자리 숫자여야 한다.
  • month는 0(1월)부터 11(12월) 사이의 숫자여야 한다.
  • date는 일을 나타내는데, 값이 없는 경우엔 1일로 처리된다.
  • hours/minutes/seconds/ms에 값이 없는 경우엔 0으로 처리된다.
new Date(2022, 0, 1, 0, 0, 0, 0); // 2022년 1월 1일, 00시 00분 00초
new Date(2022, 0, 1); // hours를 비롯한 인수는 기본값이 0이므로 위와 동일

let date = new Date(2022, 0, 1, 2, 3, 4, 567);
console.log( date ); // 2022년 1월 1일, 02시 03분 04.567초

2. 날짜 구성요소 얻기

Date 객체의 메소드를 사용하면 연, 월, 일 등의 값을 얻을 수 있다.

  • getFullYear(): 연도(네 자릿수)를 반환한다. 여기서 getYear()메소드도 있는데 두 자릿수 연도를 반환하는 경우가 있기에 사용하지 말자!
  • getMonth(): 월을 반환한다(0 이상 11 이하).
  • getDate(): 일을 반환한다(1 이상 31 이하).
  • getHours(), getMinutes(), getSeconds(), getMilliseconds(): 각각 시, 분, 초, 밀리초를 반환한다.
  • getDay(): 요일을 반환한다. 일요일(0) 부터 시작해서 토요일(6)로 끝나며 일요일이 0임을 꼭 기억해두자!

위의 메소드들은 모두 현지 시간 기준 날짜 구성요소를 반환한다!
각 메소드들 get다음에 "UTC"를 붙혀주면 표준시(UTC+0) 기준으로 반환해준다.

아래 두 메소드들은 UTC기준의 날짜 구성 요소를 반환해주는 메소드가 없는 메소드들 이다.

-getTime(): 주어진 일시와 1970년01월01일 00시 00분 00초 사이의 간격(밀리초 단위)인 타임스태프를 반환한다.

  • getTimezoneOffset(): 현지 시간과 표준 시간의 차이(분)를 반환한다.
// UTC-1 시간대에서 이 예시를 실행하면 60이 출력된다.
// UTC+3 시간대에서 이 예시를 실행하면 -180이 출력된다.
console.log( new Date().getTimezoneOffset() );

3. 날짜 구성요소 설정하기

아래의 메소드를 사용하면 날짜 구성요소를 설정할 수 있다.

  • setFullYear(year, [month], [date])
  • setMonth(month, [date])
  • setDate(date)
  • setHours(hour, [min], [sec], [ms])
  • setMinutes(min, [sec], [ms])
  • setSeconds(sec, [ms])
  • setMilliseconds(ms)
  • setTime(milliseconds) (1970년 1월 1일 00:00:00 UTC부터 밀리초 이후를 나타내는 날짜를 설정)

setTime()을 제외한 모든 메서드는 setUTCHours()같이 표준시에 따라 날짜 구성 요소를 설정해주는 메소드가 있다.

setHours와 같은 메소드는 여러 개의 날짜 구성요소를 동시에 설정할 수 있는데, 메소드의 인수에 없는 구성요소는 변경되지 않는다.

let today = new Date();

today.setHours(0);
console.log(today); // 날짜는 변경되지 않고 시만 0으로 변경된다.

today.setHours(0, 0, 0, 0);
console.log(today); // 날짜는 변경되지 않고 시, 분, 초가 모두 변경된다(00시 00분 00초).

4. 자동 고침

Date 객체엔 자동 고침(autocorrection) 이라는 유용한 기능이 있다.
범위를 벗어나는 값을 설정하려고 하면 자동 고침 기능이 활성화 되면서 값이 자동으로 수정된다.

let date_0132 = new Date(2022, 0, 32); // 2022년 1월 32일은 없다.
console.log(date_0132); // 2022년 2월 1일이 출력된다.

입력받은 날짜 구성 요소가 범위를 벗어나면 초과분은 자동으로 다른 날짜 구성요소에 배분된다.

특정 년월일의 이틀 뒤 날짜를 구하고 싶다고 가정하자. 근데 윤년인지 아닌지를 모르는 년도의 2월 28일 선택하면 어떻게 될까? 이럴 때는 고민할 필요 없이 단순히 이틀을 더해주면 해결된다. Date 객체가 알아서 처리해주기 때문이다.

let leap_year = new Date(2016, 1, 28);
leap_year.setDate(leap_year.getDate() + 2);

console.log( leap_year ); // 2016년 3월 1일

자동 고침은 일정 시간이 지난 후의 날짜를 구하는데도 종종 사용된다.
지금부터 70초 후의 날짜를 구해보자!

let date = new Date();
date.setSeconds(date.getSeconds() + 70);

console.log( date ); // 70초 후의 날짜가 출력

0이나 음수를 날짜 구성요소에 설정하는 것도 가능하다.

let date = new Date(2016, 0, 2); // 2016년 1월 2일

date.setDate(1); // 1일로 변경
console.log( date ); // 01 Jan 2016

date.setDate(0); // 일의 최솟값은 1이므로 0을 입력하면 전 달의 마지막 날을 설정한 것과 같은 효과
console.log( date ); // 31 Dec 2015

5. Date 객체를 숫자로 변경해 시간차 측정하기

Date 객체를 숫자형으로 변셩하면 타임스태프(date.getTime()을 호출 시 반환되는 값)가 된다.

let date = new Date();
console.log(+date); // 타임스탬프(date.getTime()를 호출한 것과 동일함)

이를 응용하면 날짜에 마이너스 연산자를 적용해 밀리초 기준 시차를 구할 수 있다.
시차를 측정해 나만의 스톱워치를 만들어보자!

let start = new Date(); // 측정 시작

// 원하는 작업을 수행
for (let i = 0; i < 100000; i++) {
  let doSomething = i * i * i;
}

let end = new Date(); // 측정 종료

console.log( `반복문을 모두 도는데 ${end - start} 밀리초가 걸렸습니다.` );

6. Date.now()

Date 객체를 만들지 않고도 시차를 측정할 방법이 있다.

현재 타임스탬프를 반환하는 메서드 Date.now()를 응용하면 된다.

Date.now()new Date().getTime()과 의미론적으로 동일하지만 중간에 Date 객체를 만들지 않는다는 점이 다르다. 따라서 new Date().getTime()를 사용하는 것보다 빠르고 가비지 컬렉터의 일을 덜어준다는 장점이 있다.

javascript를 사용해 게임을 구현한다던가 전문분야의 애플리케이션을 구현할 때와 같이 성능이 중요한 경우와 편의를 위해 Date.now()가 자주 활용된다.

위 예시를 Date.now()를 사용해 변경하면 성능이 더 좋다.

let start = Date.now(); // 1970년 1월 1일부터 현재까지의 밀리초

// 원하는 작업을 수행
for (let i = 0; i < 100000; i++) {
  let doSomething = i * i * i;
}

let end = Date.now(); // done

alert( `반복문을 모두 도는데 ${end - start} 밀리초가 걸렸습니다.` ); // Date 객체가 아닌 숫자끼리 차감함

7. 벤치마크 테스트

벤치마크 테스트는 비교 대상을 두고 성능을 비교하여 시험하고 평가할 때 쓰인다.
CPU를 많이 잡아먹는 함수의 신뢰할만한 벤치마크(평가 기준)를 구하려면 상당한 주의가 필요하다.

다음은 두 날짜의 차이를 계산해주는 함수의 성능을 비교해보는 예시이다.

function diffSubtract(date1, date2) {
  return date2 - date1;
}

function diffGetTime(date1, date2) {
  return date2.getTime() - date1.getTime();
}

function bench(f) {
  let date1 = new Date(0);
  let date2 = new Date();

  let start = Date.now();
  for (let i = 0; i < 100000; i++) f(date1, date2);
  return Date.now() - start;
}

let time1 = 0;
let time2 = 0;

// 함수 bench를 각 함수(diffSubtract, diffGetTime)별로 10번씩 돌립니다.
for (let i = 0; i < 10; i++) {
  time1 += bench(diffSubtract);
  time2 += bench(diffGetTime);
}

console.log( 'diffSubtract에 소모된 시간: ' + time1 );
console.log( 'diffGetTime에 소모된 시간: ' + time2 );

8. Date.parse와 문자열

메소드 Date.parse(str)를 사용하면 문자열에서 날짜를 읽어올 수 있다.
단, 문자열 형식은 YYYY-MM-DDTHH:mm:ss.sssZ처럼 생겨야 한니다.

  • YYYY-MM-DD: 날짜(연-월-일)
  • "T": 구분 기호로 쓰임
  • HH:mm:ss.sss: 시:분:초.밀리초
  • 'Z'(옵션): +-hh:mm 형식의 시간대를 나타낸다. Z 한 글자인 경우엔 UTC+0을 나타낸다.

YYYY-MM-DD, YYYY-MM, YYYY같이 더 짧은 문자열 형식도 가능하다.

위 조건을 만족하는 문자열을 대상으로 Date.parse(str)를 호출하면 문자열과 대응하는 날짜의 타임스탬프가 반환된다. 문자열의 형식이 조건에 맞지 않은 경우엔 NaN이 반환된다.

let ms = Date.parse('2012-01-26T13:51:50.417-07:00');

console.log(ms); // 1327611110417  (타임스탬프)

Date.parse(str)를 이용하면 타임스탬프만으로도 새로운 Date 객체를 바로 만들 수 있다.

let date = new Date( Date.parse('2012-01-26T13:51:50.417-07:00') );

console.log(date);
profile
잘 할 수 있는 개발자가 되기 위하여

0개의 댓글