Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.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_Datediff - Fatal编程技术网

Java日历:将两个日期/时间之间的差减一

Java日历:将两个日期/时间之间的差减一,java,date,calendar,datediff,Java,Date,Calendar,Datediff,我看到了很多关于这个话题的问题和答案,但没有一个能解决我的问题。我扩展了java Calendar类(标准——没有第三方库),需要找出两个任意日期之间天的差异 方法: 将两个日期的时间更改为午夜 将日期转换为毫秒 找出两个日期之间的差异 将结果除以一天中的毫秒数(24*60* 60*1000) 结果应该是以天为单位的差异 有时是,有时不是。即使是在同一天进行的测试也可能被取消一次。发生了什么事?您在第一步中通过将时间设置为午夜来识别问题:这确保了所有的小时、分钟和秒都为零。但你走得不够远!您还必

我看到了很多关于这个话题的问题和答案,但没有一个能解决我的问题。我扩展了java Calendar类(标准——没有第三方库),需要找出两个任意日期之间天的差异

方法:

  • 将两个日期的时间更改为午夜
  • 将日期转换为毫秒
  • 找出两个日期之间的差异
  • 将结果除以一天中的毫秒数(24*60* 60*1000)
  • 结果应该是以天为单位的差异

  • 有时是,有时不是。即使是在同一天进行的测试也可能被取消一次。发生了什么事?

    您在第一步中通过将时间设置为午夜来识别问题:这确保了所有的小时、分钟和秒都为零。但你走得不够远!您还必须确保毫秒也归零

    这里有一些代码可以做到这一点

    protected long truncate_to_seconds (long date_in_millis) {
        long l = date_in_millis / 1000L;
        l *= 1000L;
        return l;
    } 
    

    我认为,在计算差异之前,您需要从日期开始截断时间部分,如下所示:

       DateFormat formatter= new SimpleDateFormat("MM/dd/yyyy");
       String truncatedDateString1 = formatter.format(date1);
       Date truncatedDate1 = formatter.parse(truncatedDateString1);
    
       String truncatedDateString2 = formatter.format(date2);
       Date truncatedDate2 = formatter.parse(truncatedDateString2);
    
       long timeDifference = truncatedDate2.getTime()- truncatedDate1.getTime();
    
       int daysInBetween = timeDifference / (24*60*60*1000);
    
    希望这能起作用。

    该库对此类问题提供了很好的支持:

    LocalDate d1 = new LocalDate(calendar1.getTimeInMillis());
    LocalDate d2 = new LocalDate(calendar2.getTimeInMillis());
    int days = Days.daysBetween(d1, d2).getDays();
    
    更新(来自@basil bourque的反馈):

    从Java 8开始,新的时间库
    Java.time
    已经引入,现在可以使用一个没有外部依赖项的类似选项:

    int days = Duration.between(calendar1.toInstant(), calendar2.toInstant()).toDays();
    

    正如其他用户所建议的,您还需要将日历的毫秒值设置为零,以便只比较日期。这可以通过以下代码段实现:

    someCalendar.set(Calendar.MILLISECOND, 0)
    

    另外,请注意,时区的变化(例如,从冬季时间移到夏季时间)可能意味着一天中的时间大于或小于86400000毫秒。

    应您的要求,我有自己的功能。我使用日历,在比较之前,我将所有时间部分设置为0

        int countDays(Date dateBegin, Date dateEnd) {
        if (dateBegin == null || dateEnd == null)
            return 0;
        Calendar from = asCalendar(dateBegin); // asCalendar() Initialise a Calendar from a Date
        Calendar to = asCalendar(dateEnd);
        // Set the time part to 0
        from.set(Calendar.MILLISECOND, 0);
        from.set(Calendar.SECOND, 0);
        from.set(Calendar.MINUTE, 0);
        from.set(Calendar.HOUR_OF_DAY, 0);
        to.set(Calendar.MILLISECOND, 0);
        to.set(Calendar.SECOND, 0);
        to.set(Calendar.MINUTE, 0);
        to.set(Calendar.HOUR_OF_DAY, 0);
        int nbJours = 0;
        for (Calendar c = from ; c.before(to) ; c.add(Calendar.DATE, +1))
        {
            nbJours++;
        }
        for (Calendar c = from ; c.after(to) ; c.add(Calendar.DATE, -1))
        {
            nbJours--;
        }
        return nbJours;
        }
    
    tl;博士 天真的计算 您在代码中假设每天正好24小时。不是真的。异常情况,如表示天数可能不同,如23小时长、25小时或其他数字。时区的真正含义是跟踪这些异常的历史

    另外,假设一天从午夜开始。不是真的。由于异常情况,有些日子从一天中的其他时间开始,如
    01:00

    避免遗留日期时间类 您使用的是麻烦的旧日期时间类,例如,和
    java.text.SimpleTextFormat
    现在已被这些类取代

    时区 以
    大陆/地区
    的格式指定,例如,或
    太平洋/奥克兰
    。切勿使用3-4个字母的缩写,如
    EST
    IST
    ,因为它们不是真正的时区,也不是标准化的,甚至不是唯一的(!)

    不要扩展java.time 不要扩展java.time类(子类)(它们被标记为
    final

    不要将它们的接口概括为您的业务逻辑;坚持这个框架的具体类。虽然在其他框架(如java.time)中,泛化是有意义的,但在java.time中则不然

    使用java.time 使用java.time类,这项工作要容易得多

    表示时间线上具有指定tim区域(
    ZoneId
    )的时刻

    枚举可以计算一对时刻之间经过的时间

    long days = ChronoUnit.DAYS.between( then , now );
    

    然后.toString():2017-01-23T12:34:56.123456789-05:00[美国/蒙特利尔]

    now.toString():2017-03-01T21:26:04.884-05:00[美国/蒙特利尔]

    天数:37

    将遗留实例转换为java.time 如果给定了对象,请使用添加到旧类中的新方法将其转换为java.time

    ZonedDateTime zdt = myGregCal.toZonedDateTime() ;
    
    如果您知道一个
    日历
    实例实际上是一个
    格里高利安日历
    ,请将其强制转换

    GregorianCalendar myGregCal = (GregorianCalendar) myCal ;
    
    半开 time类通过半开放方法定义时间跨度,其中开始是包含的,而结束是独占的


    关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

    该项目现已启动,建议迁移到类

    要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

    从哪里获得java.time类

    • 后来
      • 内置的
      • 标准JavaAPI的一部分,带有捆绑实现
      • Java9添加了一些次要功能和修复
      • 大部分java.time功能都在中向后移植到Java6和Java7
      • 该项目专门为Android采用了ThreeTen Backport(如上所述)

    该项目使用其他类扩展了java.time。这个项目是java.time将来可能添加的一个试验场。您可以在这里找到一些有用的类,如、、和。

    我已经编写了一种更简单的方法来解决这个问题,即使我遇到了同样的问题,在某些日期额外安排一天

    这是我目前的做法,

        public long getDays(long currentTime, long endDateTime) {
    
        Calendar endDateCalendar;
        Calendar currentDayCalendar;
    
    
        //expiration day
        endDateCalendar = Calendar.getInstance(TimeZone.getTimeZone("EST"));
        endDateCalendar.setTimeInMillis(endDateTime);
        endDateCalendar.set(Calendar.MILLISECOND, 0);
        endDateCalendar.set(Calendar.MINUTE, 0);
        endDateCalendar.set(Calendar.HOUR, 0);
    
        //current day
        currentDayCalendar = Calendar.getInstance(TimeZone.getTimeZone("EST"));
        currentDayCalendar.setTimeInMillis(currentTime);
        currentDayCalendar.set(Calendar.MILLISECOND, 0);
        currentDayCalendar.set(Calendar.MINUTE, 0);
        currentDayCalendar.set(Calendar.HOUR, 0);
    
        long remainingDays = Math.round((float) (endDateCalendar.getTimeInMillis() - currentDayCalendar.getTimeInMillis()) / (24 * 60 * 60 * 1000));
    
        return remainingDays;
    }
    
    之前我用的是这条线,其余的都一样:-

    long remainingDays = TimeUnit.MILLISECONDS.toDays(
                Math.abs(expiryCalendar.getTimeInMillis() - currentDayCalendar.getTimeInMillis()));
    

    但似乎对我不起作用。

    另一方面,您确定扩展
    日历
    而不是生成在
    日历
    实例上运行的帮助程序库是一个好主意吗?一个问题是,您假设一天有86400000毫秒。无需使用truncate方法,他只需将
    日历
    实例上的毫秒归零,就可以设置
    集(Calendar.millissecond,0)
    @DuncanJones,甚至更好!没有看到日历库的那个方面,谢谢@邓肯·琼斯:请加上这个作为回答,这样我就可以给你适当的信用。@ScottBiggs:很高兴知道。请不要忘记接受答案。优雅的解决方案!我应该更彻底地阅读文档(就像我们都有时间一样!)。仅供参考,麻烦的旧日期时间cla
        public long getDays(long currentTime, long endDateTime) {
    
        Calendar endDateCalendar;
        Calendar currentDayCalendar;
    
    
        //expiration day
        endDateCalendar = Calendar.getInstance(TimeZone.getTimeZone("EST"));
        endDateCalendar.setTimeInMillis(endDateTime);
        endDateCalendar.set(Calendar.MILLISECOND, 0);
        endDateCalendar.set(Calendar.MINUTE, 0);
        endDateCalendar.set(Calendar.HOUR, 0);
    
        //current day
        currentDayCalendar = Calendar.getInstance(TimeZone.getTimeZone("EST"));
        currentDayCalendar.setTimeInMillis(currentTime);
        currentDayCalendar.set(Calendar.MILLISECOND, 0);
        currentDayCalendar.set(Calendar.MINUTE, 0);
        currentDayCalendar.set(Calendar.HOUR, 0);
    
        long remainingDays = Math.round((float) (endDateCalendar.getTimeInMillis() - currentDayCalendar.getTimeInMillis()) / (24 * 60 * 60 * 1000));
    
        return remainingDays;
    }
    
    long remainingDays = TimeUnit.MILLISECONDS.toDays(
                Math.abs(expiryCalendar.getTimeInMillis() - currentDayCalendar.getTimeInMillis()));