根据时间的复杂统计

客户的需求往往是各种各样的,本人在开发系统的时候遇到一个比较复杂的业务时间统计。
统计某个业务的工作时间(工作时间=结束时间-创建时间) 结束时间和创建时间在表里有字段记录,如果光是这样的统计就很简单了,直接用结束时间-创建时间就ok.可是客户用了几天觉得不爽,原因是统计不够精确。。比如,创建时间为17:00、完成时间为隔天9:00.数据库统计的时间应该是16个小时。但是程序计算往往和实际情况还是有一些差别。。客户实际情况是5点半下班,8点半上班。。那么这里的统计时间也应该为1个小时,而不是16个小时。。针对这个问题,客户提出了如下需求:
[color=red][size=x-small][b]1、统计时间不包含节假日
2、统计时间不包含上下班时间
3、统计时间不包含周六周日
4、统计时间包含一些特殊的周六周日(如国庆节周六周日上班的情况)[/b][/size][/color]
这样统计的话就很蛋疼了,如果根据这个需求统计那就得知道每个业务单的创建和完成时间,然后再根据每一个写各种蛋疼的判断。。而且重点是这个操作无法在数据库完成。。只能把所有符合要求的业务单查询出来 然后逐个判断并累加。。数量达到一定的程度的时候结果可想而知。。当然这是我最初的想法。。
后来我改变了下想法、何不在填写完成时间的时候就直接把时间算好,然后填到一个字段里,于是就出现了如下的代码。。


import org.apache.commons.lang.time.DateUtils;

public class DateUtil{

/**
* 获取一天的毫秒数
*/
public static final long A_DAY_TIME = 86400000;

static String startWork = "08:30:00"; // 上班時間

static String offWork = "17:30:00"; // 下班時間

static List<String> holiday;// 节假日

static List<String> must; //不排除时间,必须上班
/**
* 这里没有使用数据库的数据直接是写了一个实例
*/
static {
holiday = new ArrayList<String>();
holiday.add("2012-12-10");
must = new ArrayList<String>();
must.add("2012-12-11");
}
/**
* 根据排除节假日、上班下班时间等条件算出两个时间之间的时间差 <br>
* 有特殊情况下,如国庆节周六周日上班,这种情况下可设置不排除时间
*
* @param startTime
* 开始时间
* @param toTime
* 结束时间
* @return 计算结果时间差
*/
public static final long countTimeByConditions(final long startTime,
final long toTime) {
long different = toTime - startTime;
final Date startDate = new Date(startTime);
final Date endDate = new Date(toTime);
final boolean isSame = DateUtils.isSameDay(startDate, endDate);// 判断开始时间和结束时间是否为同一天
if (!isSame) {
final int startDayOfWeek = DateUtil.getDayOfWeek(startDate); // 初始时间的星期几
System.out.println("起始时间为星期"+startDayOfWeek);
final int endDayOfWeek = DateUtil.getDayOfWeek(endDate);// 结束时间的星期几
System.out.println("结束时间为星期"+endDayOfWeek);
final int cha = DateUtil.diffInDate(startDate, endDate);// 相差几天
System.out.println("一共相差"+cha+"天");
final int holidays = DateUtil.hasHoliday(startDate, endDate); // 中间有几天节假日
System.out.println("其中有"+holidays+"天是节假日");
final int weeks = countWeeks(startDayOfWeek, endDayOfWeek, cha);// 计算一共经历了多少周
System.out.println("共经历了"+weeks+"周");
different -= (holidays * getAWorkTime());// 减去节假日
different -= (cha * (DateUtil.A_DAY_TIME - getAWorkTime()));// 减去下班
different -= (weeks * 2 * getAWorkTime());// 减去周末
different += (countMustWorkDays(startDate, endDate) * getAWorkTime()); // 计算必须上班的时间
}
return different;
}

/**
* 计算时间内有几天必须上班的时间(包括周末)
*
* @param start
* 开始时间
* @param end
* 结束时间
* @return 天数
*/
private static final int countMustWorkDays(final Date start, final Date end) {
int num = 0;
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
for (String day : DateUtil.must) {
try {
final long time = sdf.parse(day).getTime();
if (time < start.getTime() && time > end.getTime()) {
num++;
}
} catch (ParseException e) {
e.printStackTrace();
continue;
}
}
return num;
}

/**
* 根据开始星期几和结束星期几判断一个经历几周
*
* @param start
* 开始星期几
* @param end
* 结束星期几
* @param cha
* 经历天数
* @return 周数
*/
private static final int countWeeks(final int start, final int end,
final int cha) {
if (end - start > 0 && cha < 7)
return 0;
else {
int week = cha / 7;
if (end < start)
week++;
return week;
}
}

/**
* 获取一天工作时间
*
* @return
*/
private static final long getAWorkTime() {
final String start = "2000-01-01 " + startWork;
final String end = "2000-01-01 " + offWork;
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date s = null;
Date t = null;
try {
s = sdf.parse(start);
t = sdf.parse(end);
} catch (ParseException e) {
e.printStackTrace();
}
return t.getTime() - s.getTime();
}

/**
* 判断时间段内是否有节假日
*
* @param startDate
* 開始時間
* @param endDate
* 結束時間
* @return true or false
*/
private static final int hasHoliday(final Date startDate, final Date endDate) {
int num = 0;
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
for (String day : DateUtil.holiday) {
try {
final long time = sdf.parse(day).getTime();
if (time < endDate.getTime() && time > startDate.getTime()) {
num++;
}
} catch (ParseException e) {
e.printStackTrace();
continue;
}
}
return num;
}

/**
* 根据中国的星期来计算<br>
* 周日返回0,其他星期几则返回几
*
* @param date
* 要判断的时间
* @return 星期x
*/
public static final int getDayOfWeek(final Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int week = cal.get(Calendar.DAY_OF_WEEK) - 1;
return week == 0 ? 7 : week;
}

/**
* 返回两个日期相差的天数,有一个时间为null返回-1
*
* @param d1
* 长的时间
* @param d2
* 短的时间
* @return int
*/
public static final int diffInDate(Date d1, Date d2) {
double result = (double) (d1.getTime() - d2.getTime()) / 86400000;
if (result < 0)
result *= -1;
if (result > (int) result)
result++;
return (int) result;
}

public static void main(String[] args) {
final String time = "2012-12-11 09:00:00 ";
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
long now=System.currentTimeMillis();
System.out.println("起始时间:"+sdf.format(new Date(now)));
System.out.println("结束时间:"+time);
long hm = countTimeByConditions(now, sdf .parse(time).getTime());
System.out.println(hm+"毫秒");
System.out.println(hm/1000+"秒");
System.out.println((double)hm/(1000*60)+"分钟");
System.out.println((double)hm/(1000*60*60)+"小时");
System.out.println((double)hm/(1000*60*60*24)+"天");
} catch (ParseException e) {
e.printStackTrace();
}
}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值