Date객체와 날짜

양주영·2021년 8월 29일
0

javascript

목록 보기
13/42

내장 객체 Date는 날짜를 저장할 수 있고, 날짜와 관련된 메서드도 제공해준다.
Date 객체를 활용하면 생성 및 수정 시간을 저장하거나 시간을 측정할 수 있고, 현재 날짜를 출력하는 용도 등으로 활용할 수 있다.


📍 객체 생성하기


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

- new Date()

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

let now = new Date();
alert( now ); // 현재 날짜 및 시간이 출력됨

- 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);
alert( Jan01_1970 );

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

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

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

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

// 31 Dec 1969
let Dec31_1969 = new Date(-24 * 3600 * 1000);
alert( Dec31_1969 );

참고: Date 객체의 중심을 구성하는 시간 값은 UTC 기준이지만, 날짜와 시간 등 구성 요소를 가져오는 메서드는 모두 현지(호스트 시스템의 위치)의 시간대를 사용한다.



- new Date(datestring)

인수가 하나인데, 문자열이라면 해당 문자열은 자동으로 구문 분석(parsed)됩니다. 구문 분석에 적용되는 알고리즘은 Date.parse에서 사용하는 알고리즘과 동일한데, 자세한 내용은 아래에서 다루도록 하겠습니다.

let date = new Date("2017-01-26");
alert(date);
// 인수로 시간은 지정하지 않았기 때문에 GMT 자정이라고 가정하고
// 코드가 실행되는 시간대(timezone)에 따라 출력 문자열이 바뀝니다.
// 따라서 얼럿 창엔
// Thu Jan 26 2017 11:00:00 GMT+1100 (Australian Eastern Daylight Time)
// 혹은
// Wed Jan 25 2017 16:00:00 GMT-0800 (Pacific Standard Time)등이 출력됩니다.

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

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

  • year는 반드시 네 자리 숫자여야 한다.
  • month는 0(1월)부터 11(12월) 사이의 숫자여야 한다.
  • date는 일을 나타내는데, 값이 없는 경우엔 1일로 처리된다.
  • hours/minutes/seconds/ms에 값이 없는 경우엔 0으로 처리된다.

예시:

new Date(2011, 0, 1, 0, 0, 0, 0); // 2011년 1월 1일, 00시 00분 00초
new Date(2011, 0, 1); // hours를 비롯한 인수는 기본값이 0이므로 위와 동일

최소 정밀도는 1밀리초(1/1000초)이다.

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


📍 날짜 구성요소 얻기


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

- getFullYear()

연도(네 자릿수)를 반환한다. getYear()말고 getFullYear()를 사용하자.

- getMonth()

월을 반환한다(0 이상 11 이하).

- getDate()

일을 반환한다(1 이상 31 이하).

- getDay()

일요일을 나타내는 0부터 토요일을 나타내는 6까지의 숫자 중 하나를 반환한다.
몇몇 나라에서 요일의 첫날이 일요일이 아니긴 하지만, getDay에선 항상 0이 일요일을 나타낸다.

- getHours(), getMinutes(), getSeconds(), getMilliseconds()

시, 분, 초, 밀리초를 반환한다.

위 메서드 모두는 현지 시간 기준 날짜 구성요소를 반환한다.

위 메서드 이름에 있는 ‘get’ 다음에 'UTC’를 붙여주면 표준시(UTC+0) 기준의 날짜 구성 요소를 반환해주는 메서드 getUTCFullYear()getUTCMonth()getUTCDay()를 만들 수 있다.

현지 시간대가 UTC 시간대와 다르다면 아래 예시를 실행했을 때 얼럿창엔 다른 값이 출력된다.

// 현재 일시
let date = new Date();

// 현지 시간 기준 시
alert( date.getHours() );

// 표준시간대(UTC+0, 일광 절약 시간제를 적용하지 않은 런던 시간) 기준 시
alert( date.getUTCHours() );

아래 두 메서드는 위에서 소개한 메서드와 달리 표준시(UTC+0) 기준의 날짜 구성 요소를 반환해주는 메서드가 없다.

- getTime()

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

