연관글 : 2012/03/04 - Trac DecoratorPlugin 3차 커스터마이징

개인적으로 개발하고 있는 Trac 플러그인에 JQuery UI Timepicker Addon 를 추가하려는 작업을 하고 있다.

국제화 기능의 완성도를 높이기 위해 타임존 관련 코딩을 하던 중, DST(Daylight saving time: 썸머타임) 가 존재하는
타임존에서 자바스크립트의 Date Object 가 오작동하는 상황을 발견하였다.

<요르단 암만 타임존 (UTC+2) 에서 Date Object 가 오작동하는 사례>


스크린 샷에 나타난 요르단 암만 타임존에서는 2011년 4월 1일 0 시 정각에 DST 가 시작 되었는데,

2011-03-31 23:59:59 초 (UTC+2) 에서 1초 경과 후에 2011-04-01 01:00:00 초 (UTC+3) 가 된다.

따라서, 해당 타임존에서 2011년 4월 1일 0 시 (UTC+2) 는 세상에 존재하지 않는 시간인 것 이다.


해당 타임존에서 Date Object 에 2011년 4월 1일 0시를 직접 입력하면, 2011년 3월 31일 23시 (UTC+2) 로 인식한다.

getTime() 함수 결과도 동일해서 서로 구분할 수 없다.

( 참고: 자바스크립트 Date Object 에서 월은 0~11 까지의 값을 가진다. 1월은 0 , 2월은 1 로 처리함. )


따라서, DST 가 존재하는 타임존에서 특정 날짜의 시간을
Date Object 에 직접 입력해야 할 경우 (날짜 직접 입력, 날짜 산술연산 등등 ...),

Date Object 에 저장된 결과를 getHours() 함수로 읽어서, 원래 입력하려던 시간과 다르다면

( 0 시를 입력했는데 전 날 23 시로 저장되었거나, 02 시를 입력했는데 01 시로 저장되는 등등 ... )

DST 로 전환되는 시점인 세상에 존재하지 않는 시간을 직접 입력해서
자바스크립트 Date Object 가 처리하지 못하고 오작동하는 상황으로 판단해야한다.

( 상식적으로 예상되는 결과가 아니므로 편의상 오작동이라 표현하였으나,
  결과에 대한 논리적인 규칙성이 있으므로
  엄밀히 따지면 오작동이라 볼 수 없고 Javascript 스펙이 그렇게 설계된 것 같다. @.@;; )

이러한 경우에는 setHours() 함수로 2시간을 더해 주거나,
getTime() 함수 결과값에 1시간 == (3600 * 1000) ms 를 더해주거나,
어떤 방식으로던지 DST 가 적용된 실제 시간으로 강제 변경하는 후속 조치를 반드시 해줘야한다.

( new Date(2012,2,1) 형식으로 생성한 경우는 날짜를 직접 입력한 것 이므로 DST 에 대해 후속 조치를 해줘야 한다.

  new Date() 형식으로 생성한 Date Object 를 날짜 직접 입력이나 산술연산 등 이 전혀 없이,
  read only 전용 변수로만 사용한 경우에는 DST 에 대해 아무런 조치를 하지 않아도 안전하다. )


앞서 말한 DST 가 존재하는 타임존에서 자바스크립트 Date Object 가 오작동하는 상황은

로컬 시스템의 운영체제에서 제공하는 시간 정보 (DST 시작일/종료일에 대한 정보)에 전적으로 의존적이다.

따라서, 운영체제에서 애초에 잘못된 DST 시작일/종료일에 대한 정보를 제공하고 있다면
DST 가 적용된 실제 시간으로 강제 변경하는 조치를 해도 제대로 된 결과를 얻을 수 없다.

( 윈도우 XP SP3 에서 이스라엘 예루살렘 타임존 (UTC+2) 으로 2011년 에 대해 테스트하다,
  운영체제에서 DST 시작일/종료일 정보를 부정확하게 제공하는 것을 발견하였다. )


DST 가 존재하는 타임존에서 자바스크립트 Date Object 를 신뢰하면 안된다.

그리고, Server-side 나 다른 개발 언어와의 연동 없이,
Client-side 자바스크립트 만 으로 타임존이나 DST 를 제대로 처리한다는 것은 거의 불가능에 가깝다.

Server-side 나 다른 개발 언어와 연동해서 타임존이나 DST 를 해결하더라도

자바스크립트 Date Objcet 는 오로지 로컬 시간 정보만 처리할 수 있으므로

다른 타임존의 시간 정보는 절대로 Date Object 로 처리해서는 안된다.

Posted by Genie.
,