"2016-02-16"이 "2016-02-16 00:00"과 같지 않은 이유는 무엇입니까?


96

두 날짜 문자열을 모두 new Date(t).

두 문자열이 같은 시간을 나타내기를 기대합니다. 결국 시간을 생략하면 그날 자정이 아니겠습니까?

하지만

new Date("2016-02-16 00:00")

예상대로 2016-02-16, 자정, 현지 시간을 반환합니다.

new Date("2016-02-16")

2016-02-16, 자정 UTC를 반환합니다. 이는 잘못되었거나 다른 문자열이 구문 분석하는 것을 고려할 때 내가 예상했던 것과는 다릅니다.

시간을 현지 시간으로 반환하든 UTC로 반환하든 둘 다 동일한 동작을한다면 이해할 수 있지만, 이와 같이 다른 것을 반환하는 이유는 매우 일관성이 없어 보입니다.

해결 방법으로 해당하는 타임 스탬프가없는 날짜를 발견 할 때마다 "00:00"을 추가하여 일관된 동작을 얻을 수 있지만 이것은 다소 취약한 것처럼 보입니다.

'datetime-local'유형의 INPUT 요소에서이 값을 얻고 있으므로 페이지 요소에서 반환 된 값을 처리해야하는 것이 특히 일치하지 않는 것 같습니다.

내가 뭘 잘못하고있는 건가요, 아니면 다르게해야할까요?


2
2016-02-16 00:00-이것은 전혀 유효한 시간처럼 보이지 않습니다. ecma-international.org/ecma-262/6.0/… ,하지만 T거기에 넣어도 실제로 다르게 동작합니다
zerkms

현재 값을 기준으로 입력 요소에서 Date 객체를 얼마나 정확하게 얻고 있습니까?
BoltClock

4
표준에 따라- "HH, mm 또는 ss 필드가없는 경우"00 "이 값으로 사용되고없는 sss 필드의 값은"000 "입니다. 시간대 오프셋이없는 경우 날짜-시간 현지 시간으로 해석됩니다. " --- 동일하게 작동해야합니다.
zerkms

@BoltClock 흠, 요소의 값 필드를 취하고 (zerkms가 알아 차린 것처럼) 어떤 이유로 T를 제거하는 것처럼 보입니다 (값이 "T"가 혼란 스러울 수있는 컨텍스트에서 사용자에게 표시되고 있기 때문이라고 생각합니다)
Michael