- getTimezoneOffset()

현지 시간과 표준 시간의 차이(분)를 반환한다.

// UTC-1 시간대에서 이 예시를 실행하면 60이 출력됩니다.
// UTC+3 시간대에서 이 예시를 실행하면 -180이 출력됩니다.
alert( new Date().getTimezoneOffset() );


📍 날짜 구성요소 설정하기


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

  • 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);
alert(today); // 날짜는 변경되지 않고 시만 0으로 변경됩니다.

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


📍 자동 고침


자동 고침(autocorrection) 은 범위를 벗어나는 값을 설정하려고 하면 자동 고침 기능이 활성화되면서 값이 자동으로 수정된다.

예시:

let date = new Date(2013, 0, 32); // 2013년 1월 32일은 없습니다.
alert(date); // 2013년 2월 1일이 출력됩니다.

입력받은 날짜 구성 요소가 범위를 벗어나면 초과분은 자동으로 다른 날짜 구성요소에 배분된다.
'2016년 2월 28일’의 이틀 뒤 날짜를 구하고 싶다고 가정해보자. 답은 3월 2일 혹은 3월 1일(윤년)이 될 텐데, 2016년이 윤년인지 아닌지 생각할 필요 없이 단순히 이틀을 더해주기만 하면 답을 구할 수 있다.



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


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

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


📍 Date.now()


현재 타임스탬프를 반환하는 메서드 Date.now()를 응용하면 Date 객체를 만들지 않고도 시차를 측정할 수 있다.
Date.now()는 new Date().getTime()과 의미론적으로 동일하지만 중간에 Date 객체를 만들지 않는다는 점이 다르다. 따라서 new Date().getTime()를 사용하는 것보다 빠르고 가비지 컬렉터의 일을 덜어준다.
편의와 성능이 중요한 경우에 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 객체가 아닌 숫자끼리 차감함


📍 벤치마크 테스트


'벤치마크 테스트’는 비교 대상을 두고 성능을 비교하여 시험하고 평가할 때 쓰인다.

CPU를 많이 잡아먹는 함수의 신뢰할만한 벤치마크를 구하려면 상당한 주의가 필요하다.

두 날짜의 차이를 계산해주는 함수 두 개가 있는데, 어느 함수의 성능이 더 좋은지 알아내야 한다고 가정해보자.

// 두 함수 중 date1과 date2의 차이를 어떤 함수가 더 빨리 반환할까요?
function diffSubtract(date1, date2) {
  return date2 - date1;
}

// 반환 값은 밀리초입니다.
function diffGetTime(date1, date2) {
  return date2.getTime() - date1.getTime();
}

두 함수는 완전히 동일한 작업을 수행하지만, 한 함수는 날짜를 밀리초 단위로 얻기 위해 date.getTime()를 사용하고 있고, 다른 함수는 마이너스 연산자 적용 시 객체가 숫자형으로 변화한다는 특징을 사용하고 있다. 두 함수가 반환하는 값은 항상 동일하다.

속도는 어떨까?

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;
}

alert( 'diffSubtract를 십만번 호출하는데 걸린 시간: ' + bench(diffSubtract) + 'ms' );
alert( 'diffGetTime을 십만번 호출하는데 걸린 시간: ' + bench(diffGetTime) + 'ms' );

형 변환이 없어서 엔진 최적화에 드는 자원이 줄어들므로 getTime()을 이용한 방법이 훨씬 빠르다.

좀 더 신뢰할만한 벤치마크 테스트를 만들려면 benchmark를 번갈아 가면서 여러 번 돌려야 한다.



📍 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-DDYYYY-MMYYYY같이 더 짧은 문자열 형식도 가능하다.
위 조건을 만족하는 문자열을 대상으로 Date.parse(str)를 호출하면 문자열과 대응하는 날짜의 타임스탬프가 반환된다. 문자열의 형식이 조건에 맞지 않은 경우엔 NaN이 반환된다.

예시:

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

alert(ms); // 1327611110417  (타임스탬프)

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


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

alert(date);



참조 : https://ko.javascript.info/date

profile
뚜벅뚜벅

0개의 댓글