2010年10月2日Java日历/日期中的错误?

时间:2010-12-17 06:19:02

标签: java date

我不确定我做错了什么,但我有一段代码可以计算两个日期之间的天数,看起来如下:

final Calendar first = new GregorianCalendar(2010, Calendar.OCTOBER, 1);
final Calendar last = new GregorianCalendar(2010, Calendar.NOVEMBER, 1);

final long difference = last.getTimeInMillis() - first.getTimeInMillis();
final long days = difference / (1000 * 60 * 60 * 24);

System.out.println("difference: " + difference);
System.out.println("days: " + days);

总结一下,上面的代码块计算了2010年10月1日到2010年11月1日之间的天数。我希望看到它返回31天(看到10月份的31天)

difference: xxxx
days: 31

但相反它在十月份显示了30天!

difference: 2674800000
days: 30

我已经设法将其缩小到2010年10月2日和2010年10月3日之间,这似乎只有82800000毫秒,而不是完整的86400000毫秒(恰好缺少一个小时)。

有没有人有任何想法我做错了什么?或者10月2日是一个比常规日少一分钟的特殊日期?

5 个答案:

答案 0 :(得分:10)

(86400000 - 82800000)/1000 = 3600,这是一个小时。您将看到夏令时,再加上整数数学的舍入

您可以通过使用浮点数进行计算并在最后进行舍入来绕过它,或者您可以查看像Joda time这样的库,它提供了比内置数据更好的日期数学。

答案 1 :(得分:0)

您可能最好比较一年,一天或一年,而不是一天中经过的毫秒数。

 int lastYear= last.get(Calendar.YEAR);
 int firstYear= first.get(Calendar.YEAR);
 int lastDayofYear = last.get(Calendar.DAY_OF_YEAR);
 int firstDayofYear = first.get(Calendar.DAY_OF_YEAR);
 int nDaysElapse = lastDayofYear - firstDayofYear;
 int nYearsElapse = lastYear- firstYear;
 int days = (nYearsElapse*365)+nDaysElapse;

答案 2 :(得分:0)

您应该阅读this post以更好地了解日历与日期/时间戳的相互关系。

阅读该网站后,我最初的问题是:

你的日子是什么意思?你的意思是'24小时块'或者你的意思是日历日?同样,你是否因为夏令时等问题而关心?

如果您的意思是日历日,那么最好的选择可能是:

final Calendar first = new GregorianCalendar(2010, 9, 1);
final Calendar last = new GregorianCalendar(2010, 10, 1);

Calendar difference = Calendar.getInstance();
difference.setTimeInMillis(last.getTimeInMillis() - first.getTimeInMillis());

int numDays = difference.get(Calendar.DAY_OF_YEAR) - difference.getMinimum(Calendar.DAY_OF_YEAR);

当然,上述代码仅在天数< 365.您需要创建滚动计算,例如

int yearDiff = last.get(Calendar.YEAR) - first.get(Calendar.YEAR);
Calendar tmp = new GregorianCalendar();
tmp.setTimeInMillis(first.getTimeInMillis());
for(int i = 0; i < yearDiff; i++) {
  numDays += tmp.getActualMaximum(Calendar.DAY_OF_YEAR);
  i++;
  tmp.add(Calendar.YEAR, 1);
}

这应该允许您以正确和一致的方式获得天数,而不必担心夏令时,闰年等。

也就是说,JodaTime可能内置了这个功能。

答案 3 :(得分:0)

answer by Brad Mace是正确的。

使用库

这个问题是一个很好的例子,说明为什么你应该使用一个好的日期时间库,而不是自己动手。对于Java,这意味着在Java 8中使用Joda-Time或新的java.time包。

约达时间

Joda-Time中的示例代码。

DateTimeZone timeZone = DateTimeZone.forID( "Australia/Melbourne" );
DateTime theFirst = new DateTime( 2014, DateTimeConstants.OCTOBER, 1, 0, 0, 0, timeZone ).withTimeAtStartOfDay();
DateTime nextMonth = theFirst.plusMonths( 1 ).withTimeAtStartOfDay();
int days = Days.daysBetween( theFirst, nextMonth ).getDays();

如果您不关心时间,请使用LocalDate课程。

java.time

Java 8及更高版本附带了一个新的java.time框架来取代旧的java.util.Date/.Calendar类。灵感来自Joda-Time,由JSR 310定义,并由ThreeTen-Extra项目扩展。

使用Java 8的示例代码。请注意,枚举ChronoUnit返回64位long而不是int

LocalDate firstOfOctober = LocalDate.of( 2010 , java.time.Month.OCTOBER , 1 );
LocalDate nextMonth = firstOfOctober.plusMonths( 1 );
long daysInMonth  = ChronoUnit.DAYS.between( firstOfOctober , nextMonth );

答案 4 :(得分:-3)

您在帖子中输入的代码是计算9月1日到10月1日之间的时间,而不是10月1日和11月1日。您输出的代码输出正确。