2

タイムゾーンの GMT からのオフセット (たとえば、太平洋夏時間の場合は -7 時間) を指定すると、ローカル時間をユーザーに表示するのは非常に簡単であることを理解しています。

しかし、長期間 (たとえば 1 年間) 正しい現地時間を表示し続けたい場合はどうすればよいでしょうか。GMT からのオフセットだけでは、ユーザーがどのタイムゾーンにいるのかわかりません。たとえば、-7 を指定すると、ユーザーは米国またはカナダ (または他の国) に住んでいる可能性があります。これらの国では、1 年のさまざまな時点で現地時間が異なります (たとえば、米国が 3 月に夏時間に、CA が 4 月に変更された場合)。

私の質問は、上記の段落は正しいですか? GMT オフセットを取得して、ユーザーがどのタイムゾーンにいるのかを推測する標準的な方法はありますか?

4

1 に答える 1

1

あなたの結論は正しいです: offset-from-UTC からタイムゾーンを特定する信頼できる方法はありません。

のオフセットの例として、現在のリストに含まれる可能性のあるタイム ゾーンを約30 個-07:00数えます: 、、および。America/BoiseAmerica/ChihuahuaAmerica/Edmonton

タイムゾーンは実際にはオフセットの集まりでありその地域で一定期間使用された特定のオフセットを使用して経時的に行われた変更を記録し、その後別の一定期間にわたって変更されました。

たとえば、America/Los_Angeles各年の一部には のオフセットが-08:00あり、年の別の部分には があり-07:00ます。そのため、そのタイム ゾーンは、年に少なくとも 2 つのオフセットの履歴を蓄積しています。対照的に、タイムゾーンを使用する隣接地域America/Phoenixは、オフセットの変化を蓄積しておらず-07:00、何十年も同じオフセットを保持しています。

したがって、オフセットとタイム ゾーンの間には多対多の関係があります。オフセットは、1 つ以上のタイム ゾーンで表示される場合があります。また、各タイム ゾーンには 1 つまたは複数のオフセットを設定できます (履歴によって変更されています)。

タイムゾーン名を含める

これが、java.time クラスの設計者が、オフセットのみを使用して標準のISO 8601形式を拡張し、タイム ゾーンの名前を角括弧で追加するZonedDateTime自由をメソッドに持たせた理由です。toString

たとえば2007-12-03T10:15:30+01:00、クラスは単に標準形式を生成するのではなく、 Europe/Paris2007-12-03T10:15:30+01:00[Europe/Paris]というゾーンの名前を追加して生成します。

ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )
             .toString()

2007-12-03T10:15:30+01:00[ヨーロッパ/パリ]

タイムゾーン名を追加するというこの慣習が定着することを願っています。タイム ゾーン名の欠如は、ISO 8601 の設計において際立った仕事をした標準化委員会による驚くべき省略です。

ビジネス シナリオのコンテキストからの手がかりを使用して、タイム ゾーンを推測できます。しかし、私はそれに対して忠告します。特に世界中の政治家はタイムゾーンを頻繁に再定義する傾向があるため、推測は危険です.

UTC

日時値の格納、シリアル化、および交換のベスト プラクティスは、一般にUTCに調整することです。日時ライブラリのtzdataが最新であると仮定すると、UTC に調整すると、常に正確で明確な信頼できる値が得られます。

たとえば Java では、Instantオブジェクトを使用または抽出することを意味します。このクラスは、 UTCInstantのタイムライン上の瞬間をナノ秒単位(小数点以下 9 桁まで) で表します。

Instant instant = Instant.now();

…または…</p>

ZonedDateTime zdt = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
Instant instant = zdt.toInstant();

このような値を表す標準の ISO 8601 形式の文字列は、UTCZの略で意味のある を使用します。Zulu

2007-12-03T09:15:30Z

OffsetDateTime

オフセットのみの日時を表す文字列が与えられた場合は、それをOffsetDateTimeオブジェクトとして解析します。

OffsetDateTime odt = OffsetDateTime.parse( "2007-12-03T10:15:30+01:00" );

odt.toString(): 2007-12-03T10:15:30+01:00

そこから、UTC の値を抽出できますInstant

Instant instant = odt.toInstant();

インスタント.toString(): 2007-12-03T09:15:30Z

または、目的のタイム ゾーンに調整して、オブジェクトと同じ瞬間を取得することもできZonedDateTimeます。

ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );

zdt.toString(): 2007-12-03T14:45:30+05:30[アジア/コルカタ]

用語: 「ローカル」</h1>

地域の特定の壁時計時間に調整された日付/時間を参照する場合は、「ローカル」という用語を避けることをお勧めします。java.time クラスやその他の文脈における「ローカル」という言葉は、特定の地域ではなく、任意の地域を意味します。ローカル日付/時間は、タイムライン上の特定の瞬間ではなく、考えられる瞬間の範囲についての大まかなアイデアにすぎません。

たとえば、今年のクリスマスの始まりのローカル日時は です2017-12-25T00:00:00が、その真夜中の瞬間はコルカタよりもオークランドの方がはるかに早く、パリではさらに数時間遅く、モントリオールではさらに数時間遅くなります。

代わりに、特定のタイム ゾーンのレンズを通して見た特定の瞬間を意味する用語を使用することをお勧めしますzonedwall-clock time

ヒント: オフセット リテラル

質問は-7、オフセットを参照するときにたまたま文字を使用していました。私はいつも提案します:

  • ISO 8601 で要求されているように、パディング ゼロで 2 桁を使用する
  • 一部のライブラリと形式で期待されるように、時間と分の両方を使用します。

-07:00ではなく使用して-7ください。

于 2017-02-15T22:54:45.067 に答える