Java计算两个日期之间的工作时长【包含节假日、补班、周末】

目的:用来计算两个日期之间的工作时长
说明:其中节假日、工作日工作时间需要从配置表中获取
直接上代码

public static void main(String[] args) throws Exception {calTime("2023-09-23 07:30:00", "2023-09-25 18:30:05");}/*** 计算两个日期间的工作时长** @param begintime yyyy-MM-dd HH:mm:ss* @param endTime   yyyy-MM-dd HH:mm:ss* @return 工作时长/毫秒*/public static long calTime(String begintime, String endTime) {Date startDate = DateUtil.parse(begintime);//节点到达时间Date endDate = DateUtil.parse(endTime);//当前时间int compareNum = DateUtil.compare(startDate, endDate);if (compareNum > 0) {String temp = endTime;endTime = begintime;begintime = temp;}startDate = DateUtil.parse(begintime);//节点到达时间endDate = DateUtil.parse(endTime);//当前时间System.out.println("计算前-hours-" + (((DateUtil.between(startDate, endDate, DateUnit.MS) * 1.0 / 3600000) - 3) > 0));long millis = DateUtil.between(startDate, endDate, DateUnit.MS);System.out.println("计算前-millis-" + millis);System.out.println("计算前-" + DateUtil.formatBetween(millis, BetweenFormater.Level.SECOND));//开始日期当天String beginDateStr = DateUtil.format(DateUtil.parse(begintime), "yyyy-MM-dd");String beginTimeStr = DateUtil.format(DateUtil.parse(begintime), "HH:mm:ss");//截止日期当天String endDateStr = DateUtil.format(DateUtil.parse(endTime), "yyyy-MM-dd");String endTimeStr = DateUtil.format(DateUtil.parse(endTime), "HH:mm:ss");long subMills = 0;//需要减去的时长Map<String, Map<String, String>> workDayInfoMap = initWorkdayInfo();// 同一天if (beginDateStr.equals(endDateStr)) {if (isWorkingDay(beginDateStr)) {//工作日long tempMills = calWorkDayRestMills(workDayInfoMap, beginDateStr, beginTimeStr, endTimeStr);subMills += tempMills;} else {subMills = millis;//同一天且非工作日}} else {long daysLen = DateUtil.between(DateUtil.parse(beginDateStr), DateUtil.parse(endDateStr), DateUnit.DAY, false);//相差天数//处理开始日期if (isWorkingDay(beginDateStr)) {long tempMills = calWorkDayRestMills(workDayInfoMap, beginDateStr, beginTimeStr, "23:59:59") + 1000;subMills += tempMills;} else {long tempMills = DateUtil.between(DateUtil.parse(begintime), DateUtil.parse(beginDateStr + " 23:59:59"), DateUnit.MS) + 1000;subMills += tempMills;}//处理中间日期if (daysLen > 1) {for (int i = 1; i < daysLen; i++) {String tempDateStr = DateUtil.format(DateUtil.offsetDay(DateUtil.parse(begintime), i), "yyyy-MM-dd");if (isWorkingDay(tempDateStr)) {long tempMills = calWorkDayRestMills(workDayInfoMap, tempDateStr, "00:00:00", "23:59:59") + 1000;subMills += tempMills;} else {long tempMills = DateUtil.between(DateUtil.parse(tempDateStr + " 00:00:00"), DateUtil.parse(tempDateStr + " 23:59:59"), DateUnit.MS) + 1000;subMills += tempMills;}}}//处理截止日期if (isWorkingDay(endDateStr)) {long tempMills = calWorkDayRestMills(workDayInfoMap, endDateStr, "00:00:00", endTimeStr);//工时长subMills += tempMills;} else {long tempMills = DateUtil.between(DateUtil.parse(endDateStr + " 00:00:00"), DateUtil.parse(endTime), DateUnit.MS);subMills += tempMills;}}System.out.println("计算后-subMills-" + subMills);millis = millis - subMills;System.out.println("计算后-millis-" + millis);System.out.println("计算后-" + DateUtil.formatBetween(millis, BetweenFormater.Level.SECOND));return millis;}/*** 计算工作日,开始时间--截止时间知之间的非工作日时间长【日期是同一天,且是工作日】** @param workDayInfoMap 工作日工作时间信息* @param dateStr        yyyy-MM-dd* @param beginTimeStr   HH:mm:ss* @param endTimeStr     HH:mm:ss* @return*/private static Long calWorkDayRestMills(Map<String, Map<String, String>> workDayInfoMap, String dateStr, String beginTimeStr, String endTimeStr) {if (workDayInfoMap == null || workDayInfoMap.size() == 0|| dateStr == null || beginTimeStr == null || endTimeStr == null) {return null;}//step1:判断时间大小Integer hourB = DateUtil.hour(DateUtil.parse(beginTimeStr), true);Integer hourE = DateUtil.hour(DateUtil.parse(endTimeStr), true);if (hourB > hourE) {String temp = endTimeStr;endTimeStr = beginTimeStr;beginTimeStr = temp;}//step2:获取两个时间的时间差,单位毫秒long allMills = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr), DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);System.out.println("计算中-allMills-" + allMills);long workMills1 = 0;long workMills2 = 0;//step3:获取月份及工作日信息Integer month = 1 + DateUtil.month(DateUtil.parse(dateStr));//DateUtil.month从0开始算String monthStr = String.valueOf(month);if (month < 10) {monthStr = "0" + month;}Map<String, String> workInfo = workDayInfoMap.get(monthStr);if (workInfo == null) {return null;}String amBegin = workInfo.get("amBegin");String amEnd = workInfo.get("amEnd");String pmBegin = workInfo.get("pmBegin");String pmEnd = workInfo.get("pmEnd");//step4:开始时间、结束时间和工作日时间对比int bcr1 = DateUtil.compare(DateUtil.parse(beginTimeStr), DateUtil.parse(amBegin));//1表示前面大,0相等,-1表示前面小int bcr2 = DateUtil.compare(DateUtil.parse(beginTimeStr), DateUtil.parse(amEnd));int bcr3 = DateUtil.compare(DateUtil.parse(beginTimeStr), DateUtil.parse(pmBegin));int bcr4 = DateUtil.compare(DateUtil.parse(beginTimeStr), DateUtil.parse(pmEnd));int ecr1 = DateUtil.compare(DateUtil.parse(endTimeStr), DateUtil.parse(amBegin));int ecr2 = DateUtil.compare(DateUtil.parse(endTimeStr), DateUtil.parse(amEnd));int ecr3 = DateUtil.compare(DateUtil.parse(endTimeStr), DateUtil.parse(pmBegin));int ecr4 = DateUtil.compare(DateUtil.parse(endTimeStr), DateUtil.parse(pmEnd));//step4:获取工作时长if (bcr1 < 0) {//上午上班前if (ecr1 < 0) {//上午上班前--无需处理} else if (ecr1 >= 0 && ecr2 < 0) {//上午上班区间workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + amBegin), DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);} else if (ecr2 >= 0 && ecr3 < 0) {//中午休息区间workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + amBegin), DateUtil.parse(dateStr + " " + amEnd), DateUnit.MS);} else if (ecr3 >= 0 && ecr4 < 0) {//下午上班区间workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + amBegin), DateUtil.parse(dateStr + " " + amEnd), DateUnit.MS);workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + pmBegin), DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);} else if (ecr4 >= 0) {//下午下班时间workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + amBegin), DateUtil.parse(dateStr + " " + amEnd), DateUnit.MS);workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + pmBegin), DateUtil.parse(dateStr + " " + pmEnd), DateUnit.MS);}} else if (bcr1 >= 0 && bcr2 < 0) {//上午上班区间if (ecr1 >= 0 && ecr2 < 0) {//上午上班区间workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr), DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);} else if (ecr2 >= 0 && ecr3 < 0) {//中午休息区间workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr), DateUtil.parse(dateStr + " " + amEnd), DateUnit.MS);} else if (ecr3 >= 0 && ecr4 < 0) {//下午上班区间workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr), DateUtil.parse(dateStr + " " + amEnd), DateUnit.MS);workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + pmBegin), DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);} else if (ecr4 >= 0) {//下午下班时间workMills1 = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr), DateUtil.parse(dateStr + " " + amEnd), DateUnit.MS);workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + pmBegin), DateUtil.parse(dateStr + " " + pmEnd), DateUnit.MS);}} else if (bcr2 >= 0 && bcr3 < 0) {//中午休息区间if (ecr2 >= 0 && ecr3 < 0) {//中午休息区间--无需处理} else if (ecr3 >= 0 && ecr4 < 0) {//下午上班区间workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + pmBegin), DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);} else if (ecr4 >= 0) {//下午下班时间workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + pmBegin), DateUtil.parse(dateStr + " " + pmEnd), DateUnit.MS);}} else if (bcr3 >= 0 && bcr4 < 0) {//下午上班区间if (ecr3 >= 0 && ecr4 < 0) {//下午上班区间workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr), DateUtil.parse(dateStr + " " + endTimeStr), DateUnit.MS);} else if (ecr4 >= 0) {//下午下班时间workMills2 = DateUtil.between(DateUtil.parse(dateStr + " " + beginTimeStr), DateUtil.parse(dateStr + " " + pmEnd), DateUnit.MS);}} else if (bcr4 >= 0) {//下午下班时间--无需处理}System.out.println("计算中-workMills1-" + workMills1);System.out.println("计算中-workMills2-" + workMills2);long noWorkMills = allMills - workMills1 - workMills2;System.out.println("计算中-(allMills - workMills1 - workMills2)-" + noWorkMills);return noWorkMills;}/*** 判断是否为工作日** @param dateStr yyyy-MM-dd* @return*/public static Boolean isWorkingDay(String dateStr) {List<String> holiday = initHoliday();List<String> extraWorkDay = initExtraWorkDay();//补班日if (extraWorkDay.contains(dateStr)) {return true;}//节假日if (holiday.contains(dateStr)) {return false;}//hutool工具jar,5.3.0版本【1是工作日,2-7表示周一到周六】int week = DateUtil.dayOfWeek(DateUtil.parse(dateStr));if (week == 1 || week == 7) {return false;//周末}return true;}/*** 初始化节假日【生产环境中请使用配置表】* 可通过接口获取每年节假日保存到配置表【文档--https://timor.tech/api/holiday】* String url = "https://timor.tech/api/holiday/year/2023/";* String rsa = HttpUtil.get(url);** @return*/public static List<String> initHoliday() {List<String> holiday = new ArrayList<>();holiday.add("2023-01-28");holiday.add("2023-12-31");holiday.add("2023-10-06");holiday.add("2023-10-05");holiday.add("2023-10-04");holiday.add("2023-10-03");holiday.add("2023-10-02");holiday.add("2023-10-01");holiday.add("2023-09-30");holiday.add("2023-09-29");holiday.add("2023-06-24");holiday.add("2023-06-23");holiday.add("2023-06-22");holiday.add("2023-05-03");holiday.add("2023-05-02");holiday.add("2023-05-01");holiday.add("2023-04-30");holiday.add("2023-04-29");holiday.add("2023-04-05");holiday.add("2023-01-27");holiday.add("2023-01-26");holiday.add("2023-01-25");holiday.add("2023-01-24");holiday.add("2023-01-23");holiday.add("2023-01-22");holiday.add("2023-01-21");holiday.add("2023-01-02");holiday.add("2023-01-01");return holiday;}/*** 初始化额外加班日【生产环境中请使用配置表】* 可通过接口获取每年节假日保存到配置表【文档--https://timor.tech/api/holiday】* String url = "https://timor.tech/api/holiday/year/2023/";** @return*/public static List<String> initExtraWorkDay() {List<String> extraWorkDay = new ArrayList<>();extraWorkDay.add("2023-10-08");extraWorkDay.add("2023-10-07");extraWorkDay.add("2023-06-25");extraWorkDay.add("2023-05-06");extraWorkDay.add("2023-04-23");extraWorkDay.add("2023-01-29");extraWorkDay.add("2023-01-28");return extraWorkDay;}/*** 初始化工作日工作时间【生产环境中请使用配置表】** @return*/public static Map<String, Map<String, String>> initWorkdayInfo() {Map<String, Map<String, String>> workDayInfoMap = new HashMap<>();//冬令时Map<String, String> map = new HashMap<>();map.put("amBegin", "08:00:00");map.put("amEnd", "12:00:00");map.put("pmBegin", "14:00:00");map.put("pmEnd", "17:30:00");workDayInfoMap.put("10", map);workDayInfoMap.put("11", map);workDayInfoMap.put("12", map);workDayInfoMap.put("01", map);workDayInfoMap.put("02", map);workDayInfoMap.put("03", map);workDayInfoMap.put("04", map);//夏令时map = new HashMap<>();map.put("amBegin", "08:00:00");map.put("amEnd", "12:00:00");map.put("pmBegin", "14:30:00");map.put("pmEnd", "18:00:00");workDayInfoMap.put("05", map);workDayInfoMap.put("06", map);workDayInfoMap.put("07", map);workDayInfoMap.put("08", map);workDayInfoMap.put("09", map);return workDayInfoMap;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/116611.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django viewsets 视图集与 router 路由实现评论接口开发

正常来说遵循restful风格编写接口&#xff0c;定义一个类包含了 get post delete put 四种请求方式&#xff0c;这四种请求方式是不能重复的 例如:获取单条记录和多条记录使用的方式都是get&#xff0c;如果两个都要实现的话那么得定义两个类&#xff0c;因为在同一个类中不能有…

【系统架构设计】 架构核心知识: 2 云原生架构

目录 一 云原生架构 1 云计算 2 分类 3 云计算架构 4 云原生架构设计原则

矿用升降台驱动电机调速控制系统建模与仿真

摘 要 在我们日常生活中&#xff0c;无刷直流电机随处可见&#xff0c;因为其相比其他电机而言结构相对简单&#xff0c;运行稳定且便于维修等优势&#xff0c;最重要的是直流电机在调速方面具有很好的优势。随着自动控制技术和微电子技术的不断革新&#xff0c;目前的技术水平…

【rust/树莓派】使用rppalembedded-graphics控制st7789 LCD屏幕

说在前面 树莓派版本&#xff1a;4bLCD模块&#xff1a;ST7789V2 240*280 LCD树莓派系统&#xff1a;Linux raspberrypi 5.15.76-v8 #1597 SMP aarch64 GNU/Linuxrust版本&#xff1a;rustc 1.73.0 模块详情 某雪的1.69inch LCD模块&#xff0c;包含杜邦线 准备工作 树莓派…

Camera2开发基础知识篇——手机影像参数

1. 2、对焦 对焦指相机将图像清晰聚焦的过程。自动对焦功能可自动调整焦点&#xff0c;确保主体清晰锐利。手动对焦功能允许用户手动选择焦点。 3、焦距 简单理解就是指镜头的视角和放大倍数。实际到物理设备&#xff0c;焦距就是从镜片光学中心到底片、CCD或CMOS等成像平面…

如何有效取代FTP来帮助企业快速传输大文件

在互联网的发展历史上&#xff0c;FTP是一种具有里程碑意义的协议&#xff0c;它最早出现在1971年&#xff0c;是实现网络上文件传输的基础。FTP的优点是简单、稳定、兼容性强&#xff0c;可以在不同的操作系统和平台之间进行文件交换。然而&#xff0c;时代在进步&#xff0c;…

【C语言】指针错题(类型分析)

题目&#xff1a; #include <stdio.h> int main () {int*p NULL;int arr[10] {0}; return 0; } 选项&#xff1a; A、p arr ; B、 int (* ptr )[10]& arr ; C、 p & arr [ 0 ]; D、 p & arr ; 解析&#xff1a; 1、 p 是一个指针变量&#xff0c;指…

vue3使用QuillEditor

1.安装 npm install vueup/vue-quillalpha --save 2.引入 全局引入 import { QuillEditor } from vueup/vue-quill; import vueup/vue-quill/dist/vue-quill.snow.css; app.component(QuillEditor, QuillEditor); 部分引入 import { QuillEditor } from vueup/vue-quill im…

【机器学习】模型平移不变性/等变性归纳偏置Attention机制

Alphafold2具有旋转不变性吗——从图像识别到蛋白结构预测的旋转对称性实现 通过Alphafold2如何预测蛋白质结构&#xff0c;看有哪些机制或tricks可以利用&#xff1f; 一、等变Transformer 等变Transformer是Transformer众多变体的其中一种&#xff0c;其强调等变性。不变性…

Vue非单文件组件

组件就是用来实现局部特定功能效果的代码集合&#xff0c;为的就是复用编码&#xff0c;简化项目编码&#xff0c;提高运行效率。 组件分为非单文件组件和单文件组件&#xff0c;这里介绍的是非单文件组件。 一、创建组件 创建组件的语法格式如下&#xff1a; const 组件名 …

Centos 7 部署Docker CE和docker-compose教程

一、Docker CE 1、Docker CE 安装 ①、安装依赖包 yum install -y yum-utils device-mapper-persistent-data lvm2②、设置yum源 # 官方源&#xff08;二选一&#xff09; yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # 阿里源…

Jmeter(十二):线程组元件第三方插件的线程组压力和负载线程详解

线程组(thread group) 线程组元件是任何一个测试计划的开始点。在一个测试计划中的所有元件 都必须在某个线程下。所有的任务都是基于线程组。 一个线程组可以看做一个虚拟用户组&#xff0c;线程组中的每个线程都可以理解为一 个虚拟用户。多个用户同时去执行相同的一批次任…

Git基本命令和使用

文章目录 1、Git本地库命令1.1、初始化本地库1.2、设置用户签名1.3、查看本地库状态1.4、将工作区的修改添加到暂存区1.5、将暂存区的修改提交到本地库1.6、历史版本1.7、取消commit1.8、取消暂存文件 2、分支操作2.1、查看分支2.2、创建分支2.3、分支合并时产生冲突 3、Gitee远…

Pillow(PIL)库的主要方法介绍

Pillow&#xff08;Python Imaging Library&#xff09;是Python中一个强大的图像处理库&#xff0c;它允许你进行图像的创建、打开、编辑、保存和显示等操作。Pillow 是 PIL&#xff08;Python Imaging Library&#xff09;的分支&#xff0c;支持多种图像格式&#xff0c;并提…

javaEE -7(网络原理初识 --- 7000字)

一&#xff1a;网络初识 计算机的独立模式是指多台计算机在网络中相互独立运行&#xff0c;彼此之间不共享资源或信息。在早期&#xff0c;计算机主要采用独立模式&#xff0c;每台计算机都拥有自己的操作系统、应用程序和数据&#xff0c;它们之间没有直接的连接或通信。 在…

解决LOGITECH 罗技驱动 MAC版出现的一些问题汇总!

安装前将之前的安装文件清理干净&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 罗技驱动最新安装包下载 我的鼠标是G304 1. 驱动安装一直卡在99% 运行官方下载的安装程序&#xff0c;卡住后关掉窗口。 在终端中执行以下命令&#xff1a; sudo /Users/用户名…

期 货 分 仓,资 管 分 仓,跟单软件都有哪些特点?

期货分仓软件是一种用于期货交易的软件系统。通过该系统&#xff0c;机构可以在一个主账户中同时使用多个子账户操作多个期货合约&#xff0c;并且可以设置不同资金量的用户不同的开仓比例。 由于目前国内的期货市场对于国际市场的品种还处于不规范阶段&#xff1a;一方面是保证…

Openssl数据安全传输平台003:Protobuf - 部署

文章目录 Github代码仓库位置一、Windows环境配置生成库文件之后—>参考3.3 配置VS1. 先将平台设置为所有平台2. 配置属性 >> C/C >> 常规 >> 附加包含目录3. 配置属性 >> C/C >> 预处理器 >> 预处理器定义,添加4. 配置属性 >> C…

1024程序员节:理解编码背后的艺术

1024的含义 "1024"在中国互联网文化中有两个主要的含义&#xff1a; 1024是2的10次方&#xff0c;这在计算机科学中是一个重要的数字&#xff0c;因为计算机的基础是二进制。因此&#xff0c;程序员们常常把1024作为一个特殊的日子来庆祝&#xff0c;也就是10月24日…

laravel框架介绍(一)

laravel框架是一套简洁&#xff0c;优雅的PHPWeb开发框架。