如何使用Java日历忽略周末? [英] How do I ignore weekends using the Java calendar?

查看:167
本文介绍了如何使用Java日历忽略周末?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过忽略周末获得两个特定时间实例之间的分钟数。这是我做的。

  public static final List< Integer> NON_WORKING_DAYS; 
static {
List< Integer> nonWorkingDays = new ArrayList< Integer>();
nonWorkingDays.add(Calendar.SATURDAY);
nonWorkingDays.add(Calendar.SUNDAY);
NON_WORKING_DAYS = Collections.unmodifiableList(nonWorkingDays);
}

public static int getMinsBetween(Date d1,Date d2,boolean onlyBusinessDays)
{
int minsBetween =(int)((d2.getTime d1.getTime())/(1000 * 60));
int minsToSubtract = 0;
if(onlyBusinessDays){
Calendar dateToCheck = Calendar.getInstance();
dateToCheck.setTime(d1);
Calendar dateToCompare = Calendar.getInstance();
dateToCompare.setTime(d2);


//将星期一的第一天移动到星期二,以便星期六,太阳和星期在同一周,容易调整日期
dateToCheck.setFirstDayOfWeek 。星期二);
dateToCompare.setFirstDayOfWeek(Calendar.TUESDAY);

//将日期移出周末
if(!isBusinessDay(dateToCheck,NON_WORKING_DAYS)){
dateToCheck.set(Calendar.DAY_OF_WEEK,Calendar.SATURDAY);
dateToCheck.set(Calendar.HOUR,0);
dateToCheck.set(Calendar.MINUTE,0);
dateToCheck.set(Calendar.SECOND,0);
dateToCheck.set(Calendar.MILLISECOND,0);
}

if(!isBusinessDay(dateToCompare,NON_WORKING_DAYS)){
dateToCompare.set(Calendar.DAY_OF_WEEK,Calendar.MONDAY);
dateToCompare.set(Calendar.HOUR,0);
dateToCompare.set(Calendar.MINUTE,0);
dateToCompare.set(Calendar.SECOND,0);
dateToCompare.set(Calendar.MILLISECOND,0);
}

for(; dateToCheck.getTimeInMillis()< dateToCompare.getTimeInMillis(); dateToCheck.add(Calendar.DAY_OF_MONTH,1)){
if(isBusinessDay(dateToCheck ,NON_WORKING_DAYS)){
minsToSubtract = minsToSubtract + 1440;
}
}
minsBetween = minsBetween - minsToSubtract;
}
return minsBetween;
}


private static boolean isBusinessDay(Calendar dateToCheck,List< Integer> daysToExclude){
for(Integer dayToExclude:daysToExclude){
if( dayToExclude!= null&& amp; dayToExclude == dateToCheck.get(Calendar.DAY_OF_WEEK)){
return true;
}
else continue;
}
return false;
}

有人可以告诉我,如果我的逻辑是正确的,如果不是如何做?我不太确定这个代码在月末在周末变化时的行为。



某些测试用例的预期输出:


  1. 周一下午6点

  2. 星期六下午12点,星期六上午6点 - 应该返回6小时


解决方案

我强烈建议您使用 Joda-Time 关于Java中日期操作的任何东西,因为它带有很多有用的函数,使代码不那么复杂。 >

此代码使用JodaTime:

  public static final List< Integer> NON_WORKING_DAYS; 
static {
List< Integer> nonWorkingDays = new ArrayList< Integer>();
nonWorkingDays.add(DateTimeConstants.SATURDAY);
nonWorkingDays.add(DateTimeConstants.SUNDAY);
NON_WORKING_DAYS = Collections.unmodifiableList(nonWorkingDays);
}

public static Minutes getMinsBetween(DateTime d1,DateTime d2,
boolean onlyBusinessDays){

BaseDateTime startDate = onlyBusinessDays& !isBusinessDay(d1)?
new DateMidnight(d1):d1;
BaseDateTime endDate = onlyBusinessDays&&& !isBusinessDay(d2)?
new DateMidnight(d2):d2;

分钟分钟= Minutes.minutesBetween(startDate,endDate);

if(onlyBusinessDays){
DateTime d = new DateTime(startDate);

while(d.isBefore(endDate)){
if(!isBusinessDay(d)){
Duration dayDuration = new Duration(d,d.plusDays(1)) ;
minutes = minutes.minus(int)dayDuration.getStandardMinutes());
}
d = d.plusDays(1);
}
}
return minutes;
}

