[英]Difference between two dates, in days, varies
Date d = new Date(today.getTimeInMillis());
Date d1 = new Date(dueDate.getTimeInMillis());
int daysUntil = (int) ((d1.getTime() - d.getTime())/ (1000 * 60 * 60 * 24));
Using the above code, where today
is a calendar set to 00:00 on the current day, and dueDate
is set to 00:00 on the date I am comparing today to, my results from this differ. 使用上面的代码,
today
的日历设置为当天00:00,而dueDate
设置为我今天比较的日期00:00,我的结果不同。
There is something in this which varies, making my output either x or x+1 where x is the correct answer. 这有些变化,使我的输出x或x + 1,其中x是正确的答案。
What is the issue here, and what can I do to make it more stable? 这里有什么问题,我该怎么做才能让它更稳定?
You do not provide actual values, so we cannot determine precisely the problem. 您没有提供实际值,因此我们无法准确确定问题。 We do not know what the
today
and dueDate
variables are. 我们不知道
today
和dueDate
变量是什么。
The question is now outmoded, as the troublesome old date-time classes including java.util.Date/.Calendar have been supplanted by the new java.time framework. 现在这个问题已经过时了,因为新的java.time框架已经取代了麻烦的旧日期时间类,包括java.util.Date/.Calendar。 See Tutorial .
请参阅教程 。 Defined by JSR 310 , inspired by Joda-Time , and extended by the ThreeTen-Extra project.
由JSR 310定义,灵感来自Joda-Time ,并由ThreeTen-Extra项目扩展。
In java.time: 在java.time中:
Instant
is a moment on the timeline in UTC. Instant
是UTC时间轴上的一个时刻。 ZoneId
represents a time zone. ZoneId
表示时区。 Use proper time zone names, never the 3-4 letter codes like "EST" or "IST" as they are neither standardized nor unique. ZonedDateTime
= Instant + ZoneId. ZonedDateTime
= Instant + ZoneId。 Unfortunately, java.time does not include a facility for calculating days elapsed between date-time values. 遗憾的是,java.time不包含用于计算日期时间值之间经过的天数的工具。 We can use the ThreeTen-Extra project and its
Days
class with between
method to provide that calculation. 我们可以使用ThreeTen-Extra项目及其
Days
类与方法between
来提供该计算。 The ThreeTen-Extra project is a collection of features deemed non-essential for java.time during the JSR process. 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 ();
Dump to console. 转储到控制台。
System.out.println ( "From then: " + then + " to due: " + due + " = days: " + days );
From then: 2015-10-31T16:01:13.082-04:00[America/Montreal] to due: 2015-11-07T16:01:13.082-05:00[America/Montreal] = days: 7
从那时起:2015-10-31T16:01:13.082-04:00 [美国/蒙特利尔]到期日期:2015-11-07T16:01:13.082-05:00 [美国/蒙特利尔] =天数:7
For Android or older versions of Java, use the excellent Joda-Time library. 对于Android或旧版本的Java,请使用优秀的Joda-Time库。
The Days
class is smart and handles anomalies such as Daylight Saving Time (DST). Days
类很聪明,可以处理夏令时 (DST)等异常情况。
Note that unlike java.util.Date, a Joda-Time DateTime
object knows its own time zone. 请注意,与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 );
Dump to console… 转储到控制台......
System.out.println( days.getDays() + " days between " + startOfToday + " and " + startOfAnotherDay + "." );
When run… 跑的时候......
3 days between 2014-01-21T00:00:00.000-06:00 and 2014-01-24T00:00:00.000-06:00.
There are mainly two reasons why your code is broken: 您的代码被破坏主要有两个原因:
I demonstrate and explain the second reason. 我演示并解释了第二个原因。
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)
The code was run in timezone "Europe/Berlin". 该代码在时区“Europe / Berlin”中运行。 Due to the change from winter time to summer time causing a jump of clocks by one hour forward on 2016-03-27 at 2 am, there is one hour missing.
由于冬季到夏季时间的变化导致2016-03-27凌晨2点时钟前进一小时,所以有一个小时失踪。 One day has only 23 hours so the division by 24 yields zero resulting in counting one day less.
一天只有23个小时,所以除以24得到零,导致计算一天减少。
What can you do else? 你还能做什么?
Your workaround adding 1000 milliseconds to dueDate
sounds as if you have overlooked possible millisecond deltas in your input. 您的解决方法将1000毫秒添加到
dueDate
听起来就好像您忽略了输入中可能的毫秒级别。 This might solve a special case but will usually not be sufficient to solve the daylight saving problem, too. 这可能会解决一个特殊情况,但通常也不足以解决夏令时问题。 Whatever you choose on base of
java.util.Date
it is a more or less an evil hack. 无论你在
java.util.Date
基础上选择什么,它或多或少是一个邪恶的黑客。
The best I have in mind (within the scope of Android-built-in stuff) is to construct an instance of java.util.GregorianCalendar
and to add successively one day after one until you have passed the due-date, and then count how many days you have added . 我想到的最好(在Android内置的东西范围内)是构造一个
java.util.GregorianCalendar
的实例,并在一天之后连续添加,直到你通过截止日期,然后计算如何很多天你都添加了 。 Not elegant and errorprone because varying millisecond parts can easily be overlooked here, too. 不优雅和错误,因为这里也可以轻易忽略不同的毫秒部分。
Otherwise you can try various external libraries for this task. 否则,您可以尝试各种外部库来完成此任务。 There are four available on Android which can calculate elapsed days in an easy way.
Android上有四种可以轻松计算经过的天数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.