왜 ZoneOffset.UTC! = ZoneId.of ( "UTC")입니까?


125

ZonedDateTime now = ZonedDateTime.now();
System.out.println(now.withZoneSameInstant(ZoneOffset.UTC)
        .equals(now.withZoneSameInstant(ZoneId.of("UTC"))));

인쇄 false?

ZonedDateTime인스턴스가 같을 것으로 예상합니다 .

답변:


180

대답은 (강조 내) 의 javadocZoneId 에서 나옵니다 .

ZoneId는 Instant와 LocalDateTime간에 변환하는 데 사용되는 규칙을 식별하는 데 사용됩니다. ID에는 두 가지 유형이 있습니다.

  • 고정 오프셋-모든 현지 날짜-시간에 대해 동일한 오프셋을 사용하는 UTC / 그리니치에서 완전히 해결 된 오프셋
  • 지리적 영역-UTC / 그리니치에서 오프셋을 찾기위한 특정 규칙 집합이 적용되는 영역

대부분의 고정 오프셋은 ZoneOffset으로 표시됩니다. ZoneId에서 normalized ()를 호출하면 고정 오프셋 ID가 ZoneOffset으로 표시됩니다.

... 그리고 (강조 내) 의 javadoc에서ZoneId#of :

이 메서드는 ZoneId 또는 ZoneOffset을 생성하는 ID를 구문 분석합니다. ID가 'Z'이거나 '+'또는 '-'로 시작하는 경우 ZoneOffset이 반환됩니다 .

인수 id는로 지정 "UTC"되므로 ZoneId오프셋과 함께 를 반환하며 문자열 형식으로도 표시됩니다.

System.out.println(now.withZoneSameInstant(ZoneOffset.UTC));
System.out.println(now.withZoneSameInstant(ZoneId.of("UTC")));

출력 :

2017-03-10T08:06:28.045Z
2017-03-10T08:06:28.045Z[UTC]

equals비교를 위해 방법을 사용할 때 객체 동등성확인합니다 . 설명 된 차이로 인해 평가 결과는 다음과 같습니다.false 입니다.

normalized()문서에 제안 된 방법이 사용되며, 사용 비교 equals리턴이 true같은 normalized()대응을 리턴한다 ZoneOffset:

시간대 ID를 정규화하여 가능한 경우 ZoneOffset을 반환합니다.

now.withZoneSameInstant(ZoneOffset.UTC)
    .equals(now.withZoneSameInstant(ZoneId.of("UTC").normalized())); // true

설명서에 나와 있듯이 "Z"또는 "+0"입력 ID로 사용 of하면을 ZoneOffset직접 반환하고 normalized()다음 을 호출 할 필요가 없습니다 .

now.withZoneSameInstant(ZoneOffset.UTC).equals(now.withZoneSameInstant(ZoneId.of("Z"))); //true
now.withZoneSameInstant(ZoneOffset.UTC).equals(now.withZoneSameInstant(ZoneId.of("+0"))); //true

동일한 날짜 시간을 저장 하는지 확인하려면 isEqual대신 메서드를 사용할 수 있습니다 .

now.withZoneSameInstant(ZoneOffset.UTC)
    .isEqual(now.withZoneSameInstant(ZoneId.of("UTC"))); // true

견본

System.out.println("equals - ZoneId.of(\"UTC\"): " + nowZoneOffset
        .equals(now.withZoneSameInstant(ZoneId.of("UTC"))));
System.out.println("equals - ZoneId.of(\"UTC\").normalized(): " + nowZoneOffset
        .equals(now.withZoneSameInstant(ZoneId.of("UTC").normalized())));
System.out.println("equals - ZoneId.of(\"Z\"): " + nowZoneOffset
        .equals(now.withZoneSameInstant(ZoneId.of("Z"))));
System.out.println("equals - ZoneId.of(\"+0\"): " + nowZoneOffset
        .equals(now.withZoneSameInstant(ZoneId.of("+0"))));
System.out.println("isEqual - ZoneId.of(\"UTC\"): "+ nowZoneOffset
        .isEqual(now.withZoneSameInstant(ZoneId.of("UTC"))));

산출:

equals - ZoneId.of("UTC"): false
equals - ZoneId.of("UTC").normalized(): true
equals - ZoneId.of("Z"): true
equals - ZoneId.of("+0"): true
isEqual - ZoneId.of("UTC"): true

4
문서는 또한 "존 ID가 'GMT', 'UTC'또는 'UT'와 같으면 결과는 ZoneOffset.UTC와 동일한 ID 및 규칙을 가진 ZoneId입니다"라고 말합니다. ID와 규칙은 같지만 행동은 다릅니다. ZoneId.of("Z")당신을 제공 ZoneOffset.UTC하지만, ZoneId.of("UTC")당신을 제공합니다 ZoneId(즉 아니다 ZoneOffset.UTC). 이 API는 적어도 직관적이지 않습니다.
Adam Millerchip
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.