2

我想问是否有人知道任何 API 或类似的东西可以让我管理一天中的具体部分(例如工作时间)

我的问题是我必须在下一个上下文中管理时间:

想象一下,我在一家工作时间为“8am-2pm”和“3pm-6pm”的公司工作,夏令时从“8am 到 2pm”。我想知道具体日期的具体时刻是劳动时刻还是不是。

例如,如果我有提到的日历,并且我询问 API “2012 年 8 月 13 日晚上 9 点”是否是工作时间,它必须检查它并返回正确答案(在这种情况下为错误),如果我询问“ 2012 年 8 月 13 日上午 9 点”是一个工作时刻,它必须返回“真”

其他重要的事情相关。我必须使用提到的日历计算两个日期之间的间隔。例如,如果我将开始时间设置为“今天下午 5 点”,结束时间设置为“明天上午 10 点”,则它必须返回 3 小时(或以秒或毫秒为单位的等效时间),因为它是在开始日期和此日历中的结束日期。

它还必须与假期一起工作(特别是每个国家/地区)。我找到了一个 API 调用“JollyTime”,但是,虽然它适用于假期,但它不支持工作时间......

任何想法?

4

3 回答 3

1

更新: Joda-Time 库现在处于维护模式,其主要作者 Stephen Colebourne 继续领导 JSR 310,它定义了Java 8 及更高版本中内置的java.time类。


一个对日期时间具有复杂支持的良好数据库在这里可能会有所帮助。一个这样的数据库是Postgres,具有良好的日期时间数据类型命令(“函数”)

Joda-Time框架也可能有所帮助。Interval类及其父类定义了一对开始和停止日期时间之间的时间跨度。它们提供了比较方法,例如:包含、重叠、isBefore、is After。

下面是一些示例代码,可帮助您开始使用 Joda-Time 2.3 和 Java 7。

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;

DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );

List<Interval> workIntervalsFor13Aug2012 = new ArrayList<Interval>( 2 );
DateTime start, stop;
Interval interval;

start = new DateTime( 2012, 8, 13, 8, 0, 0, timeZone );
stop = new DateTime( 2012, 8, 13, 14, 0, 0, timeZone );
interval = new org.joda.time.Interval( start, stop );
workIntervalsFor13Aug2012.add( interval );

start = new DateTime( 2012, 8, 13, 15, 0, 0, timeZone );
stop = new DateTime( 2012, 8, 13, 18, 0, 0, timeZone );
interval = new org.joda.time.Interval( start, stop );
workIntervalsFor13Aug2012.add( interval );

// Check a date-time against those work intervals.
DateTime test09 = new DateTime( 2012, 8, 13, 9, 0, 0, timeZone );
DateTime test21 = new DateTime( 2012, 8, 13, 21, 0, 0, timeZone );

// You should write a "dateTimeIsInWorkingInterval" method that performs this loop.
Boolean hit = false;
for ( Interval nthInterval : workIntervalsFor13Aug2012 ) {
    if( nthInterval.contains( test09 )) {
        hit = true;
        break;
    }
}
if( hit ) {
    System.out.println( "This date-time: " + test09 + " occurs during a work interval.");
} else {
    System.out.println( "This date-time: " + test09 + " occurs outside a work interval.");
}

hit = false;
for ( Interval nthInterval : workIntervalsFor13Aug2012 ) {
    if( nthInterval.contains( test21 )) {
        hit = true;
        break;
    }
}
if( hit ) {
    System.out.println( "This date-time: " + test21 + " occurs during a work interval.");
} else {
    System.out.println( "This date-time: " + test21 + " occurs outside a work interval.");
}

运行时……</p>

This date-time: 2012-08-13T09:00:00.000+02:00 occurs during a work interval.
This date-time: 2012-08-13T21:00:00.000+02:00 occurs outside a work interval.
于 2013-12-24T22:06:01.990 回答
0

看看 JODA 时间库。我知道它有间隔,可能正是您所需要的。

于 2012-08-13T12:12:49.407 回答
0

我已经实施了一个简单的解决方案来计算两个日期之间的工作时间。从这个角度出发可能会帮助你完成你的任务。

这是以分钟或毫秒为单位计算工作时间的类。

