首页 文章

Joda-Time中两个日期之间的天数

提问于
浏览
291

如何找到两个Joda-Time DateTime实例之间的天数差异? “天数差异”是指如果开始是星期一而结束是星期二,我预计返回值为1,无论开始日期和结束日期的小时/分钟/秒 .

Days.daysBetween(start, end).getDays() 如果开始是在晚上并在早上结束,则给我0 .

我对其他日期字段也有同样的问题,所以我希望有一种通用的方法来“忽略”不太重要的字段 .

换句话说,2月到3月4日之间的月份也是1,而14:45到15:12之间的时间也是1 . 但是,14:01和14:55之间的小时差异为0 .

8 回答

  • -11

    令人讨厌的是,withTimeAtStartOfDay的答案是错误的,但只是偶尔 . 你要:

    Days.daysBetween(start.toLocalDate(), end.toLocalDate()).getDays()
    

    事实证明,“午夜/一天的开始”有时意味着凌晨1点(在某些地方以这种方式发生夏令时),Days.daysBetween无法正常处理 .

    // 5am on the 20th to 1pm on the 21st, October 2013, Brazil
    DateTimeZone BRAZIL = DateTimeZone.forID("America/Sao_Paulo");
    DateTime start = new DateTime(2013, 10, 20, 5, 0, 0, BRAZIL);
    DateTime end = new DateTime(2013, 10, 21, 13, 0, 0, BRAZIL);
    System.out.println(daysBetween(start.withTimeAtStartOfDay(),
                                   end.withTimeAtStartOfDay()).getDays());
    // prints 0
    System.out.println(daysBetween(start.toLocalDate(),
                                   end.toLocalDate()).getDays());
    // prints 1
    

    通过 LocalDate 回避整个问题 .

  • 349

    天班

    使用Days类与withTimeAtStartOfDay方法应该工作:

    Days.daysBetween(start.withTimeAtStartOfDay() , end.withTimeAtStartOfDay() ).getDays()
    
  • 2

    你可以使用LocalDate

    Days.daysBetween(new LocalDate(start), new LocalDate(end)).getDays()
    
  • 0

    tl;博士

    java.time.temporal.ChronoUnit.DAYS.between( 
        earlier.truncatedTo( ChronoUnit.DAYS )  , 
        later.truncatedTo( ChronoUnit.DAYS ) 
    )
    

    …要么…

    java.time.temporal.ChronoUnit.HOURS.between( 
        earlier.truncatedTo( ChronoUnit.HOURS )  , 
        later.truncatedTo( ChronoUnit.HOURS ) 
    )
    

    java.time

    仅供参考,Joda-Time项目现在是maintenance mode,该团队建议移民到java.time class .

    相当于Joda-Time DateTimeZonedDateTime .

    ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
    ZonedDateTime now = ZonedDateTime.now( z ) ;
    

    显然,您希望按日期计算日期,这意味着您要忽略一天中的时间 . 例如,在午夜前一分钟开始到午夜后一分钟结束应该会导致一天 . 对于此行为,从 ZonedDateTime 中提取 LocalDate . LocalDate类表示没有时间且没有时区的仅日期值 .

    LocalDate localDateStart = zdtStart.toLocalDate() ;
    LocalDate localDateStop = zdtStop.toLocalDate() ;
    

    使用ChronoUnit枚举计算已用天数或其他单位 .

    long days = ChronoUnit.DAYS.between( localDateStart , localDateStop ) ;
    

    截断

    至于你要求一个更通用的方法来计算你感兴趣的小时数增量作为小时的时间而不是60小时的 Span 的完整时间,使用 truncatedTo 方法 .

    这是你在同一天14:45到15:12的例子 .

    ZoneId z = ZoneId.of( "America/Montreal" ); 
    ZonedDateTime start = ZonedDateTime.of( 2017 , 1 , 17 , 14 , 45 , 0 , 0 , z );
    ZonedDateTime stop = ZonedDateTime.of( 2017 , 1 , 17 , 15 , 12 , 0 , 0 , z );
    
    long hours = ChronoUnit.HOURS.between( start.truncatedTo( ChronoUnit.HOURS ) , stop.truncatedTo( ChronoUnit.HOURS ) );
    

    1

    对于按日期计算的天数,请截断为 ChronoUnit.DAYS . 这是一个例子,从过去的五分钟到五分钟后的午夜,经历了 1 的过去几天 .

    ZoneId z = ZoneId.of( "America/Montreal" );
    ZonedDateTime start = ZonedDateTime.of( 2017 , 1 , 17 , 23 , 55 , 0 , 0 , z );
    ZonedDateTime stop = ZonedDateTime.of( 2017 , 1 , 18 , 00 , 05 , 0 , 0 , z );
    
    long days = ChronoUnit.DAYS.between( start.truncatedTo( ChronoUnit.DAYS ) , stop.truncatedTo( ChronoUnit.DAYS ) );
    

    1


    关于java.time

    java.time框架内置于Java 8及更高版本中 . 这些类取代了麻烦的旧legacy日期时间类,如java.util.DateCalendarSimpleDateFormat .

    现在位于maintenance modeJoda-Time项目建议迁移到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 .

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

  • 183

    接受的答案构建了两个 LocalDate 对象,如果您正在阅读大量数据,这些对象非常昂贵 . 我用这个:

    public static int getDaysBetween(DateTime earlier, DateTime later)
      {
        return (int) TimeUnit.MILLISECONDS.toDays(later.getMillis()- earlier.getMillis());
      }
    

    通过调用 getMillis() ,您可以使用已存在的变量 .
    MILLISECONDS.toDays() 然后,使用简单的算术计算,不会创建任何对象 .

  • 82

    java.time.Period

    使用java.time.Period类来count days .

    由于Java 8计算差异更直观,使用 LocalDateLocalDateTime 来表示两个日期

    LocalDate now = LocalDate.now();
        LocalDate inputDate = LocalDate.of(2018, 11, 28);
    
        Period period = Period.between( inputDate, now);
        int diff = period.getDays();
        System.out.println("diff = " + diff);
    
  • 6
    DateTime  dt  = new DateTime(laterDate);        
    
    DateTime newDate = dt.minus( new  DateTime ( previousDate ).getMillis());
    
    System.out.println("No of days : " + newDate.getDayOfYear() - 1 );
    
  • 1
    public static int getDifferenceIndays(long timestamp1, long timestamp2) {
        final int SECONDS = 60;
        final int MINUTES = 60;
        final int HOURS = 24;
        final int MILLIES = 1000;
        long temp;
        if (timestamp1 < timestamp2) {
            temp = timestamp1;
            timestamp1 = timestamp2;
            timestamp2 = temp;
        }
        Calendar startDate = Calendar.getInstance(TimeZone.getDefault());
        Calendar endDate = Calendar.getInstance(TimeZone.getDefault());
        endDate.setTimeInMillis(timestamp1);
        startDate.setTimeInMillis(timestamp2);
        if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) {
            int day1 = endDate.get(Calendar.DAY_OF_MONTH);
            int day2 = startDate.get(Calendar.DAY_OF_MONTH);
            if (day1 == day2) {
                return 0;
            } else {
                return 1;
            }
        }
        int diffDays = 0;
        startDate.add(Calendar.DAY_OF_MONTH, diffDays);
        while (startDate.before(endDate)) {
            startDate.add(Calendar.DAY_OF_MONTH, 1);
            diffDays++;
        }
        return diffDays;
    }
    

相关问题