1
@Michael : 환상적입니다. 이와 같은 브라우저 특성이 제가 가장 좋아하는 것입니다. (또는 DOM 사양의
기이 한 것일 수

답변:


100

그것은 무엇 ES5.1 사양 할 말합니다 :

없는 시간대 오프셋 값은 "Z"입니다.

또한 다음과 같이 말합니다.

이 함수는 먼저 날짜 시간 문자열 형식 (15.9.1.15)에서 호출 된 규칙에 따라 문자열의 형식을 구문 분석하려고합니다. 문자열이 해당 형식을 따르지 않는 경우 함수는 구현 별 휴리스틱 또는 구현 별 날짜 형식으로 대체 될 수 있습니다.

형식에는 T날짜와 시간 사이 에 구분자가 필요하므로 유효한 시간은 UTC로 이동합니다.

> new Date("2016-02-16T00:00:00")
Tue Feb 16 2016 01:00:00 GMT+0100 (CET)
> new Date("2016-02-16")
Tue Feb 16 2016 01:00:00 GMT+0100 (CET)

... node.js에서 유효하지 않은 시간 (T 구분 기호 없음)은 구현 특정 현지 시간으로 이동하는 것 같습니다.

> new Date("2016-02-16 00:00:00")
Tue Feb 16 2016 00:00:00 GMT+0100 (CET)

ES6 이것을 변경 했으며 , 문서 의 같은 부분 에서 다음과 같이 변경되었습니다.

시간대 오프셋이 없으면 날짜-시간이 현지 시간으로 해석됩니다.

깨는 기쁨이 합니다.

편집하다

TC39 에 따르면 이 사양은 시간대가없는 날짜 및 시간 문자열 (예 : "2016-02-16T00 : 00 : 00")은 로컬 (ISO 8601에 따라)로 처리되지만 날짜 만 문자열 (예 : "2016-02-16")을 UTC (ISO 8601과 일치하지 않음)로 지정합니다.


20
파괴의 기쁨은 실제로 변합니다. ES7 표준의 새로운 초안 에서 UTC에서 현지 시간으로 변경된 일부가 되돌 렸습니다 . 새로운 표준에서는 시간대가 지정되지 않은 경우 날짜를 UTC로 해석해야하고 시간대가없는 경우 날짜-시간은 현지 시간으로 해석해야한다고 말합니다. 지정됩니다.
hichris123

3
날짜 전용 또는 날짜 시간 형식에 관계없이 둘 다 실제로 현지 시간이어야합니다. 이것이 ISO8601이 작동하는 방식입니다. 시간을 초월한 UTC 날짜가 개념적으로도 의미가 없기 때문에 날짜 전용 형식이 자정 UTC로 해석된다는 것은 말도 안됩니다. ECMA tc39에서 이에 대한 열띤 논쟁이있었습니다. 나는 현지 시간을 위해 싸웠고졌다. github.com/tc39/ecma262/issues/87
Matt Johnson-Pint

10

사양 에 따르면 :

이 함수는 먼저 날짜 시간 문자열 형식 (15.9.1.15)에서 호출 된 규칙에 따라 문자열의 형식을 구문 분석하려고합니다. 문자열이 해당 형식을 따르지 않는 경우 함수는 구현 별 휴리스틱 또는 구현 별 날짜 형식으로 대체 될 수 있습니다.

그리고 날짜 시간 문자열 형식은 동의를 2016-02-16유효한 날짜로

이 형식에는 날짜 전용 양식이 포함됩니다.

YYYY
YYYY-MM
YYYY-MM-DD

[...] HH, mm, ss 필드가 없으면 "00"이 값으로 사용되고 sss 필드가없는 값은 "000"입니다. 없는 시간대 오프셋 값은 "Z"입니다.

따라서 2016-02-16번역한다 2016-02-16T00:00:00.000Z.

다른 날짜 2016-02-16 00:00는 형식을 따르지 않으므로 구문 분석은 구현에 따라 다릅니다. 분명히 이러한 날짜는 현지 시간대가있는 것으로 처리되며 예제 날짜는 시간대에 따라 다른 값을 반환합니다.

/* tz = +05:00 */ new Date("2016-02-16 00:00").toISOString() // 2016-02-15T19:00:00.000Z
/* tz = -08:00 */ new Date("2016-02-16 00:00").toISOString() // 2016-02-16T08:00:00.000Z

요약:

  • 일치하는 날짜 시간 형식의 경우 동작이 잘 정의되어 있습니다. 시간대 오프셋이없는 경우 날짜 문자열은 UTC (ES5) 또는 로컬 (ES6)로 처리됩니다.
  • 일치하지 않는 날짜 시간 형식의 경우 동작은 구현에 따라 다릅니다. 표준 시간대 오프셋이없는 경우 일반적인 동작은 날짜를 로컬로 처리하는 것입니다.
  • 사실 구현 시 부적합 날짜를 구문 분석 하는NaN 대신 반환하도록 선택할 수 있습니다 . Internet Explorer 11에서 코드를 테스트하십시오.)

7

ES5, ES6 구현과 예상 결과 사이에 차이가있을 수 있습니다. 당 다음 Date.parse MDN에서 2015년 10월 12일 12시 0분 0초는 "NaN의 UTC 또는 로컬 시간대로 해석 할 수있다" "특히 같은 문자열이 다른 ECMAScript를 구현에서"중요하다.