public class WorkingTime {

private static final long ONE_SECOND_AS_MILISECONDS = TimeUnit.SECONDS.convert(1, TimeUnit.SECONDS);

private Integer startHour;
private Integer endHour;
private Integer startMinute;
private Integer endMinute;

public WorkingTime(int startHour, int endHour) {
    this(startHour, 0, endHour, 0);
}

public WorkingTime(Integer startHour, Integer startMinute, 
        Integer endHour, Integer endMinute) {
    super();
    this.startHour = startHour;
    this.endHour = endHour;
    this.startMinute = startMinute;
    this.endMinute = endMinute;
}

... getters and setters

public long calculateWorkingAsMilis(Date date1, Date date2) {
    return ONE_SECOND_AS_MILISECONDS * calculateWorkingSeconds(date1, date2);
}

public long calculateWorkingSeconds(Date date1, Date date2) {
    Calendar cal1 = Calendar.getInstance();
    cal1.setTime(date1);
    setWorkingCalendar(cal1);

    Calendar cal2 = Calendar.getInstance();
    cal2.setTime(date2);
    setWorkingCalendar(cal2);

    long day1 = TimeUnit.MILLISECONDS.toDays(cal1.getTimeInMillis());
    long day2 = TimeUnit.MILLISECONDS.toDays(cal2.getTimeInMillis());
    long daydiff = day2 - day1;
    long weekendDiff = (daydiff / 7); // get number of weekends
    if (isLeakWeekend(cal1, cal2))
        weekendDiff++;

    long dailyWorkingTimeAsMinutes = getDailyWorkingTimeAsMinutes();
    long secondsToBeDecrementedAsNonWorkingHours = TimeUnit.SECONDS.convert((24 * 60 - dailyWorkingTimeAsMinutes), TimeUnit.MINUTES); // seconds that are not in interval of working hours
    long secondsToBeDecrementedAsWorkingHoursForWeekends = TimeUnit.SECONDS.convert(dailyWorkingTimeAsMinutes * 2, TimeUnit.MINUTES); // weekend is not working days, they need to be decremented

    long dayDiffAsSeconds = daydiff * secondsToBeDecrementedAsNonWorkingHours;
    dayDiffAsSeconds += (weekendDiff * secondsToBeDecrementedAsWorkingHoursForWeekends); 

    long workDiffSeconds = TimeUnit.SECONDS.convert(
            cal2.getTimeInMillis() - cal1.getTimeInMillis(),
            TimeUnit.MILLISECONDS) - dayDiffAsSeconds; 
    return workDiffSeconds;
}

private boolean isLeakWeekend(Calendar cal1, Calendar cal2) {
    if (cal1.get(Calendar.DAY_OF_WEEK) > cal2.get(Calendar.DAY_OF_WEEK))
        return true;
    return false;
}

private long getDailyWorkingTimeAsMinutes() {
    return (getEndHour() * 60 + getEndMinute()) - (getStartHour() * 60 + getStartMinute());
}

private Calendar setWorkingCalendar(Calendar cal) {
    if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
        cal.set(Calendar.DAY_OF_YEAR, cal.get(Calendar.DAY_OF_YEAR) + 1);
        resetWorkingHourAndSeconds(cal);
    } else if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
        cal.set(Calendar.DAY_OF_YEAR, cal.get(Calendar.DAY_OF_YEAR) + 2);
        resetWorkingHourAndSeconds(cal);
    } else if (cal.get(Calendar.HOUR_OF_DAY) > endHour || (cal.get(Calendar.HOUR_OF_DAY) == endHour && cal.get(Calendar.MINUTE) > endMinute)) {
        cal.set(Calendar.HOUR_OF_DAY, endHour);
        cal.set(Calendar.MINUTE, endMinute);
    } else if (cal.get(Calendar.HOUR_OF_DAY) < startHour || (cal.get(Calendar.HOUR_OF_DAY) == startHour && cal.get(Calendar.MINUTE) < startMinute)) {
        cal.set(Calendar.HOUR_OF_DAY, startHour);
        cal.set(Calendar.MINUTE, startMinute);
    }
    return cal;
}
private Calendar resetWorkingHourAndSeconds(Calendar cal) {
    cal.set(Calendar.HOUR_OF_DAY, startHour);
    cal.set(Calendar.MINUTE, startMinute);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    return cal;
}

}

这是用法

// create an instance (working hours from 08:30 to 17:30)
WorkingTime workingTime = new WorkingTime(8, 30, 17, 30);
long durationAsMilis = workingTime.calculateWorkingAsMilis(date1, date2);

希望有帮助

通凯森图尔克

于 2013-12-24T09:34:01.637 回答