计算两个日期之间的小时数,不包括周末

时间:2016-03-21 18:02:03

标签: java date time

您好我在尝试计算在不同周末的java中两个不同时间戳之间发生的24小时工作小时数时遇到问题。

String timestamp = rs.getString("timestamp");

 String timeStamp = new SimpleDateFormat("yyyyMMddHH").format(new Date());

   int currentTimeStamp = Integer.parseInt(timeStamp);

   String orderTime = timestamp.replace("-", "");
   String[] splitTimestamp = orderTime.split(" ");

   String finalTimestamp = splitTimestamp[0] +    splitTimestamp[1].substring(0,2);

   int orderTimeStamp = Integer.parseInt(finalTimestamp);

这项目前确实有效,但包括周末。

如果有人能帮助我,我将非常感激。

这都是在东部时区完成的。

。周末不需要或不需要假期。

3 个答案:

答案 0 :(得分:3)

避免旧的日期时间类

与最早版本的Java捆绑在一起的旧日期时间类设计糟糕,令人困惑且麻烦。避免使用java.util.Date/.Calendar等。

java.time

使用Java 8及更高版本中内置的java.time框架。或者它的Java 7&的后端口6.见Oracle Tutorial

我没有尝试过运行此代码;就在我的头顶。 从不运行,从未进行过测试。可能会给你一个开始。

该问题似乎表明我们希望假定通用的24小时工作日而不是实际工作日(由于夏令时等异常情况,这些工作日可能会有所不同)。在通用日的情况下,我们不关心时区。我们可以使用LocalDateTime类。

如果开始时间是周末,请将其移至下周​​一的第一个时刻。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "yyyyMMddHH" );
LocalDateTime start = LocalDateTime.parse( "2016010123" , formatter );
// If on a weekend, move to first moment of Monday.
if( start.getDayOfWeek().equals( DayOfWeek.SATURDAY ) {
    start = start.plusDays( 2 ).toLocalDate().atStartOfDay(); 
}
if( start.getDayOfWeek().equals( DayOfWeek.SUNDAY ) {
    start = start.plusDays( 1 ).toLocalDate().atStartOfDay(); 
}

同样停止。如果在周末,请转到下周一的第一时刻。

LocalDateTime stop = LocalDateTime.parse( "2016010723" , formatter );
// If on a weekend, move to first moment of Monday.
if( stop.getDayOfWeek().equals( DayOfWeek.SATURDAY ) {
    stop = stop.plusDays( 2 ).toLocalDate().atStartOfDay(); 
}
if( stop.getDayOfWeek().equals( DayOfWeek.SUNDAY ) {
    stop = stop.plusDays( 1 ).toLocalDate().atStartOfDay(); 
}

如果开始与停止相同,我们就完成了:报告零。

if( start.isEqual( stop ) ) {
    return 0;
}

如果开始在停止之后,我们会出现错误情况。抛出异常,尝试纠正问题,或报告零,无论你的应用程序有什么意义。

if( start.isAfter( stop ) ) {
    return 0; // Or consider it a problem, throw exception.
}

让我们将这个问题分为三个部分:

  • 第一天,
  • 最后一个部分日,
  • 介于两者之间的整天数。

为了表示部分日期,我们使用Duration类。 Duration是一个时间跨度跟踪的总秒数加上纳秒。

第一部分从start开始到第二天的第一时刻。

LocalDateTime firstMomentOfDayAfterStart = start.toLocalDate().plusDays(1).atStartOfDay();
Duration firstDayDuration = Duration.between( start , firstMomentOfDayAfterStart );

最后一个部分日从同一天的第一个时刻开始stop

LocalDateTime firstMomentOfDayOfStop = stop.toLocalDate().atStartOfDay();
Duration lastDayDuration = Duration.between( firstMomentOfDayOfStop , stop );

我们可以将每个Duration转换为数小时。

int hoursFirstDay = firstDayDuration.toHours(); 
int hoursLastDay = lastDayDuration.toHours();

因此,我们有定义这些时间跨度的变量,如下图所示。请记住,这些是半开放的,每个范围的结尾是独占

[ start > firstMomentOfDayAfterStart ][ firstMomentOfDayAfterStart > firstMomentOfDayOfStop ][ firstMomentOfDayOfStop > stop ]

现在在这对偏天之间循环整整一天。每天递增,连续一天测试工作日或周末。记住我们遇到的工作日。使用方便的DayOfWeek enum进行比较。

int countWeekdays = 0;
LocalDateTime firstMomentOfSomeDay = firstMomentOfDayAfterStart
while( firstMomentOfSomeDay.isBefore( firstMomentOfDayOfStop ) ) {
    DayOfWeek dayOfWeek = firstMomentOfSomeDay.getDayOfWeek();
    if( dayOfWeek.equals( DayOfWeek.SATURDAY ) || dayOfWeek.equals( DayOfWeek.SUNDAY ) ) {
        // ignore this day.
    } else {
        countWeekdays ++ ; // Tally another weekday.
    }
    // Set up the next loop.
    firstMomentOfSomeDay = firstMomentOfSomeDay.plusDays( 1 );
}

我们可以使用TimeUnit枚举将整天的计数转换为小时数。此转换假设为24小时通用。

int hoursOfWholeDays = TimeUnit.DAYS.toHours( countWeekDays ) ;

全部添加。

int totalHours = ( hoursFirstDay + hoursOfWholeDays + hoursLastDay ) ;

完成。返回总小时数。

return totalHours ;

如果您的数据通常包含很长一段时间,那么您可以考虑通过检测星期一和计算整周数来优化性能。我假设在业务场景中跟踪订单,间隔时间很短。所以这种优化不太可能很重要。

EnumSet

您可以替换该行:

if( dayOfWeek.equals( DayOfWeek.SATURDAY ) || dayOfWeek.equals( DayOfWeek.SUNDAY ) )…

...使用EnumSet

Set<DayOfWeek> weekend = EnumSet.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY ) ;
…
if( weekend.contains( dayOfWeek ) ) …

时间调整器

有关使用my answer to another Question课程的nextWorkingDaypreviousWorkingDay方法检测周末的详细信息,请参阅Temporals。这个类可以在扩展java.time框架的ThreeTen-Extra项目中找到。

此外,该类文档表明,编写自己的时态调整器以适合您的特定业务规则相对容易。

答案 1 :(得分:2)

我发现java.util.Calendar更干净,这是一个从3月1日(早上8点)到当前时间的小时数的例子:

git push origin master:test

答案 2 :(得分:0)

你可以这样做:

    Date date1 = new Date(2016, 3, 21), date2 = new Date(2016, 4, 9);

    int oneHour = 1000 * 60 * 60;

    //Note that this rounds down the number of hours/days
    int hours = (int)((date2.getTime() - date1.getTime()) / oneHour); 
    int days = hours / 24; 

    int day1, day2;
    //set the values of day: [Sun=0, Mon=1, Tue=2, Wed=3, Thur=4, Fri=5, Sat=6]
    //date.getDay() is supposed to do that, but it's deprecated

    int nWEdays = days/7*2;

    if(day2-day1 < 0) nWEdays += 2;
    else {
        if(day1 == 0 || day1 == 6) nWEdays++;
        else if(day2 == 0 || day2 == 6) nWEdays++;
    }
    int weekendHours = hours - nWEdays*24;