`
hekuilove
  • 浏览: 158189 次
  • 性别: Icon_minigender_1
  • 来自: 魔都
社区版块
存档分类
最新评论
阅读更多
客户的需求往往是各种各样的,本人在开发系统的时候遇到一个比较复杂的业务时间统计。
统计某个业务的工作时间(工作时间=结束时间-创建时间) 结束时间和创建时间在表里有字段记录,如果光是这样的统计就很简单了,直接用结束时间-创建时间就ok.可是客户用了几天觉得不爽,原因是统计不够精确。。比如,创建时间为17:00、完成时间为隔天9:00.数据库统计的时间应该是16个小时。但是程序计算往往和实际情况还是有一些差别。。客户实际情况是5点半下班,8点半上班。。那么这里的统计时间也应该为1个小时,而不是16个小时。。针对这个问题,客户提出了如下需求:
1、统计时间不包含节假日
2、统计时间不包含上下班时间
3、统计时间不包含周六周日
4、统计时间包含一些特殊的周六周日(如国庆节周六周日上班的情况)

   这样统计的话就很蛋疼了,如果根据这个需求统计那就得知道每个业务单的创建和完成时间,然后再根据每一个写各种蛋疼的判断。。而且重点是这个操作无法在数据库完成。。只能把所有符合要求的业务单查询出来 然后逐个判断并累加。。数量达到一定的程度的时候结果可想而知。。当然这是我最初的想法。。
  后来我改变了下想法、何不在填写完成时间的时候就直接把时间算好,然后填到一个字段里,于是就出现了如下的代码。。 

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();
		}
	}
      
}
分享到:
评论

相关推荐

    复杂数据统计方法-基于R应用(第三版)

    这些模型和算法在统计分析中非常常见,尤其在处理复杂的生存数据、时间序列数据、分类数据等方面有广泛的应用。 从书中获取的知识点可以总结如下: 1. R语言基础:包括R语言的基本语法、函数使用、数据结构、数据...

    时间序列分析—高阶统计量方法-张贤达

    此外,高阶统计量还能结合交叉验证、自助法(Bootstrap)等现代统计技术,对时间序列数据进行更复杂的分析。这些技术能够提供更为稳定和可靠的估计结果,并能有效地处理样本数据中的不确定性和复杂性。 在学习和...

    复杂网络统计动力学理论基础

    标题:复杂网络统计动力学理论基础 描述:这篇文章深入探讨了复杂网络的统计力学理论,是该领域的一个经典基础理论。对于那些致力于研究复杂网络的人来说,这篇文章提供了宝贵的见解和详尽的信息。 一、引言 复杂...

    高等院校研究生用书·复杂数据统计方法 基于R的应用 第2版 PDF电子书下载 带书签目录 试读版.pdf

    随着大数据时代的来临,统计学家和数据分析师常常需要处理比传统数据更复杂的数据集,这可能涉及到高维统计推断、时间序列分析、因果推断、网络数据分析等高级统计技术。 3. **案例教学法**: 描述中提到的“很多...

    时间序列分析——高阶统计量方法-张贤达

    高阶统计量方法是时间序列分析的一个重要分支,它超越了传统的均值、方差等低阶统计量,深入探讨数据的复杂结构和特性。 在张贤达的《时间序列分析——高阶统计量方法》中,作者可能详细讲解了以下几个关键知识点:...

    Oracle数据库按时间进行分组统计数据的方法

    Oracle数据库提供了一种强大的数据分组和统计功能,这在处理时间序列数据时尤其有用。在本示例中,我们关注的是如何利用SQL查询...在实际工作中,根据具体需求,可以组合使用这些方法,以实现更复杂的时间段分组统计。

    复杂数据统计方法_基于R的应用

    这些基础知识是理解和应用更复杂统计方法的基础。 其次,书中可能详细探讨了回归分析,包括线性回归、逻辑回归、多元回归以及岭回归等,这些都是预测和关联分析的核心工具。吴教授可能会通过实例来解释如何在R中...

    从统计物理学看复杂网络研究

    ### 从统计物理学视角探索复杂网络研究 #### 引言 近年来,复杂网络的研究成为跨学科研究的一个热点领域,涉及图论、统计物理学、计算机科学、生态学、社会学乃至经济学等多个学科。从统计物理学的角度来看,网络...

    字符串统计和百分比及程序运行时间

    在VB(Visual Basic)中,可以使用内置函数如`Len()`来获取字符串长度,`InStr()`或`Like`运算符来查找特定字符或模式,以及通过循环遍历字符串进行更复杂的统计。 **百分比计算**: 在数据分析中,百分比是一种...

    SPSS11统计分析教程高级篇-(生存、回归、时间序列

    《SPSS11统计分析教程高级篇——生存、回归、时间序列》是针对数据分析爱好者和专业人士的一份宝贵资源,它涵盖了统计学中的三个关键领域:生存分析、回归分析以及时间序列分析。本教程旨在帮助用户深入理解并熟练...

    代码行数统计工具

    SourceCounter作为这样的工具,其具体实现和特性可能会根据实际需求有所不同,但其核心功能在于提供准确、全面的代码行数统计,以便于项目管理和优化。在使用这类工具时,开发者应结合其他指标,如代码质量、测试...

    开始时间+结束时间+注册数量+登录数量+统计图

    “统计图”是数据可视化的核心工具,它能将复杂的数据转化为易于理解的图形,如折线图、柱状图、饼图等。在这个场景中,我们可以创建一个时间序列图,横轴表示时间,纵轴分别表示注册数量和登录数量,这样就可以清晰...

    统计物理与社会动态--一篇关于复杂网络方面的综述

    ### 统计物理与社会动态——复杂网络综述 #### 引言 本文是一篇关于统计物理在社会动力学中的应用及其与复杂网络之间关系的综述性文章。作者们探讨了统计物理学作为一种有效的框架来描述传统物理学领域之外的现象...

    复杂网络的统计力学,对复杂网络研究的整体介绍

    ### 复杂网络的统计力学 #### 一、引言 复杂网络的研究旨在探索和理解自然界及社会系统中广泛存在的复杂互联结构。这些系统包括但不限于细胞网络、国际互联网、社交网络、万维网等。传统的研究方法往往采用随机图...

    统计数字算法解答

    本篇将深入探讨“统计数字算法解答”,这是一个使用C++语言实现的解决方案,其关键在于它实现了高效的时间复杂度——对数时间复杂度O(log N)。这样的算法在处理大规模数据时具有显著优势,因为它能够快速地找出所需...

    冰雨数理统计器

    在实际应用中,冰雨数理统计器可能还提供了其他高级功能,如非参数检验、时间序列分析、多元统计方法等,以满足用户对复杂数据模型的需求。用户在使用时应熟悉软件界面和操作流程,同时理解统计原理,以确保正确解读...

    作业时间统计表.docx

    如果此部分时间过长,可能表明计划过程过于复杂或者目标不清晰,需要进行优化。 2. 由搭讪到预约所费的时间:这部分主要针对需要与客户沟通的业务,例如销售或咨询工作。它涵盖了从初次接触客户到成功安排会面的...

    c#源代码行数统计工具

    这个"C#源代码行数统计工具"提供了自定义排除行的功能,这意味着用户可以根据需求排除注释行、空行或者特定的代码块,使得统计结果更加精准。例如,注释行通常不计入有效代码行,因为它们不直接影响程序执行。此外,...

Global site tag (gtag.js) - Google Analytics