private static boolean isBusinessDay(DateTime dateToCheck){
return!NON_WORKING_DAYS.contains(dateToCheck.dayOfWeek()。get());
}

测试此代码时,它会产生以下结果:

  DateTime d1 = new DateTime(2013,1,4,18,0); // a Friday,6 pm 
DateTime d2 = new DateTime(2013,1,7,6,0); //下一个星期一,上午6点

分钟分钟= getMinsBetween(d1,d2,true);
System.out.println(minutes.toStandardHours()。getHours()); //输出12(以小时为单位)

d1 = new DateTime(2013,1,5,12,0) // a Saturday,12 pm
d2 = new DateTime(2013,1,6,12,0); //下一个星期日,12时

minutes = getMinsBetween(d1,d2,true);
System.out.println(minutes.toStandardHours()。getHours()); //输出0(以小时为单位)

d1 = new DateTime(2013,1,5,12,0) // a Saturday,12 pm
d2 = new DateTime(2013,1,7,6,0); //下一个星期一,上午6点

minutes = getMinsBetween(d1,d2,true);
System.out.println(minutes.toStandardHours()。getHours()); //输出6(以小时为单位)

周末:从3月29日(6pm)星期五到4月1日星期一(6am):

  3,29,18,0); 
d2 = new DateTime(2013,4,1,6,0);

minutes = getMinsBetween(d1,d2,true);
System.out.println(minutes.toStandardHours()。getHours());

结果是12小时,因此它适用于月份更改。






我的第一个解决方案没有正确处理夏令时。我们必须确定每个实际天减去分钟的时间,因为夏令时更改的日期不会是24小时:

  if(!isBusinessDay(d)){
Duration dayDuration = new Duration(d,d.plusDays(1));
minutes = minutes.minus(int)dayDuration.getStandardMinutes());
}


I'm trying to get the number of minutes between two particular time instances by ignoring weekends. This is what I've done.

public static final List<Integer> NON_WORKING_DAYS;
static {
    List<Integer> nonWorkingDays = new ArrayList<Integer>();
    nonWorkingDays.add(Calendar.SATURDAY);
    nonWorkingDays.add(Calendar.SUNDAY);
    NON_WORKING_DAYS = Collections.unmodifiableList(nonWorkingDays);
}

public static int getMinsBetween(Date d1, Date d2, boolean onlyBusinessDays)
{
    int minsBetween = (int)((d2.getTime() - d1.getTime()) / (1000 * 60));
    int minsToSubtract = 0;
    if(onlyBusinessDays){
        Calendar dateToCheck = Calendar.getInstance();
        dateToCheck.setTime(d1);
        Calendar dateToCompare = Calendar.getInstance();
        dateToCompare.setTime(d2);


        //moving the first day of the week to Tues so that a Sat, sun and mon fall in the same week, easy to adjust dates
        dateToCheck.setFirstDayOfWeek(Calendar.TUESDAY);
        dateToCompare.setFirstDayOfWeek(Calendar.TUESDAY);

        //moving the dates out of weekends
        if(!isBusinessDay(dateToCheck, NON_WORKING_DAYS)){
            dateToCheck.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
            dateToCheck.set(Calendar.HOUR, 0);
            dateToCheck.set(Calendar.MINUTE, 0);
            dateToCheck.set(Calendar.SECOND, 0);
            dateToCheck.set(Calendar.MILLISECOND, 0);
        }

        if(!isBusinessDay(dateToCompare, NON_WORKING_DAYS)){
            dateToCompare.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
            dateToCompare.set(Calendar.HOUR, 0);
            dateToCompare.set(Calendar.MINUTE, 0);
            dateToCompare.set(Calendar.SECOND, 0);
            dateToCompare.set(Calendar.MILLISECOND, 0);
        }

        for(; dateToCheck.getTimeInMillis() < dateToCompare.getTimeInMillis() ; dateToCheck.add(Calendar.DAY_OF_MONTH, 1)){
            if(isBusinessDay(dateToCheck, NON_WORKING_DAYS)){
                minsToSubtract = minsToSubtract + 1440;
            }
        }
    minsBetween = minsBetween - minsToSubtract; 
    }
    return minsBetween;
}


