2015년 12월 16일 수요일

javascript: Date Object

Javascript Date Object를 소개합니다...


생각날 때 마다 하나의 주제에 대해서 강좌를 써내려갈까 합니다.
언젠가는 많이 모이겠거니... 하는 마음으로요... ㅎㅎ

그럼 시작합니다.

Date객체는 아래와 같이 생성할 수 있죠.

  1. new Date();
  2. new Date( milliseconds );
  3. new Date( dateString );
  4. new Date( year, month, day, hours, minutes, seconds, milliseconds );

Date 객체가 가지고 있는 프로퍼티와 메소드들은 W3Schools에 아주 자세히 나와있으니 한번 살펴보세요.

1. new Date();

이 방법은 가장 단순하게 Date객체를 생성하는 방법이며, 현재 날짜와 시간으로 객체를 생성합니다. 년, 월, 일, 시, 분, 초, 밀리초 가 객체 생성시점으로 초기화 됩니다.


2. new Date( milliseconds );

이 방법은 1970년 1월 1일 0시 0분 0초 0밀리초 부터 넘겨진 milliseconds 까지의 밀리초를 기준으로 객체를 생성하는 방법입니다. 1970년 이전의 날짜를 지정할 때는 음의 정수로 설정할 수 있습니다. 참고로 이 글을 작성하고 있는 2015년 12월 16일 오후 10시 37분 경은 1450273039059 로 표현이 됩니다.

지금이 2015.12.16 22:37 경이라고 할 때,
  • new Date();
  • new Date( 1450273039059 );
위 두 객체는 매우 유사한 값을 같은 객체가 됩니다.


3. new Date( dateString );

여기서 말하는 dateString은 설명이 어려우니 또한번 W3Schools를 방문해 보세요.


4. new Date( year, month, day, hours, minutes, seconds, milliseconds );

위의 3가지 방법과는 달리 파라미터가 유난히 많습니다.
개인적으로는 1번 방법과 함께 가장 중요한 생성자라고 생각이 됩니다.

일반적으로 Date 객체를 사용해서 날짜비교, 날짜 차이계산 등의 연산을 많이 하게 됩니다.

하지만 Date객체의 특성을 제대로 이해하지 못하면 자칫 버그를 만들어낼 가능성이 있습니다.

아래 코드를 한번 살펴봐 주세요.
var today = new Date();
var userInput = new Date( "2015-12-16" );
if( today === userInput ) {
    // L1. 입력날짜가 오늘인 경우 수행할 로직
} else {
    // L2. 입력날짜가 오늘이 아닌경우 수행할 로직
}
위의 코드에서 이상한 점은 무엇일까요? 과연 위의 코드가 의도대로 동작을 할까요?
위에서 L1 로직에 진입하기 위해서는 로또에 당첨될 만큼의 운이 따라줘야 합니다.
console.log( today );
// Wed Dec 16 2015 22:54:55 GMT+0900 (대한민국 표준시)
console.log( userInput );
// Wed Dec 16 2015 09:00:00 GMT+0900 (대한민국 표준시)
위의 결과 예제를 보시면 이해가 되실겁니다.

여기서 첫번째 중요한 사실이 있습니다.
Date객체를 사용할 때는 반드시 시간을 밀리초까지 고려해야 한다는 점입니다.

그럼, 아래의 코드를 봐주세요.
var dateFrom = new Date( "2015-12-16 23:00:00.000" );
var dateTo = new Date( 2015, 11, 16, 23, 0, 0, 0 );
console.log( dateFrom == dateTo ); // false
console.log( dateFrom > dateTo ); // false
console.log( dateFrom < dateTo ); // false
console.log( dateFrom.getTime() == dateTo.getTime() ); // true
console.log( dateFrom.getTime() > dateTo.getTime() ); // false
console.log( dateFrom.getTime() < dateTo.getTime() ); // false
첫번째~세번째 출력결과가 모두 false, 네번째는 true 입니다.
여기서 dateTo를 초기화 할때 12월을 11로 설정한 것은 javascript에서 month 파라미터를 0~11까지범위로 나타내기 때문입니다. 처음 Date객체를 사용하시는 분들은 실수하기 딱 좋은 부분이니 주의해 주셔야 합니다.

다시 본론으로 돌아와서, 도대체 왜 첫번째 ~ 세번째는 모두 false일까요? 같지도 다르지도 않다는 뜻일까요? 첫번째 수식의 비밀은 '==' 연산자에 있습니다. Java와 유사하게 '==' 연산자는 두 객체 자체를 비교합니다. dateFrom과 dateTo는 각각 인스턴스화 된 개별 객체입니다. 그래서 두 객체가 다르다고 표현을 하게 됩니다. 희안하게도 '>', '<' 연산자에 대해서는 operator overloading이 되어 있는지.. 두 객체의 값을 비교하게 됩니다.

어쨌든 제가 말씀드리고자 하는것은, 두 Date객체의 값을 비교할 때는 네번째 방법이 가장 안전하다는 것입니다. 대소비교는 물론이고 등위비교를 할 때도 모두 안전한 방법입니다.
만약 시간, 분, 초, 밀리초는 무시하고 싶을 경우 밀리초값에 약간의 산수를 더하면 정확하게 할 수 있게 됩니다.
var dateFrom = new Date( "2015-12-16" );
var dateTo = new Date( 2015, 11, 16, 23, 25, 49, 555 );
dayFrom = parseInt( dateFrom.getTime() / 1000 / 60 / 60 / 24, 10 );
dayTo = parseInt( dateTo.getTime() / 1000 / 60 / 60 / 24, 10 );
console.log( dateFrom.getTime() == dateTo.getTime() ); // false
console.log( dayFrom == dayTo ); // true
위와 같이 밀리초, 초, 분, 시간 단위를 역산해서 날짜까지만 숫자로 변환을 할수가 있습니다.

오늘은 여기까지 하겠습니다.


댓글 없음:

댓글 쓰기