Firefox 44와 IE 11의 추가 테스트에서는 둘 다에 대한 날짜 개체를 반환하는 것으로 나타났습니다 new Date("2016-02-16 00:00").이 개체는 날짜 구성 요소 값을 가져 오려고 할 때 NaN을 반환하고 toString 값이 "Invalid Date"( "NaN"아님)입니다. 따라서 "일관된 동작을 얻기 위해 00:00"을 추가하면 다른 브라우저에서 쉽게 중단 될 수 있습니다.

다른 답변에서 언급했듯이 new Date("2016-02-16")기본적으로 0의 시간대 오프셋을 사용하여 로컬 대신 자정 UTC를 생성합니다.


OP는 동일한 구현에서 다른 결과를 얻는 것 같습니다.
Salman A

6

DateParser::Parse()Chrome 용 V8 소스 코드 당 .

ES5 ISO 8601 날짜 :

[('-'|'+')yy]yyyy[-MM[-DD]][THH:mm[:ss[.sss]][Z|(+|-)hh:mm]]

부호없는 숫자 뒤에 ':'이 오는 것은 시간 값이며 TimeComposer에 추가됩니다.

시간대가 없으면 Z가 기본값입니다.

> new Date("2016-02-16 00:00")
  Tue Feb 16 2016 00:00:00 GMT+0800 (China Standard Time)

두 형식 (예 1970-01-01:) 과 일치하는 문자열 은 ES5 날짜-시간 문자열로 구문 분석됩니다. 즉, 기본값은 UTC time-zone입니다. ES5 사양을 따르면 불가피합니다.

> new Date("2016-02-16")
Tue Feb 16 2016 08:00:00 GMT+0800 (China Standard Time)

3

2016-02-16, 자정 UTC를 반환합니다. 이는 잘못되었거나 다른 문자열이 구문 분석하는 것을 고려할 때 내가 예상했던 것과는 다릅니다.

시간대 오프셋을 00:00

new Date("2016-02-16") 출력 Tue Feb 16 2016 05:30:00 GMT+0530 (India Standard Time)

내 시간대는 오프셋 값 (분)이있는 IST +330이므로 330 분을 00:00에 추가했습니다.

ECMA-262, 섹션 20.3.3.2 다음 Date.parse (문자열)

ToString 결과 갑작스러운 완료가 발생하면 완료 레코드가 즉시 반환됩니다. 그렇지 않으면 구문 분석은 결과 문자열을 날짜 및 시간으로 해석합니다. 날짜와 시간에 해당하는 UTC 시간 값인 숫자를 반환합니다. 문자열은 문자열의 내용에 따라 현지 시간, UTC 시간 또는 다른 시간대의 시간으로 해석 될 수 있습니다.

시간 단위 를 명시 적으로 설정 하면 다음 과 new Date("2016-02-16 00:00")같이 설정합니다 .hoursminutes

그렇지 않으면 여기 2 0.3.1.16에 명시된대로

시간대 오프셋이 없으면 날짜-시간이 현지 시간으로 해석됩니다.


예, 그런데 왜 한 경우에는 이것을 수행하지만 다른 경우에는 수행하지 않습니까?
Michael


그렇다면 그 결과가 다른 이유는 무엇입니까? 표준은 동일해야한다고 주장합니다
zerkms

@zerkms Standard는 시간 단위를 통과 할 때 무엇을 할 것인지를 말하고, 그렇지 않을 때 할 일을 말하지 않습니다. 그것이 The String may be interpreted as a local time, a UTC time, or a time in some other time zone, depending on the contents of the String.동일해야한다고 주장하는 곳은 어디인가?
gurvinder372

@ gurvinder372 질문 댓글에 인용문을 제공했습니다. "HH, mm 또는 ss 필드가없는 경우"00 "이 값으로 사용되고없는 sss 필드의 값이"000 "입니다. 시간대 오프셋 인 경우 없는 경우 날짜-시간은 현지 시간으로 해석됩니다. "
zerkms
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.