private static boolean isBusinessDay(Calendar dateToCheck, List<Integer> daysToExclude){
    for(Integer dayToExclude : daysToExclude){
        if(dayToExclude != null && dayToExclude == dateToCheck.get(Calendar.DAY_OF_WEEK)) {
            return true; 
        }
        else continue;
    }
    return false;
}

Can someone tell me if my logic is correct and if not how to do this? I'm not too sure how this code would behave when the month changes over the weekend.

Expected output for some test cases:

  1. Friday 6 pm, Monday 6 am - should return 12 hours
  2. Saturday 12 pm, Sunday 12 pm - should return 0 hours
  3. Saturday 12 pm, Monday 6 am - should return 6 hours

解决方案

I would highly recommend using Joda-Time for anything concerning date manipulations in Java, because it comes with a lot of helpful functions to make the code less complicated.

This code uses JodaTime:

public static final List<Integer> NON_WORKING_DAYS;
static {
    List<Integer> nonWorkingDays = new ArrayList<Integer>();
    nonWorkingDays.add(DateTimeConstants.SATURDAY);
    nonWorkingDays.add(DateTimeConstants.SUNDAY);
    NON_WORKING_DAYS = Collections.unmodifiableList(nonWorkingDays);
}

public static Minutes getMinsBetween(DateTime d1, DateTime d2,
        boolean onlyBusinessDays) {

    BaseDateTime startDate = onlyBusinessDays && !isBusinessDay(d1) ?
                new DateMidnight(d1) : d1;
    BaseDateTime endDate = onlyBusinessDays && !isBusinessDay(d2) ?
                new DateMidnight(d2) : d2;

    Minutes minutes = Minutes.minutesBetween(startDate, endDate);

    if (onlyBusinessDays) {
        DateTime d = new DateTime(startDate);

        while (d.isBefore(endDate)) {
            if (!isBusinessDay(d)) {
                Duration dayDuration = new Duration(d, d.plusDays(1));
                minutes = minutes.minus(int) dayDuration.getStandardMinutes());
            }
            d = d.plusDays(1);
        }
    }
    return minutes;
}

private static boolean isBusinessDay(DateTime dateToCheck) {
    return !NON_WORKING_DAYS.contains(dateToCheck.dayOfWeek().get());
}

When this code is tested, it gives the following results:

DateTime d1 = new DateTime(2013, 1, 4, 18, 0); // a Friday, 6 pm
DateTime d2 = new DateTime(2013, 1, 7, 6, 0);  // the following Monday, 6 am

Minutes minutes = getMinsBetween(d1, d2, true);
System.out.println(minutes.toStandardHours().getHours()); // outputs "12" (in hours)

d1 = new DateTime(2013, 1, 5, 12, 0); // a Saturday, 12 pm
d2 = new DateTime(2013, 1, 6, 12, 0); // the following Sunday, 12 pm

minutes = getMinsBetween(d1, d2, true);
System.out.println(minutes.toStandardHours().getHours()); // outputs "0" (in hours)

d1 = new DateTime(2013, 1, 5, 12, 0); // a Saturday, 12 pm
d2 = new DateTime(2013, 1, 7, 6, 0);  // the following Monday, 6 am

minutes = getMinsBetween(d1, d2, true);
System.out.println(minutes.toStandardHours().getHours()); // outputs "6" (in hours)

I just tested a case where the month changes over the weekend: From Friday, March 29th (6pm) to Monday, April 1st (6am):

d1 = new DateTime(2013, 3, 29, 18, 0);
d2 = new DateTime(2013, 4, 1, 6, 0);

minutes = getMinsBetween(d1, d2, true);
System.out.println(minutes.toStandardHours().getHours());

The result is 12 hours, so it works for the month change.


My first solution wasn't handling daylight saving times correctly. We have to determine the duration of each actual day when subtracting the minutes because days with a change in daylight saving time will not be 24h:

if (!isBusinessDay(d)) {
    Duration dayDuration = new Duration(d, d.plusDays(1));
    minutes = minutes.minus(int) dayDuration.getStandardMinutes());
}

这篇关于如何使用Java日历忽略周末?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