Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java日历不一致的结果_Java_Date_Calendar - Fatal编程技术网

Java日历不一致的结果

Java日历不一致的结果,java,date,calendar,Java,Date,Calendar,我一直在寻找这个问题的答案,但似乎找不到答案。有人能解释一下为什么下面的代码没有给我每个月的1,而是在几个月内跳到31吗?它适用于需要确定下个月日期的报告事件 DateFormat formatter = new SimpleDateFormat("dd-MMM-yy"); Calendar cal = Calendar.getInstance( TimeZone .getTimeZone( "America/Los_Angeles" ) ); DateFormat formatter

我一直在寻找这个问题的答案,但似乎找不到答案。有人能解释一下为什么下面的代码没有给我每个月的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();
} 
注意它是如何跳到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)日历API的错误,或2)对日历API的工作方式缺乏了解。无论哪种情况,我只想要下个月(同一天),当然,除非某些月份和日期有问题。但上述情景让我感到困惑。这不会发生在一个月的其他任何一天,只发生在第一天。

而不仅仅是
cal.add(Calendar.month,frequency),请尝试以下操作:

cal.add(Calendar.MONTH, frequency);
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));

这是一个时区问题。用以下内容替换现有的设置行,以便日历和格式化程序都使用相同的时区:

    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,您可能会觉得没问题,但您可以看到,我在英国时区)。

您正在系统默认时区中打印时间。使用格式化程序来显示它

为格式化程序设置相同的时区:

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()));
}
while(cal.getTime().getTime()
来自Javadoc

添加(f,增量)将增量添加到字段f。这相当于调用set(f,get(f)+delta)并进行两次调整:

  • 添加规则1。调用后字段f的值减去 调用前的字段f是delta,对已发生的任何溢出进行模化 发生在字段f中。当字段值超过其值时发生溢出 范围,因此,下一个较大的字段将递增或 递减,并将字段值调整回其范围

  • 添加规则2。如果一个较小的字段预期是不变的,但它是不变的 由于变化,它不可能等于其先前的值 字段f更改或其他更改后的最小值或最大值 约束,例如时区偏移更改,则其值为 调整为尽可能接近其预期值。较小的 字段表示较小的时间单位。小时比时间小 月日。未对较小的字段进行调整 期望是不变的。日历系统确定哪些字段 期望是不变的

此外,与set()不同,add()强制立即重新计算日历的毫秒数和所有字段

例如:考虑GregorianCalendar最初设定为1999年8月31日。调用add(Calendar.MONTH,13)将日历设置为2000年9月30日。添加规则1将月份字段设置为9月,因为将13个月添加到8月会得到下一年的9月。由于公历月份中的日期不能是9月31日,因此添加规则2会将月份中的日期设置为30,这是最接近的可能值。虽然它是一个较小的字段,但“周中的天”不受规则2的调整,因为当月份在GregoriaCalendar中发生变化时,它会发生变化


因此,在您的情况下,考虑到您已设置的时间,如果calendar API将month添加到
Jul
,则可能溢出超过一个月,因此将其调整回
Jul
Midnight

更改joda时间的日期和时间库,在这个库中,您没有发现任何错误幸运的是,我必须使用日历API,因此切换不是这个项目的选项。
Calendar
可以说是JDK中最坏的类:它实际上是不可用的。从内部看,它似乎是由一个(糟糕的)初级程序员编写的。利用乔达的时间。就这么简单。你应该告诉谁让你使用
Calendar
,他们应该尝试在与编程无关的领域工作。这样可以提供更一致的结果,但是,它现在显示每个月的第二天:当前日历时间=周五六月01日00:00:00 EDT 2012循环中-当前日历时间=周六六月02日00:00:00 EDT 2012循环中-当前日历时间=周一七月02日00:00:00 EDT 2012循环中-当前日历时间=周四八月02日00:00:00 EDT 2012循环中-当前日历时间=周日九月02日00:00:00 EDT 2012循环中-当前日历时间=2012年10月2日星期二00:00:00东部夏令时循环-当前日历时间=2012年11月2日星期五00:00:00东部夏令时在这一点上,我想这与时区有关。太好了,这成功了!忘了我们从一家初创公司获得了这个软件,而他们位于加利福尼亚州!谢谢我应该意识到这很简单!
while (cal.getTime().getTime() < now) { 
    cal.add(Calendar.MONTH, frequency);
    System.out.println("In loop - current calendar time=" + formatter.format(cal.getTime()));
}