两个日期之间的天数(不包括这两个日期)

时间:2013-10-11 11:28:09

标签: java android

我搜索到这是因为有这么多帖子提出这个问题,但所有答案都是difference In Milliseconds / (24* 1000 * 60 * 60),它给出了两个日期之间的24小时数。 但我需要两个日期之间的天数。

即。如果date109/09/13 09:00date210/09/13 22:00,则我需要0而不是1,因为date1和{{ 1}}是连续的天数(即使它们之间的间隔超过24小时)。

注意:我知道删除时间部分并使用date2方法。我正在寻找更好的解决方案。

更新:应用程序首次在difference In Milliseconds / (24* 1000 * 60 * 60)星期三使用,然后该应用程序于星期四10/09/13 22:00使用。现在用户已经在周三和周四使用了应用程序,即使有超过24小时的差距。现在,如果我计算两个日期之间的24小时数,则给出一个。因为2个日期之间有一天的差距。我需要它给零,因为用户使用它周三和周四星期三和星期四之间没有天。 希望你理解我的问题。如果你还没有离开它,我试着通过最好的解释。

5 个答案:

答案 0 :(得分:1)

这是一个简单的解决方案:

Calendar calendar = Calendar.getInstance();
calendar.setTime(startDate);

while(calendar.getTime().before(endDate))
 {
    noOfDays++;
    calendar.add(Calendar.DAY_OF_MONTH,1);
 }

其中startDate和endDate是Date类的实例。

注意:您需要初始化日期对象,以便它们具有相同的时间但只是日期不同。将它们设置为上午12点应该可以解决问题:

date.set(Calendar.HOUR_OF_DAY, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);

答案 1 :(得分:1)

import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.text.SimpleDateFormat;
import java.text.ParseException;

public class test {

    public static void main(String[] args) throws ParseException {

        String dateStart = "09/09/13 09:00";
        String dateStop = "10/09/13 22:00";

        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm");

        Date date1 = format.parse(dateStart);
        Date date2 = format.parse(dateStop);

            // calculate difference in milliseconds
        long diff = (date2.getTime() - date1.getTime()) - 86400000;
        diff = (diff <= 0 ? 0 : diff);

        System.out.println(TimeUnit.MILLISECONDS.toDays(diff));
    }

}

这将给出2个日期之间的差异。并减去一天(如果它是负数,它将差异设置为0天)。只要dateStop大于dateStart,这将起作用,否则它只会打印0;

答案 2 :(得分:1)

我已经避免使用Joda Time多年了,但是在过去的一周里,我完全使用它来解决这个问题。这非常值得!

在处理普通Java时,很容易引入一些奇怪的日期处理错误 - 例如夏令时变化时会发生什么。 Joda Time已经构建了所有这些例外。

点击此处查看相关问题:


<强>更新

从Java 8开始,时间&amp;日期功能已经改进,Joda Time团队建议使用它而不是他们的库。以下是他们在着陆页上所说的内容:

  

请注意,从Java SE 8开始,系统会要求用户迁移到   java.time(JSR-310) - JDK的核心部分,取代了它   项目

Thanks to Basil Bourque for the comment.

答案 3 :(得分:0)

您可以使用此技巧:如果date1date2之前,您可以将date1中的小时设置为1,将date2设置为0 }。这样,整个时差的小时部分永远不会超过24小时,因此不会影响计算,因此只有几天/几个月/几年才会起作用。

这是代码示例

public static long daysBetween(Date date1, Date date2) {
    Calendar c1 = Calendar.getInstance();
    c1.setTime(date1);

    Calendar c2 = Calendar.getInstance();
    c2.setTime(date2);
    if (date1.before(date2)) {
        c1.set(Calendar.HOUR_OF_DAY, 1);
        c2.set(Calendar.HOUR_OF_DAY, 0);
    } else {
        c2.set(Calendar.HOUR_OF_DAY, 1);
        c1.set(Calendar.HOUR_OF_DAY, 0);
    }

    return (c2.getTimeInMillis() - c1.getTimeInMillis())
            / (24 * 60 * 60 * 1000);
}

//DEMO
public static void main(String[] args) throws Exception {
    DateFormat df = new SimpleDateFormat("dd/MM/yy hh:mm");
    Date date1 = df.parse("09/09/13 09:00");
    Date date2 = df.parse("11/09/13 22:00");

    System.out.println(daysBetween(date1, date2));
}

输出:1


对于日期11/09/13 09:00 09/09/13 22:00,结果将为-1,因为date1位于date2之后

答案 4 :(得分:0)

TL;博士

ChronoUnit.DAYS.between(
    earlierInstant.atZone( ZoneId.of( "Africa/Tunis" ) ).toLocalDate() ,
    Instant.now().atZone( ZoneId.of( "Africa/Tunis" ) ).toLocalDate()
)

java.time

现代方法使用 java.time 类来取代麻烦的旧日期时间类,例如Date&amp; Calendar

如果要计算经过的天数作为日历日期的数量而不是24小时的时间段数,请使用仅限日期的类而不是日期时间类。

LocalDate类表示没有时间且没有时区的仅限日期的值。

时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因地区而异。例如,在Paris France午夜后的几分钟是新的一天,而Montréal Québec中仍然是“昨天”。

如果未指定时区,则JVM会隐式应用其当前的默认时区。该默认值可能随时更改,因此您的结果可能会有所不同。最好明确指定您期望/预期的时区作为参数。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;  

通常最好以UTC思考,工作,记录,序列化和交换值。为此,请使用InstantInstant类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。

Instant earlier = Instant.now() ;
…
Instant later = Instant.now() ;

通过调用Instant::toStringInstant::parse,以标准ISO 8601格式序列化为文本。

要获取您过去的日期,请应用时区(ZoneId)来获取ZonedDateTime个对象。

ZonedDateTime zdtEarlier = earlier.atZone( z ) ;
ZonedDateTime zdtLater = later.atZone( z ) ;

提取仅限日期的值。

LocalDate ldEarlier = zdtEarlier.toLocalDate() ;
LocalDate ldLater = zdtLater.toLocalDate() ;

现在我们可以获得日期之间经过的天数。

long daysElapsed = ChronoUnit.DAYS.between( ldEarlier , ldLater ) ;

此计算是根据半开放方法完成的,其中开头是包含,而结尾是独占。因此,例如,一个月从该月的第一天开始,一直运行,但不包括 月的第一天。在整个业务逻辑,数据库查询等中始终如一地使用此方法将使您的代码库不易出错,并且更易于读取/调试/维护。

我知道您希望使用完全开放的方法,其中开头和结尾都是独占的。我强烈建议你重新考虑这个立场。但如果你坚持,只需从上面的计算中减去1

long daysElapsedFullyOpen = ( ChronoUnit.DAYS.between( ldEarlier , ldLater ) - 1 ) ;  // Subtract 1 to get a fully-Open answer. NOT recommended.

顺便说一下,您可能需要考虑工作中的Period课程。同样,您可能会发现ThreeTen-Extra项目中的LocalDateRange类很有用。

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和&amp; SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore