2016-12-13 12 views
-1

私は本当に日付について非常に混乱しています。Java日付の混乱

私はJava上でバックエンドを持つWebアプリケーションを持っています。私は時間情報がない日付フィールドを持っています。私は冬眠を使ってこの情報をDBに書きます。定義は

@Column 
@Temporal(TemporalType.DATE) 
private Date startDate; 

実際にはこれらは基本的な情報です。ここに私の問題があります。

UTC(GMT+0)タイムゾーンでJavaを実行しますが、クライアントのタイムゾーンはGMT+3です。

ユーザが1日を選択します(としましょう、10.12.2016 (dd.MM.yyyy))。今日のクライアント側では10.12.2016 00:00 GMT+3と表されます。このユーザーがこの日付を保存した後。

この日付は私のバックエンドに09.12.2016 21:00 GMT+0となります。私はtimeinfoなしでこの日付を保存したい。 javaコードはデータを09.12.2016として保存します。

今、ユーザーは自分が保存したものをS /見たい(その09.12.2016 00:00 GMT+0に対応)。 Javaは日付を09.12.2016 00:00 GMT+0とし、クライアントはこの日付を09.12.2016 03:00 GMT+3とします。最後に、ユーザーは09.12.2016と表示されますが、この日付は10.12.2016と保存されています。

したがって、ユーザーは実際に保存する日の前日を確認します。

データをTemporalType.DATEとして保存し、正しい日付を表示したいと考えています。

どうすればこの問題を解決できますか? Googleで2日間掘り起こしていますが、合理的な説明が見つかりませんでした。

注::**私のユーザーは、GMT+3だけでなく、異なるタイムゾーンでもかまいません。このような状況を考えてください。

+2

タイムスタンプを使用し、実際のデータベースにUTC時刻を格納する必要があります。これは、日の境界線を正しく取得する唯一の方法です。実際、多くのデータベースはタイムゾーン情報を格納していません。 –

+0

これは論理的だと思われますが、GMT + 2のユーザーを考えてみましょう。このユーザーは09.10.2016と日付を表示します(日付は09.10.2016 23:00となるため)。これは通常のケースですか、いくつかの取り決めをする必要がありますか:/ – xxlali

+0

時間帯なしでタイムゾーンが適切ですか?日付は何を表していますか?あなたのユーザは、日付を入力し、時間を切り捨てることで効果的に別の時間に変更します。 1つのタイムゾーンで日付を入力した後、別のタイムゾーンに移動する場合は、少なくともクライアントは現在のタイムゾーンを送信する必要があります。その後、GMTのタイムゾーンを、要求に応じてクライアントのタイムゾーンに変換します。 – ProgrammersBlock

答えて

0

あなたのアプリケーションがクライアントのGMTを認識している場合は、GMTの要求をリクエストしているので、この点について詳しく説明しません。

Date databaseDate = database's date (you said you were working in GMT and it was also stored in GMT 0 so no further transformation is required) 

//As you said you are working in GMT 0 this will be the GMT of your calendar. 
Calendar calendar = new GregorianCalendar(); 

//As you know your GMT you only have to set it through this method 
TimeZone clientTimezone = TimeZone.getTimeZone("GMT-1:00"); 

Date originalDate = inputCalendar.getTime(); 
calendar.setTimeZone(clientTimezone); 

//This will return you the offset -positive or negative- of calendars time zone respect to UTC 0 - GMT 0 - in milliseconds 
int offset = inputCalendar.getTimeZone().getOffset(originalDate.getTime()); 

//You get the database's date in milliseconds and add your offset to it. It can be positive or negative and the final result will the date transformed to your request's GMT 
Date clientDate= (new Date(originalDate.getTime() + offset)); 

をそして、それはあなたの要件については十分だろう:あなたは、要求のGMT情報を持っていたら

、あなただけのこの操作を行う必要があります。

0

いくつかのオプションがあります。

  1. は、Java 8で作業している(またはJava 8に切り替えることができます)場合は、新しい パッケージjava.timeはあなたが必要なものを正確にあなたを与えるだろうはるかに柔軟日付モデルとクラス LocalDateを提供します。
  2. Java 7以下で作業する場合は、 の日付を文字列フィールドとしてDBに保存するようにしてください。私。あなたの日付を文字列にフォーマットして、それを のようにvarcharフィールドにDBに保存します。あなたがそれを読むと、 の日付に戻って解析するだけです。このようにして、あなたの「10.12.2016」は、どんな追加のトリックもなく、いずれの タイムゾーンにもそのまま残ります。
  3. 最後に、日付として保存することを強く求めている場合は、 の実際の場所に関係なく、すべての日付が常にGMT + 0に格納されるようにすることをお勧めします。同じ場所にいるこの方法では、常に同じ日付の が表示されます。しかし、異なる場所にいる2人のユーザーがまだ私がもし可能でなければ、その後の2D第一オプションをsugjestう異なる日付

と 同じフィールドが表示される場合があります。 3つ目は、あなたのアプリが別の時間帯のユーザーによって使用されている場合、ますます複雑になります。

また、あなたが面白いこの記事を見つけるかもしれない:それは日に未知の形式の文字列を変換についてです:Parsing any string to Date

0

あなたの日付と時間の問題に関するいくつかの一般的な情報、特定...

何時間帯を休止状態ではありませんあなたのサーバの現在のデフォルトは無関係であるべきです。常にオプションのタイムゾーン引数を渡して、コード内に希望の/予想されるタイムゾーンを指定してください。 Stack Overflowで何度も議論されたので、より多くの情報を検索してください。

LocalDate todayMontreal = LocalDate.now(ZoneId.of("America/Montreal")) ; 

タイムゾーンのない日付のみの値は実際には不正確です。任意の瞬間について、日付はゾーンごとに世界中で異なります。フランスの深夜から数分後、フランスは新しい一日ですが、モントリオールのカナダではまだ「昨日」です。 Stack Overflowで何度も議論されたので、より多くの情報を検索してください。

精度が必要な場合は、タイムゾーン付きの日時を使用します。 Stack Overflowで何度も議論されたので、より多くの情報を検索してください。

ZonedDateTime todayMontrealStart = todayMontreal.atStartOfDay(ZoneId.of("America/Montreal")) ; 

...か...

ZonedDateTime todayMontrealStart = ZonedDateTime.now(ZoneId.of("America/Montreal")); 

データを格納するために、その時間帯UTCを作ります。 Instantクラスは、デフォルトでは常にUTCです。

Instant instant = todayMontrealStart.toInstant(); 

あなたのJDBCドライバおよび/またはデータベースがこれを行う場合があります。 JDBC 4.2以降では、getObjectsetObjectでjava.timeオブジェクトを渡します。それ以外の場合は、java.sql型に戻ってデータベースとのデータ交換を行います。 Stack Overflowで何度も議論されたので、より多くの情報を検索してください。

java.util.Date.Calendarのような面倒な古い日時クラスは避けてください。今や、レガシーはjava.timeクラスに取って代わられています。 Stack Overflowで何度も議論されたので、より多くの情報を検索してください。

特に、LocalDate、Instant、OffsetDateTime、およびZonedDateTimeクラスのStack Overflowを検索する必要があります。

ボーナスのヒント:クライアントとサーバーの間などのテキストとして日付/時刻の値を交換する場合は、ISO 8601標準形式を使用します。 Stack Overflowで何度も議論されたので、より多くの情報を検索してください。