两个日期之间的差异,以天为单位,各不相同

时间:2014-01-22 01:57:52

标签: java android date time calendar

Date d = new Date(today.getTimeInMillis());
Date d1 = new Date(dueDate.getTimeInMillis());

int daysUntil = (int) ((d1.getTime() - d.getTime())/ (1000 * 60 * 60 * 24));

使用上面的代码,其中today是当天设置为00:00的日历,dueDate在我今天比较的日期设置为00:00,我的结果从这个不同。

这里有一些变化,使我的输出为x或x + 1,其中x是正确的答案。

这里有什么问题,我该怎么做才能让它更稳定?

2 个答案:

答案 0 :(得分:1)

模糊问题

您没有提供实际值,因此我们无法准确确定问题。我们不知道todaydueDate变量是什么。

过时的

现在问题已经过时了,因为新的java.time框架取代了包括java.util.Date/.Calendar在内的麻烦的旧日期时间类。见Tutorial。由JSR 310定义,受Joda-Time启发,并由ThreeTen-Extra项目扩展。

在java.time中:

  • Instant是UTC时间轴上的一个时刻。
  • ZoneId表示时区。使用正确的时区名称,不要使用3-4字母代码,例如" EST"或者" IST"因为它们既不标准也不独特。
  • 从概念上讲,ZonedDateTime = Instant + ZoneId。

ThreeTen-EXTRA

不幸的是,java.time不包含用于计算日期时间值之间经过的天数的工具。我们可以使用ThreeTen-Extra项目及其Days类和between方法来提供该计算。 ThreeTen-Extra项目是JSR过程中被认为对java.time不重要的功能集合。

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
ZonedDateTime then = now.minusDays ( 4 );
ZonedDateTime due = now.plusDays ( 3 );
Integer days = org.threeten.extra.Days.between ( then , due ).getAmount ();

转储到控制台。

System.out.println ( "From then: " + then + " to due: " + due + " = days: " + days );
  

从那时起:2015-10-31T16:01:13.082-04:00 [美国/蒙特利尔]到期日期:2015-11-07T16:01:13.082-05:00 [美国/蒙特利尔] =天数:7 < / p>

约达时间

对于Android或旧版本的Java,请使用优秀的Joda-Time库。

Days类很聪明,可以处理Daylight Saving Time(DST)等异常情况。

请注意,与java.util.Date不同,Joda-Time DateTime对象知道自己的时区。

// Specify a time zone rather than rely on default.
DateTimeZone timeZone = DateTimeZone.forID( "America/Regina" ); // Or "Europe/London".

DateTime now = new DateTime( timeZone );
DateTime startOfToday = now.withTimeAtStartOfDay();

DateTime fewDaysFromNow = now.plusDays( 3 );
DateTime startOfAnotherDay = fewDaysFromNow.withTimeAtStartOfDay();

Days days = Days.daysBetween( startOfToday, startOfAnotherDay );

转储到控制台...

System.out.println( days.getDays() + " days between " + startOfToday + " and " + startOfAnotherDay + "." );

跑步时......

3 days between 2014-01-21T00:00:00.000-06:00 and 2014-01-24T00:00:00.000-06:00.

答案 1 :(得分:1)

您的代码损坏主要有两个原因:

  • 第二部分或毫秒部分(您可能忽略了)
  • 夏令时效果

我演示并解释了第二个原因。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d1 = sdf.parse("2016-03-20");
Date d2 = sdf.parse("2016-03-28");
int daysUntil = (int) ((d2.getTime() - d1.getTime()) / (1000 * 60 * 60 * 24));
System.out.println(daysUntil); // 7 (should be 8)

代码在时区&#34; Europe / Berlin&#34;中运行。由于冬季到夏季时间的变化导致2016-03-27凌晨2点时钟前进一小时,所以有一个小时失踪。一天只有23个小时,所以除以24会产生零,导致计算的时间少一天。

你还能做什么?

您的解决方法是向dueDate添加1000毫秒的声音,就像您忽略了输入中可能的毫秒级增量一样。这可能会解决一个特殊情况,但通常也不足以解决夏令时问题。无论你在java.util.Date的基础上选择什么,它或多或少都是邪恶的黑客。

我想到的最好(在Android内置的东西范围内)是构造一个java.util.GregorianCalendar的实例,并在一天之后连续添加,直到你通过了 - 日期,然后计算您添加的天数。不优雅和错误,因为这里也很容易忽视不同的毫秒部分。

否则,您可以尝试各种外部库来执行此任务。 Android上有四种可以轻松计算经过的天数。