`
hekuilove
  • 浏览: 156610 次
  • 性别: 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();
		}
	}
      
}
分享到:
评论

相关推荐

    复杂网络的概念及初识

    络区别于以前广泛研究的规则网络和随机网络最重要的统计特征是什么 ? 物理学家研究复杂网络的终极问题是 什么 ? 物理过程以及相关的物理现象对拓扑结构是否敏感 ? 物理学家进入这一研究领域的原因和意义何在 ? ...

    Python实现统计复杂网络中2-4个结点间具有相同最短距离的点的对数

    统计复杂网络中2-4个结点间具有相同最短距离的点的对数。...这个算法主要采用的是Floyd算法,在统计4个点之间具有相同最短路径长度的结点对数时,时间复杂度和空间复杂度极大,需要提前为IDE分配足够的堆栈空间。

    统计线段长度.lsp

    可以快速统计全部线长,方便快捷的插件,避免了重复操作及统计工作的复杂性,大幅度的节省工作时间,且统计数据可靠,不需要担心遗漏等问题。

    从1到n的奇数序列,统计3出现的次数

    计算从1~n的奇数序列,...该代码主要考虑缩减时间复杂性。其实原理与这个题目相同,稍作变化即可,把1换成了3,并且不是所有序列,而是奇数列,除了个位数为3的情况,其他位数的统计次数除以2即可。代码中有部分注释。

    地统计分析方法被广泛应用许多领域,已成为空间统计学的一个重要分支

    ArcGIS 地统计分析模块在地统计学与 GIS之间架起了一座桥梁,使得复杂的地统计 方法可以在软件中轻易实现,体现了以人为本、可视化发展的趋势。这种结合具有重要的 开创性意义,通过测定预测表面的统计误差,GIS ...

    ArcGIS_9_教程_第10章_地统计分析

    ArcGIS 地统计分析模块在地统计学与 GIS 之间架起了一座桥梁,使得复杂的地统计 方法可以在软件中轻易实现,体现了以人为本、可视化发展的趋势。这种结合具有重要的 开创性意义,通过测定预测表面的统计误差,GIS ...

    计算机毕业设计:基于深度学习的商品销量LSTM时间序列预测(含matplotlib统计图),保证可靠运行,赠计算机答辩PPT模板

    LSTM模型的优势在于能够处理具有复杂时间依赖性的数据,因此非常适合用于商品销量预测等任务。此外,项目还利用matplotlib库生成了丰富的统计图,直观地展示了销量数据的分布和变化趋势,有助于用户更好地理解预测...

    mysql实现多表关联统计(子查询统计)示例

    统计每本书打赏金额,不同时间的充值数据统计,消费统计, 设计四个表,book 书本表,orders 订单表 reward_log打赏表 consume_log 消费表 ,通过book_id与book表关联, 问题: 当关联超过两张表时导致统计时数据...

    大数据的统计分析方法-.docx

    分组分析法就是根据统计分析的目的要求,把所研究的总体按照一个或者几个标志划分为若干个部分,加以整理,进行观察、分析,以揭示其内在的联系和规律性。 统计分组法的关键问题在于正确选择分组标值和划分各组界限...

    论文研究-移动相册的复杂网络分析.pdf

    带有照相功能的移动终端的普及,产生了大量的照片,记录了用户的日常生活...分析了照片复杂加权网络的统计特性,揭示了其小世界特性。利用照片复杂网络,不仅可以可视化照片之间的多维关系,而且可以快速检索相关照片。

    从时间序列推断复杂运动领导动态的框架

    领导力在包括人类在内的社会...此外,我们的问题形式化和框架使科学家有机会分析协调活动,并生成有关集体行为的科学假设,这些假设可以在统计和现场进行测试。 关键词:领导力、协调性、时间序列、影响力、集体行为

    SCA对气候数据统计降尺度.pdf

    在气候数据的统计降尺度中,SCA可以用于识别具有相似气候特征的地区或时间段,并将它们归类到不同的气候类型或模式中。通过数据准备、数据预处理、确定聚类变量、确定距离度量、运行SCA算法、确定最佳聚类数目、解释...

    毕业设计-CellReport 是一个netcore实现的以复杂统计报表为核心目标的制作运行工具支持数据看板大屏.zip

    这里为你收集整理了关于毕业设计、课程设计可参考借鉴的资料一份,质量非常高,如果你投入时间去研究几天相信肯定对你有很大的帮助。到时候你会回来感谢我的。 本资源是经过本地编译测试、可打开、可运行的项目、...

    大数据与统计分析综述.pdf

    大数据与统计分析综述 发表时间:2018-12-18T10:18:29.840Z 来源:《基层建设》2018年第31期 作者: 赵丹丽 房庭栋 [导读] 摘要:随着信息技术的发展越来越快,普及程度越来越高,大数据对生活各领域的影响也越来越...

    Python打卡统计项目源码【含思路教程】

    我们通过研究不同的打卡规则,提出了一种新的统计方式,这种方式不仅简单易懂,而且可以轻松应对各种复杂的打卡规则。我们在代码中使用了类和对象的概念,这样可以更好地理解和组织代码,使得代码更加简洁明了。

    时间序列分析.pdf

    本书从应用的角度出发,试图借助计算机的存贮功能和计算功能来抽象掉其深奥的数学理论和复杂的运算,从而使只具一般数学知识的读者便可掌握和运用时间序列分析方法。在阐述中,尽可能回避严格的数学推导和证明,而从...

    SPSS最全版背诵重点整理文件(基本知识、数据整理、基本统计分析)必背版

    2.⽤户可以通过编程实现更复杂的统计分析任务 ③具有第四代语⾔的特点,即⾯向对象现代编程语⾔ ④具有完善的与其他软件的数据接⼝ 如Excel Asc码 DBF⽂件等 ⑤统计分析⽅法丰富 单变量描述到多变量分析 ⑥具有强⼤...

    论文研究-神经元混沌放电局部可视网络模型分析.pdf

    通过构建滑动时间窗内复杂网络拓扑,并计算其局部可视图的统计特性来实现时间序列时变特征的描述。对神经元map模型三种簇放电时间序列进行复杂网络构建并实现网络拓扑可视化,同时分析网络的统计特性来验证方法的...

    大盘数据统计.zip

    Big Data (大数据),或称巨量资料,指的是在传统数据处理应用软件不足以处理的大或复杂的数据集。大数据也可以定义为来自各种来源的大量非结构化或结构化数据。从学术角度而言,大数据的出现促成广泛主题的新颖...

Global site tag (gtag.js) - Google Analytics