5

これに対する答えを探しましたが、見つからないようです。次のコードで毎月1が表示されないのに、数か月間31にジャンプする理由を誰かが説明できますか?翌月の日付を決定する必要があるレポートイベント用です。

DateFormat formatter = new SimpleDateFormat("dd-MMM-yy"); 
Calendar cal = Calendar.getInstance( TimeZone
    .getTimeZone( "America/Los_Angeles" ) );
DateFormat formatter = new SimpleDateFormat("dd-MMM-yy"); 
Date date;
try
{
  date = (Date)formatter.parse("01-JUN-12");
  cal.setTime(date);
  //cal.set(2012, 05, 01);

  long now = new Date().getTime();
  int frequency = 1;

  System.out.println("Current calendar time=" + cal.getTime().toString()) ;

  while (cal.getTime().getTime() < now)
  {
      cal.add( Calendar.MONTH, frequency );
      System.out.println("In loop - current calendar time=" + cal.getTime().toString()) ;
  }
}
catch (ParseException e)
{
  // TODO Auto-generated catch block
  e.printStackTrace();
} 

出力は次のとおりです。

Current calendar time=Fri Jun 01 00:00:00 EDT 2012

In loop - current calendar time=Sun Jul 01 00:00:00 EDT 2012

In loop - current calendar time=Tue Jul 31 00:00:00 EDT 2012

In loop - current calendar time=Fri Aug 31 00:00:00 EDT 2012

In loop - current calendar time=Mon Oct 01 00:00:00 EDT 2012

In loop - current calendar time=Wed Oct 31 00:00:00 EDT 2012

31にジャンプしてから1に戻ることに注意してください。代わりにCalendar.set()を使用すると、出力は正しくなります。

Current calendar time=Fri Jun 01 15:14:26 EDT 2012

In loop - current calendar time=Sun Jul 01 15:14:26 EDT 2012

In loop - current calendar time=Wed Aug 01 15:14:26 EDT 2012

In loop - current calendar time=Sat Sep 01 15:14:26 EDT 2012

In loop - current calendar time=Mon Oct 01 15:14:26 EDT 2012

In loop - current calendar time=Thu Nov 01 15:14:26 EDT 2012

これは、1)Calendar APIのバグ、または2)CalendarAPIの動作についての理解の欠如のいずれかであるように思われます。どちらの場合も、もちろん特定の月と日に問題がない限り、私は翌月(同じ日)が欲しいだけです。しかし、上記のシナリオは私を困惑させています。これは、その月の他の日では発生せず、1日のみで発生します。

4

4 に答える 4

3

タイムゾーンの問題です。Calendar と Formatter の両方が同じタイムゾーンを使用するように、既存の設定行を次のように置き換えます。

    TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
    formatter.setTimeZone(tz);
    Calendar cal = Calendar.getInstance(tz);

そしてそれはすべてうまくいきます:

Current calendar time=Fri Jun 01 08:00:00 BST 2012
In loop - current calendar time=Sun Jul 01 08:00:00 BST 2012
In loop - current calendar time=Wed Aug 01 08:00:00 BST 2012
In loop - current calendar time=Sat Sep 01 08:00:00 BST 2012
In loop - current calendar time=Mon Oct 01 08:00:00 BST 2012
In loop - current calendar time=Thu Nov 01 07:00:00 GMT 2012

toString()出力が適切なタイムゾーンになるように、呼び出しを呼び出しに置き換えることもformatter.format()できます (EDT にいる場合は問題ないように見えるかもしれませんが、ご覧のとおり、私は英国のタイムゾーンにいます)。

于 2012-10-23T19:35:54.713 に答える
3

の代わりにcal.add( Calendar.MONTH, frequency );、これを試してください:

cal.add(Calendar.MONTH, frequency);
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
于 2012-10-23T19:28:01.690 に答える
2

システムのデフォルトのタイムゾーンで時刻を印刷しています。フォーマッタを使用して表示します。

フォーマッタに同じタイム ゾーンを設定します。

DateFormat formatter = new SimpleDateFormat("dd-MMM-yy");
formatter.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));

そしてそれを使って時間を表示します:

while (cal.getTime().getTime() < now) { 
    cal.add(Calendar.MONTH, frequency);
    System.out.println("In loop - current calendar time=" + formatter.format(cal.getTime()));
}
于 2012-10-23T19:38:44.073 に答える
0

Javadocカレンダーから

add(f, delta) は、delta をフィールド f に追加します。これは、set(f, get(f) + delta) を 2 つの調整で呼び出すのと同じです。

  • ルール 1 を追加します。呼び出し後のフィールド f の値から呼び出し前のフィールド f の値を差し引いた値が、フィールド f で発生したオーバーフローを法としてデルタになります。フィールド値がその範囲を超えるとオーバーフローが発生し、その結果、次に大きいフィールドが増分または減分され、フィールド値がその範囲に戻されます。

  • ルール 2 を追加します。より小さいフィールドが不変であると予想されるが、フィールド f が変更された後の最小値または最大値の変更、またはタイム ゾーン オフセットの変更などのその他の制約のために、以前の値と等しくなることが不可能な場合。の場合、その値は期待値にできるだけ近くなるように調整されます。フィールドが小さいほど、時間の単位が小さくなります。HOUR は、DAY_OF_MONTH よりも小さいフィールドです。不変であると予想されない小さなフィールドは調整されません。暦法は、どのフィールドが不変であると予想されるかを決定します。

さらに、set() とは異なり、add() はカレンダーのミリ秒とすべてのフィールドの即時再計算を強制します。

例: 最初に 1999 年 8 月 31 日に設定された GregorianCalendar を考えてみましょう。翌年。GregorianCalendar では DAY_OF_MONTH を 9 月の 31 にすることはできないため、ルール 2 を追加して DAY_OF_MONTH を最も近い値である 30 に設定します。小さいフィールドですが、DAY_OF_WEEK は規則 2 によって調整されません。これは、GregorianCalendar で月が変わると変更されることが予想されるためです。

したがって、カレンダー API が月を追加する場合に設定した時間を考慮するとJul、1 か月以上オーバーフローしている可能性があるため、Jul真夜中に調整されます。

于 2012-10-23T19:42:43.470 に答える