2

TimeZone Europe/Vienna (+0200) を含む DateTime があります。次のメソッドで取得されます。

settlementService.getPendingPeriodStart()

次のように toString を見てください:

2012-06-01T00:00:00.000+02:00

ここで、この日付 2012-06-01 を java.util.Date として保存したいので、次のようなことを試しました。

transactionDate = settlementService.getPendingPeriodStart().withTime(0, 0, 0, 0).toDate();

しかし、結果は次のとおりです。

2012 年 5 月 31 日木曜日 22:00:00 UTC

DateTime の結果をTimeZone オフセットを含むDate として保存する最良の方法は何ですか? transactionDate は2012-06-01である必要があります。GregorianCalendar をいじることはできますが、それは私が好きなことではありません。これはもっと簡単なはずですよね?

ところで(これが明確でない場合)。ローカル システムは UTC で実行されます。そのため、結果はThu May 31 22:00:00 UTC 2012です。

4

3 に答える 3

1

残念ながら、受け入れられた答えは誤解です。実際のところ、

2012-06-01T00:00:00.000+02:00 = 2012-05-31T22:00:00Z

Z右側の は、ゼロタイムゾーン オフセットのタイムゾーン指定子です。これはズールー語を表し、Etc/UTCタイムゾーンを指定します (時間のタイムゾーン オフセットがあり+00:00ます)。

2012-06-01T00:00:00.000+02:00として記述2012-06-01することは、単なる関数呼び出しの問題ではありますが、タイムゾーンに依存するビジネス ロジックにとっては危険です。2012-06-01は、LocalDate生年月日、結婚日などのイベントを追跡するために使用する必要があります。

java.time

従来の日時 API (java.util日時型とその書式設定型SimpleDateFormatなど) は時代遅れであり、エラーが発生しやすくなっています。java.time使用を完全にやめて、最新の日時 API *に切り替えることをお勧めします。

また、以下はJoda-Time のホームページの通知です。

Java SE 8 以降では、このプロジェクトを置き換える JDK のコア部分である java.time (JSR-310) に移行するように求められることに注意してください。

java.time最新の APIを使用したソリューション:

指定された日時文字列を解析する方法:

指定された日時文字列にはタイムゾーン オフセットがあるため、 に解析する必要がありますOffsetDateTime。最新の日時 API は ISO 8601 に基づいているDateTimeFormatterため、日時文字列が ISO 8601 標準に準拠している限り、オブジェクトを明示的に使用する必要はありません。

OffsetDateTime odt = OffsetDateTime.parse("2012-06-01T00:00:00.000+02:00"); // 2012-06-01T00:00+02:00

UTC で日時を取得する方法:

複数の方法があります。Instant最も簡単な方法は、UTC のタイムライン上の瞬間的なポイントを表すに変換することです。

Instant instant = odt.toInstant(); // 2012-05-31T22:00:00Z

あるいは、

OffsetDateTime odtUtc = odt.withOffsetSameInstant(ZoneOffset.UTC); // 2012-05-31T22:00Z

それから抜け出す方法java.util.Date

java.util.Dateのインスタンスから のインスタンスが必要な場合はOffsetDateTime、 を使用できますDate#from(Instant instant)

Date date = Date.from(instant); // Thu May 31 23:00:00 BST 2012 <--In my timezone

オブジェクトは、最新の日時型のjava.util.Dateような実際の日時オブジェクトではないことに注意してください。むしろ、「エポック」(または UTC) として知られる標準ベース時刻からのミリ秒数を表します。のオブジェクトを出力すると、そのメソッドは、このミリ秒値から計算された JVM のタイムゾーンで日時を返します。異なるタイムゾーンで日時を出力する必要がある場合は、タイムゾーンを設定して、フォーマットされた文字列を取得する必要があります。January 1, 1970, 00:00:00 GMTjava.util.DatetoStringSimpleDateFormat

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
System.out.println(sdf.format(date)); // 2012-05-31T22:00:00.000Z

日付部分を取得する方法:

すでに説明したように、タイムゾーンに依存するビジネス ロジックは危険です。ただし、単純な関数呼び出しの問題です。

LocalDate localDate = odt.toLocalDate(); // 2012-06-01

最新の日時 API *の詳細についてjava.timeは、Trail: Date Timeを参照してください。


* 何らかの理由で、Java 6 または Java 7 に固執する必要がある場合は、 java.time機能のほとんどを Java 6 & 7 にバックポートするThreeTen-Backportを使用できます。Androidプロジェクトと Android API で作業している場合レベルはまだ Java-8 に準拠していません。desugarで利用できる Java 8+ APIと Android プロジェクトで ThreeTenABP を使用する方法 を確認してください。

于 2021-05-21T14:32:21.480 に答える
0

ユーザーの日付とタイムゾーンは別物です。1 つは日付、もう 1 つはプリファレンスまたはプレゼンテーション パラメータです。

それらを同じフィールドに保管しようとしないでください。

日付は UTC 日付であることが指定されているという理由だけで long に格納できるため、それらを効率的に (精度を失うことなく) 一緒に格納することさえできないと考えてください。

タイム ゾーンをオフセットとして保存できます(非常にまれなケースであるため、このオフセット ( [hh]:[mm]) に分を保持することが頻繁に推奨されます)。

于 2012-06-25T15:25:03.833 に答える
0

I think I found a solution. (If you know a better solution, just let me know)

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

DateTime dateTimeWithTimeZone = new DateTime(DateTimeZone.forID("Europe/Vienna")).withDate(2012, 06, 01).withTime(0, 0, 0, 0);      
Date dateWithTimeZoneIncluded = dateTimeWithTimeZone.toLocalDate().toDate();

System.out.println(dateFormat.format(dateWithTimeZoneIncluded));

The result is 2012-06-01 as expected.

于 2012-06-25T19:58:22.340 に答える