`
pure1202
  • 浏览: 58316 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

怎样求2个日期间隔的工作日数?解决

阅读更多
还有很多要完善的地方,还有简单的实现没?希望各位帮我提提意见。。。。。
/*步骤: 类CountDaysByDate
 * 1、中间天数处理
 * 2、开始时间处理
 * 3、结束时间处理
*/
    private static int[] val = new int[] { 1, 7 };// 默认休息日为 六,日
	
	private static double WORK_DAY_COUNT = 7.5;	//定义一天的有几个小时
	
	//设置上下班时间、中午休息时间
	private static int AM_START_HOUR = 9; 
	private static int AM_START_MINUTE = 0;
	private static int AM_END_HOUR = 12; 
	private static int AM_END_MINUTE = 0; 
	private static int PM_START_HOUR = 13; 
	private static int PM_START_MINUTE = 0; 
	private static int PM_END_HOUR = 17; 
	private static int PM_END_MINUTE = 30; 
	private static double NOON_REST = 1; 
	
	/**
	 * 计算2个日期相差天数(排除休息日)
	 * @param beginDateStr
	 * @param endDateStr
	 * @return
	 * 步骤:
	 * 1、中间天数处理
	 * 2、开始时间处理
	 * 3、结束时间处理
	 */
	@SuppressWarnings("deprecation")
	public static double getDaysByDate(String beginDateStr,String endDateStr){
		double result = 0;
		double restTime = NOON_REST;//中午休息时间
		Calendar beginCalendar = getCalendar(beginDateStr);
		Calendar endCalendar = getCalendar(endDateStr);
		/**1、中间天数处理**/
		int days = getMargin(beginDateStr, endDateStr);
		/**2、开始时间处理**/
		if(days>0){//不是同一天
			//开始天上午工作开始-结束时间
			Calendar amStartWork1 = setHourAndMinute(getCalendar(beginDateStr),AM_START_HOUR,AM_START_MINUTE);
			Calendar amEndWork1 = setHourAndMinute(getCalendar(beginDateStr),AM_END_HOUR,AM_END_MINUTE);
			//开始天下午工作开始-结束时间
			//Calendar pmStartWork1 = setHourAndMinute(getCalendar(beginDateStr),PM_START_HOUR,PM_START_MINUTE);
			Calendar pmEndWork1 = setHourAndMinute(getCalendar(beginDateStr),PM_END_HOUR,PM_END_MINUTE);
			beginCalendar = setOverTime(beginDateStr);
			//计算开始天还有多少分钟
			int bvalue = 0;
			if(beginCalendar.compareTo(amStartWork1)>=0 && beginCalendar.compareTo(pmEndWork1)<=0){//beginCalendar<=pmEndWork1
				bvalue = ((int)(pmEndWork1.getTimeInMillis() - beginCalendar.getTimeInMillis()))/(60*1000) ;
				if(beginCalendar.compareTo(amEndWork1)<0){//beginCalendar<amEndWork1
					bvalue -= (int)(restTime*60);
				}
			}
			/**3、结束时间处理**/
			//末尾天上午工作开始-结束时间
			Calendar amStartWork2 = setHourAndMinute(getCalendar(endDateStr),AM_START_HOUR,AM_START_MINUTE);
			Calendar amEndWork2 = setHourAndMinute(getCalendar(endDateStr),AM_END_HOUR,AM_END_MINUTE);
			//末尾天下午工作开始-结束时间
			//Calendar pmStartWork2 = setHourAndMinute(getCalendar(endDateStr),PM_START_HOUR,PM_START_MINUTE);
			Calendar pmEndWork2 = setHourAndMinute(getCalendar(endDateStr),PM_END_HOUR,PM_END_MINUTE);
			endCalendar = setOverTime(endDateStr);
			//计算末尾天还有多少分钟
			int evalue = 0;
			if(endCalendar.compareTo(amStartWork2)>=0 && endCalendar.compareTo(pmEndWork2)<=0){//endCalendar<=pmEndWork2
				evalue = ((int)(pmEndWork2.getTimeInMillis() - endCalendar.getTimeInMillis()))/(60*1000) ;
				if(endCalendar.compareTo(amEndWork2)<0){//endCalendar<amEndWork2
					evalue -= (int)(restTime*60);
				}
			}
			double total = (bvalue - evalue)/((double)WORK_DAY_COUNT*60);
			result = days + total;
			result = ((int)(result*100))/(double)100;
		}else{//同一天
			int bvalue = 0;
			if(endCalendar.compareTo(beginCalendar)>0 ){//endCalendar>beginCalendar
				//上午工作开始-结束时间
				//Calendar amStartWork1 = setHourAndMinute(getCalendar(beginDateStr),AM_START_HOUR,AM_START_MINUTE);
				Calendar amEndWork1 = setHourAndMinute(getCalendar(beginDateStr),AM_END_HOUR,AM_END_MINUTE);
				//下午工作开始-结束时间
				Calendar pmStartWork1 = setHourAndMinute(getCalendar(beginDateStr),PM_START_HOUR,PM_START_MINUTE);
				//Calendar pmEndWork1 = setHourAndMinute(getCalendar(beginDateStr),PM_END_HOUR,PM_END_MINUTE);
				beginCalendar = setOverTime(beginDateStr);
				endCalendar = setOverTime(endDateStr);
				/**2中情况:特殊的->《9:00~17:00》; 普通的->《9:00~12:00》《13:00~17:00》;**/
				bvalue = ((int)(endCalendar.getTimeInMillis() - beginCalendar.getTimeInMillis()))/(60*1000) ;
				if(beginCalendar.compareTo(amEndWork1)<0 && endCalendar.compareTo(pmStartWork1)>0){//beginCalendar<amEndWork1
					bvalue -= (int)(restTime*60);
				}
				double total = (bvalue)/((double)WORK_DAY_COUNT*60);
				result = ((int)(total*100))/(double)100;
			}else{
				result = 0;
			}
		}
		return result;
	}
	
	/**
	 * 设置时间在工作时间范围内
	 * @param base
	 * @param amSw
	 * @param amEw
	 * @param pmSw
	 * @param pmEw
	 * @return
	 */
	public static Calendar setOverTime(String base){
		Calendar cal = getCalendar(base);
		//上午工作开始-结束时间
		Calendar amSw = setHourAndMinute(getCalendar(base),AM_START_HOUR,AM_START_MINUTE);
		Calendar amEw = setHourAndMinute(getCalendar(base),AM_END_HOUR,AM_END_MINUTE);
		//下午工作开始-结束时间
		Calendar pmSw = setHourAndMinute(getCalendar(base),PM_START_HOUR,PM_START_MINUTE);
		Calendar pmEw = setHourAndMinute(getCalendar(base),PM_END_HOUR,PM_END_MINUTE);
		if(cal.before(amSw)){//如果操作日期为上午工作开始时间之前,指定一个默认值
			cal = setHourAndMinute(cal,AM_START_HOUR,AM_START_MINUTE);
		}else if(cal.after(amEw) && cal.before(pmSw)){//如果操作日期为12:00~13:00,指定一个默认值
			cal = setHourAndMinute(cal,PM_START_HOUR,PM_START_MINUTE);
		}else if(cal.after(pmEw) ){//如果操作日期为17:30后			cal = setHourAndMinute(cal,PM_END_HOUR,PM_END_MINUTE);
		}else if(cal.compareTo(amEw)==0 || cal.compareTo(pmSw)==0){
			cal = setHourAndMinute(cal,PM_START_HOUR,PM_START_MINUTE);//如果操作日期为12:00/13:00
		}
		return cal;
	}
	
	/**
	 * 取得2个日期之间的休息日数目
	 * @param sDate
	 * @param eDate
	 * @return
	 */
	@SuppressWarnings("static-access")
	public static int getRestDays(String bDateStr,String eDateStr){
		int days = 0;
		Calendar bDate = getCalendar(bDateStr);
		Calendar eDate = getCalendar(eDateStr);
		while(eDate.after(bDate)){
			//判断是否有休息日
			for (int i = 0; i < val.length; i++) {
				if (bDate.get(bDate.DAY_OF_WEEK) == val[i]) {
					days ++;
				}
			}
			bDate.add(bDate.DATE,1);
		}
		return days;
	}
	
	/**
	 * 计算2个日期之间的天数(排除休息日),例如:2009-04-07 15:00:00 ~ 2009-04-09 15:00:00之间只有2009-04-08一天,则返回1,此处可加入排除节假日的方法。。。。。。
	 * @param bDateStr
	 * @param eDateStr
	 * @return
	 */
	@SuppressWarnings("static-access")
	public static int getMargin(String bDateStr, String eDateStr) {
		int margin;
		int resDays = 0;
		try {
			Calendar bDate = getCalendar(bDateStr);
			Calendar eDate = getCalendar(eDateStr);
			long l = eDate.getTimeInMillis() - bDate.getTimeInMillis();
			margin = (int) (l /(24 * 60 * 60 * 1000));
			while(eDate.after(bDate)){//判断是否有休息日
				for (int i = 0; i < val.length; i++) {
					if (bDate.get(bDate.DAY_OF_WEEK) == val[i]) {
						resDays ++;
					}
				}
				bDate.add(bDate.DATE,1);
			}
			return (int)(margin-resDays);
		} catch (Exception e) {
			return 0;
		}
	}
	
	/**
	 * 根据日期字符串得到它的Calendar对象
	 * 
	 * @param date
	 * @param df
	 * @return
	 */
	public static Calendar getCalendar(String date) {
		Calendar da = Calendar.getInstance();
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");// 定义时间格式
		SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");// 定义时间格式
		try {
			
			try{
				da.setTime(df.parse(date));
			}catch(Exception ex){
				da.setTime(df1.parse(date));
			}			
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return da;
	}
	
	/**
	 * Calendar时分设置辅助方法
	 * @param cal
	 * @param hour
	 * @param minute
	 * @return
	 */
	public static Calendar setHourAndMinute(Calendar cal,int hour,int minute){
		cal.set(Calendar.HOUR_OF_DAY,hour);
		cal.set(Calendar.MINUTE,minute);
		return cal;
	}

public static void main(String[] args) {
		String str1 = "2009-04-07 12:00:00";
		String str2 = "2009-04-08 13:45:00";
		double days = CountDaysByDate.getDaysByDate(str1, str2);
		System.out.println(str1+"-》"+str2+"=="+days);
}
分享到:
评论

相关推荐

    EXCEL函数公式集

    怎么样设置才能让这一列的每个单元格只能输入12位 如何让工作表奇数行背景是红色偶数行背景是蓝色 计算特定的一组单元格中,满足条件的单元格的个数 把文本格式的数字转换成真正的数字 设置页码 Excel表格里如何插入...

    Excel公式大全操作应用实例(史上最全)

    怎么样设置才能让这一列的每个单元格只能输入12位 如何让工作表奇数行背景是红色偶数行背景是蓝色 计算特定的一组单元格中,满足条件的单元格的个数 把文本格式的数字转换成真正的数字 设置页码 Excel表格里如何插入...

    人力资源管理软件(完全免费)

    提供个税工具,应发金额、所得税、应发任输一个数据自动计算另外2个 灵活生成各类统计报表,可定制方案 查询非常方便,支持组合条件查询 支持员工数据导入,支持初始工资数据导入,启用非常方便(见dll目录下导入...

    《Excel应用大全》示例文件 光盘文件

    • 利用取舍函数生成重复个数的自然数序列 • 按照特定条件进行取舍计算 • 利用取舍函数解决四舍六入问题 • 产生50~100 的随机整数 • 利用随机函数仅生成数字和字母 • 利用随机函数实现考试座位随机编排 • 日...

    JAVA面试题最全集

    如何取得从1970年到现在的毫秒数 如何获取某个日期是当月的最后一天 如何格式化日期 5.数组和集合 6.文件和目录(I/O)操作 如何列出某个目录下的所有文件 如何列出某个目录下的所有子目录 判断一个文件或...

    excel的使用

    (1)数组和矩阵的定义矩阵不是一个数,而是一个数组。在Excel里,数组占用一片单元域,单元域用大括号表示,例如{A1:C3},以便和普通单元域A1:C3相区别。设置时先选定单元域,同时按Shift+Ctrl+Enter键,大括弧...

    易利项目管理软件2013免费体验版(双代号网络图)

    5-01 修订横道图打开旧版本文件显示有偏差的问题 多谢【後知後覺】反馈,【阿立】帮助...6.29 增加日历的智能调整日期间隔功能:当压缩、拉伸日历的时候,会根据显示的需要智能计算每个日历刻度显示的日期数 功能改进

    文章管理系统

    后台每页显示个数增加最大200限制 2.网站验证码改为富媒体验证码,更难以被识别和破解 3.其他几个小细节修复和完善 2012年03月21日 V2.5升级包 ★更新方式:admin文件夹改成你后台目录名,然后补丁包里的所有...

    三虎企业建站系统(3hooCMS) v3.0 SP2.rar

    一年没有更新这个程序,一直在想写新版的V4,但是由于本人工作原因一直没有静心的时间下来写,这段离职后把原来的程序进行了彻底的改进,对一年以来累积的问题进行了整理和修正,包括一些细节与安全问题。 本程序承诺免费...

    入门学习Linux常用必会60个命令实例详解doc/txt

    hda1中的“1”代表hda的第一个硬盘分区 (partition),hda2代表hda的第二主分区,第一个逻辑分区从hda5开始,依此类推。此外,可以直接检查 /var/log/messages文件,在该文件中可以找到计算机开机后系统已辨认出来的...

    网络安全实验报告完整.doc

    学生姓名: 指导教师: 2016 年 6 月 13 日 实验报告 题 目: 网络信息安全综合实验 院 系:计算机系 班 级: 学 号: 学生姓名: 指导教师: 成 绩: 实验日期:2021 年 6 月 一、 目的与要求 根据实验内容的要求...

    jQuery攻略.pdf

     《jQuery攻略》对使用jQuery过程中遇到的各类问题给出了解决方案,比如,如何使用jQuery框架、CSS选择器、DOM、事件处理、动画效果,以及如何开发Ajax应用程序、如何使用jQuery工具函数、如何使用插件扩展jQuery。...

    asoft签到管理系统tykq3.5_build20110125

    优化请假模块在进行剔除工作时间的请假时间计算逻辑并修复一个因跨天签到设置导致计算不准确的BUG。 [2010-09-13] V3.4 正式版 build 20100913 1、增加开关左侧导航的功能,现在你可以有更大的视觉空间来查看...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    日期类型 date 7字节 用于存储表中的日期和时间数据,取值范围是公元前4712年1月1日至公元9999年12月31日,7个字节分别表示世纪、年、月、日、时、分和秒 二进制数据类型 row 1~2000字节 可变长二进制数据,在具体...

    SQL.Server.2008管理员必备指南.part2.rar(2/4)

     这本实用指南讲述了SQL Server 2008日常管理的工作。使用快速参考表、指令和列表聚焦核心的支持与维护任务。无论您是学生还是数据库领域的从业人员,都可从《SQL Server 2008管理员必备指南》获得解决问题和完成...

Global site tag (gtag.js) - Google Analytics