2017-06-20 10 views
2

を返す:Calendar.get(Calendar.DAY_OF_MONTH)私は次のコードを実行すると、間違った日

int year = 2017; 
int month = 7; 
int dayOfMonth = 10; 

Calendar dateOfBirth = new GregorianCalendar(year, month, dayOfMonth); 
dateOfBirth.getTime(); // See http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4827490 
dateOfBirth.setTimeZone(TimeZone.getTimeZone("UTC")); 

System.out.println("Original Day Of Month:\t\t" + dayOfMonth); 
System.out.println("Calendar:\t\t\t" + dateOfBirth); 
System.out.println("Calendar substring:\t\t" + dateOfBirth.toString().substring(dateOfBirth.toString().indexOf("DAY_OF_MONTH"), dateOfBirth.toString().indexOf("DAY_OF_MONTH") + 15)); 
System.out.println("Formatted date:\t\t\t" + new SimpleDateFormat("dd").format(dateOfBirth.getTime())); 
System.out.println("get(Calendar.DAY_OF_MONTH):\t" + dateOfBirth.get(Calendar.DAY_OF_MONTH)); 

を、私はこの出力を得る:

Original Day Of Month:  10 
Calendar:     java.util.GregorianCalendar[time=1502312400000,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=?,YEAR=2017,MONTH=7,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=10,DAY_OF_YEAR=?,DAY_OF_WEEK=?,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?] 
Calendar substring:   DAY_OF_MONTH=10 
Formatted date:    10 
get(Calendar.DAY_OF_MONTH): 9 

あなたが見ることができるように、値がdateOfBirth.get(Calendar.DAY_OF_MONTH)で返されます間違っています。

生年月日であるため、私はUTCを使用しています。特定のタイムゾーンに依存しないようにしたいと思います。それを正しく行うために、私はdateOfBirth.getTime()に電話をする必要があります - http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4827490を参照してください。 私はその電話を取る場合、これは正しく動作しますが、私は他のバグに遭遇します。

月の正しい日を正確に取得するために何ができるのですか?

私はJava v1.7.0_79を使用しています。重要な場合は、現在GMT + 3です。

+0

10日目に9日を出力したいので、0日目は単に1日目を意味すると思います。日付出力をdd-MM-yyyyにフォーマットすると、カレンダーのjavadocには、月がインデックス0で始まるので、10-08-2017 最後に、数字が1で始まり0でない人間の慣習に戻るためには、1を加えなければならないことを覚えておいてください。 – Webster

+1

@Websterインデックス0から始まっていません。それは1から始まります。 –

+2

あなたはJava 7を使用していて、まさに今すぐJava 8にアップグレードするつもりはないと思います。それでも、あなたのプログラムが日付やタイムゾーンの作業をしているなら、[ThreeTen Backport](http://www.threeten.org/threetenbp/)を入手して最新のクラスを使い始めることを真剣に検討してください。 'LocalDate'では日付が何であるかを知っています。また、一般的に、現代のクラスは、このような多くの驚きを伴って動作するように非常に良いです。そして最終的にはあなたのJavaバージョンをアップグレードすれば、これらのクラスはJava 8以降に組み込まれているので、あなたは準備が整っています。 –

答えて

3

グラッドthe answer by Robby Cornelissenことは、あなたの問題を解決しました。私は何が起こったのか、なぜその答えが助けられたのかを説明したいと思います。

あなたは、三引数GregorianCalendarコンストラクタを使用している、それは「指定した日付とGregorianCalendarデフォルトロケールでデフォルトタイムゾーンにを設定して構築します。」ドキュメントを引用します。斜体は私のものです。あなたの場合、これはGMT + 3です(今のところ重要なことは、GMT なので8月です)。

ドキュメントの内容はあまり明確ではないため、時刻は0に設定されているため、2017年8月10日0時00分の時点でゾーンオフセット+3:00になっています。あなたは本当にGregorianCalendarが時刻について心配しないことを望んでいましたが、そのようなことはありません。これは私がコメントで言及したようにLocalDateを代わりに勧めている理由の1つです。

タイムゾーンを変更すると、その時点は同じですが、自分のタイムゾーンでGMTよりも先行していたため、今度は8月9日が2017 21:00 UTCになります。だから、今は正しい9日の値です。

私は、最大の驚きはtoStringメソッドが依然としてDAY_OF_MONTH=10を生成していると思います。 GregorianCalendarはどのフィールドがわかりにくいかを計算しますが、明らかにこの時点で古い値を記憶しています。

フォーマットにはnew SimpleDateFormat("dd")を使用してください。このフォーマッタは、GMT + 3のデフォルトのタイムゾーンとカレンダオブジェクトからの特定の時刻を使用して、正しく10を生成します。カレンダから日を生成したい場合は、タイムゾーンを設定している可能性がありますUTCにも。

dateOfBirth.get(Calendar.DAY_OF_MONTH)は、正しい値9を生成します。

面白いことがあり、この呼び出しの後、私は自分のラインを繰り返す場合:

System.out.println("Calendar substring:\t\t" 
      + dateOfBirth.toString().substring(dateOfBirth.toString().indexOf("DAY_OF_MONTH"), 
        dateOfBirth.toString().indexOf("DAY_OF_MONTH") + 15)); 

それが生成する。この時間:

Calendar substring:  DAY_OF_MONTH=9, 

だからフィールドが現在計算されています。

ロビーコーネリセンのコードでは、カレンダーオブジェクトはUTCタイムゾーンで生まれているので、日付を設定すると、今度は2017年7月10日ですが、0:00 UTCに設定されます。これはあなたのタイムゾーンの3時に対応しますが、日付もそこに7月10日です。残りのコードはあなたが期待した10を生成します。ただし、グリニッジ西部のタイムゾーンのユーザーは、SimpleDateFormatがGMTより遅いタイムゾーンを使用するため、09という形式の日付が表示されるため、現在は問題が発生します。完全を期すために

ここThreeTen(バックポート)バージョンです:

LocalDate date = LocalDate.of(2017, Month.AUGUST, 10); 
    System.out.println("Day of month:\t" + date.getDayOfMonth()); 

これはLocalDateは多くのことを残して、その日の任意の時点でもどの時間帯でもないを持っている

Day of month: 10 

を出力しますが、混乱の余地が少ないCalendarとは対照的に、それは人間のやり方も月に番号をつけるので、7は7月、8は8月です。

2

ジャストタイムゾーンを設定した後、日付値を設定します。

int year = 2017; 
int month = Calendar.JULY; 
int dayOfMonth = 10; 

Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC")); 
calendar.set(year, month, dayOfMonth); 

System.out.println("DAY_OF_MONTH: " + calendar.get(Calendar.DAY_OF_MONTH)); 

は、これは正しく、月の日を出力します

DAY_OF_MONTH: 10 
+0

ありがとう!それはそうです! – rweiser

+0

スクラッチ - 私はGMTにいると問題に終わります.Ole V.V.指摘している。 ThreeTenバックポートに一撃を与えます。 – rweiser

関連する問題