java解析Cron时间表达式为中文描述

碰到个需求,后端返回给前端的时候如果直接返回表达式给前端在页面展示,用户会看不懂!所以要转为非开发人员看到也能明白的中文描述

这里说一下后端解析,无非就是空格切分一个个判断了:

前端js解析在这里: CronExpParserUtil.js

直接上代码

<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.8.1</version>
</dependency>

 WeekEnum.java

package com.example.wftspringbootdemo.test.utils;public enum WeekEnum {SECONDS("1", "星期天", "Sunday "), MONDAY("2", "星期一", "Monday "), TUESDAY("3", "星期二", "Tuesday "), WEDNESDAY("4","星期三", "Wednesday "), THURSDAY("5", "星期四","Thursday "), FRIDAY("6", "星期五", "Friday "), SATURDAY("7", "星期六", "Saturday ");private String key;private String nameCn;private String nameEn;WeekEnum(String key, String nameCn, String nameEn) {this.key = key;this.nameCn = nameCn;this.nameEn = nameEn;}public static String matchNameCn(String code) {for (WeekEnum m : WeekEnum.values()) {if (m.getKey().equals(code)) {return m.getNameCn();}}return "";}public static String matchNameEn(String code) {for (WeekEnum m : WeekEnum.values()) {if (m.getKey().equals(code)) {return m.getNameEn();}}return "";}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public String getNameCn() {return nameCn;}public void setNameCn(String nameCn) {this.nameCn = nameCn;}public String getNameEn() {return nameEn;}public void setNameEn(String nameEn) {this.nameEn = nameEn;}}

CronExpParseUtil.java 

package com.example.wftspringbootdemo.test.utils;import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;public class CronExpParserUtil {protected final static String[] CRON_TIME_CN = new String[]{"秒", "分钟", "小时", "天", "月","周", "年"};private final static Integer HOURS = 24;private final static Integer TIMESCALE = 60;/***  主要解析 斜杆  /:表示起始时间开始触发,然后每隔固定时间触发一次。*      范围值+开始值 - 间隔值 = 范围内最后执行的值;*      例如在Hourss域使用3/4,则意味着从第3小时到24+3-4:23小时范围内,第3小时开始触发第一次,然后每隔4小时,即7,11,15,19,23小时等分别触发一次。*      例如在Minutes域使用5/20,则意味着从第5分钟到60+5-20:45分范围内,第5分钟开始触发第一次,然后每隔20分钟,即25,45分钟等分别触发一次。*      例如在Seconds域使用8/10,则意味着从第8秒到60+8-10:58秒范围内,第8秒开始触发第一次,然后每隔10秒,即18,28,38,48,58秒等分别触发一次。*      **   对于 *:表示匹配该域的任意值。例如在Minutes域使用*, 即表示每分钟都会触发事件。*   对于问号  ?:只能用在DayofMonth和DayofWeek两个域,其作用为不指定*   对于 -:表示范围。例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次。直接进行拼接*   对于逗号 ,:表示列出枚举值。例如在Minutes域使用5,20 , 则意味着在5和20分每分钟触发一次。*   对于L:表示最后,只能出现在DayofWeek和DayofMonth域。*      如果出现在DayofMonth域,只能使用L,表示当月最后一天*      如果在DayofWeek域*          使用数字(1-7)或L(和7的作用一样表示每周的最后一天周六),比如数字"5"表示每周4, "7"或"L"表示每周六*          使用数字(1-7)结合L,表示当月最后一周的周几,比如"5L" 表示在最后的一周的周四; "3L" 表示最后一周的周二*   对于#: 用于确定每个月第几个星期几,只能出现在DayofMonth域。*      例如 "4#2" 表示某月的第二个星期三(4表示星期三,2表示第二周);*       “6#3”表示本月第三周的星期五(6表示星期五,3表示第三周);*       “2#1”表示本月第一周的星期一;*       “4#5”表示第五周的星期三。** @param cronExp* @param cronTimeArr* @return*/public static String translateToChinese(String cronExp, String[] cronTimeArr) {if (cronExp == null || cronExp.length() < 1) {return "cron表达式为空";}String[] tmpCorns = cronExp.split(" ");StringBuffer sBuffer = new StringBuffer();if (tmpCorns.length == 6 || tmpCorns.length == 7) {if (tmpCorns.length == 7) {//解析年 YearString year = tmpCorns[6];if((!year.equals("*") && !year.equals("?"))){sBuffer.append(year).append(cronTimeArr[6]);}}//解析月 Month 主要解析 /String months = tmpCorns[4];if (!months.equals("*") && !months.equals("?")) {if (months.contains("/")) {sBuffer.append("从").append(months.split("/")[0]).append("号开始").append(",每").append(months.split("/")[1]).append(cronTimeArr[4]);} else {sBuffer.append("每年").append(months).append(cronTimeArr[4]);}}//解析周 DayofWeek  主要解析 , -  1~7/L   1L~7LString dayofWeek = tmpCorns[5];if (!dayofWeek.equals("*") && !dayofWeek.equals("?")) {if (dayofWeek.contains(",")) {// 多个数字,逗号隔开sBuffer.append("每周的第").append(dayofWeek).append(cronTimeArr[3]);} else if (dayofWeek.contains("L") && dayofWeek.length() > NumberUtils.INTEGER_ONE) {// 1L-7LString weekNum = dayofWeek.split("L")[0];String weekName = judgeWeek(weekNum);sBuffer.append("每月的最后一周的");sBuffer.append(weekName);} else if(dayofWeek.contains("-")) {String[] splitWeek = dayofWeek.split("-");String weekOne = judgeWeek(splitWeek[0]);String weekTwo = judgeWeek(splitWeek[1]);sBuffer.append("每周的").append(weekOne).append("到").append(weekTwo);} else { // 1-7/Lif("L".equals(dayofWeek)){ // L 转换为7,便于识别dayofWeek = "7";}int weekNums = Integer.parseInt(dayofWeek);if(weekNums < 0 || weekNums > 7 ){return "cron表达式有误,dayofWeek数字应为1-7";}sBuffer.append("每周的");String weekName = judgeWeek(dayofWeek);sBuffer.append(weekName);}}//解析日 days -- DayofMonth  需要解析的 / # L W//                 *       “6#3”表示本月第三周的星期五(6表示星期五,3表示第三周);//     *       “2#1”表示本月第一周的星期一;//     *       “4#5”表示第五周的星期三。String days = tmpCorns[3];if (!days.equals("?")&& !days.equals("*")) {if (days.contains("/")) {sBuffer.append("每周从第").append(days.split("/")[0]).append("天开始").append(",每").append(days.split("/")[1]).append(cronTimeArr[3]);} else if ("L".equals(days)) { // 处理L 每月的最后一天sBuffer.append("每月最后一天");}  else if ("W".equals(days)) { // 处理W 暂时不懂怎么处理sBuffer.append(days);}  else if (days.contains("#")) {String[] splitDays = days.split("#");String weekNum = splitDays[0]; // 前面数字表示周几String weekOfMonth = splitDays[1]; // 后面的数字表示第几周 范围1-4 一个月最多4周String weekName = judgeWeek(weekNum);sBuffer.append("每月第").append(weekOfMonth).append(cronTimeArr[5]).append(weekName);} else {sBuffer.append("每月第").append(days).append(cronTimeArr[3]);}} else {if (sBuffer.toString().length() == 0 || tmpCorns.length == 7) { // 前面没有内容的话,拼接下sBuffer.append("每").append(cronTimeArr[3]);}}//解析时 Hours 主要解析 /String hours = tmpCorns[2];if (!hours.equals("*")) {if (hours.contains("/")) {//                   sBuffer.append("内,从").append(hours.split("/")[0]).append("时开始").append(",每")//                            .append(hours.split("/")[1]).append(cronTimeArr[2]);sBuffer.append(appendGapInfo(hours, HOURS, 2));} else {if (!(sBuffer.toString().length() > 0)) { // 对于 , 的情况,直接拼接sBuffer.append("每天").append(hours).append(cronTimeArr[2]);} else {sBuffer.append(hours).append(cronTimeArr[2]);}}}//解析分 Minutes 主要解析 /String minutes = tmpCorns[1];if (!minutes.equals("*")) {if (minutes.contains("/")) {//                    sBuffer.append("内,从第").append(minutes.split("/")[0]).append("分开始").append(",每")//                            .append(minutes.split("/")[1]).append(cronTimeArr[1]);sBuffer.append(appendGapInfo(minutes, TIMESCALE, 1));} else if (minutes.equals("0")) {} else if (minutes.contains("-")) {String[] splitMinute = minutes.split("-");sBuffer.append(splitMinute[0]).append(cronTimeArr[1]).append("到").append(splitMinute[1]).append(cronTimeArr[1]).append("每分钟");} else {sBuffer.append(minutes).append(cronTimeArr[1]);}}//解析秒 Seconds 主要解析 /String seconds = tmpCorns[0];if (!seconds.equals("*")) {if (seconds.contains("/")) {//                    sBuffer.append("内,从第").append(seconds.split("/")[0]).append("秒开始").append(",每")//                            .append(seconds.split("/")[0]).append(cronTimeArr[0]);sBuffer.append(appendGapInfo(seconds, TIMESCALE, 0));} else if (!seconds.equals("0")) {sBuffer.append(seconds).append(cronTimeArr[0]);}}if (sBuffer.toString().length() > 0) {sBuffer.append("执行一次");} else {sBuffer.append("表达式中文转换异常");}}return sBuffer.toString();}public static String judgeWeek(String weekNum){String weekName = WeekEnum.matchNameCn(String.valueOf(weekNum));int weekNums = Integer.parseInt(weekNum);if(weekNums < 0 || weekNums > 7 ){return "cron表达式有误,dayofWeek 数字应为1-7";}return StringUtils.isNotEmpty(weekName) ? weekName : String.valueOf(weekNum);}private static String appendGapInfo(String time, int rangeNum, int index){StringBuffer sBufferTemp = new StringBuffer();String[] splitTime = time.split("/");String startNum = splitTime[0];String gapNum = splitTime[1];int endNum = rangeNum + Integer.parseInt(startNum) - Integer.parseInt(gapNum);String endStr = String.valueOf(endNum);String timeUnit = CRON_TIME_CN[index];sBufferTemp.append("从").append(startNum).append(timeUnit).append("开始").append("到").append(endStr).append(timeUnit).append("范围内").append(",每隔").append(gapNum).append(timeUnit);return sBufferTemp.toString();}public static void main(String[] args) {
//        CronExpParserUtil cronExpParserUtil = new CronExpParserUtil();//        0 0 2 1 * ? *   表示在每月的1日的凌晨2点//        String cronExpression =  "0 0 0 * * ? *";String cronExpression =  "3 59 * * * ? *";
//        String cronExpression =  "0 0 6,14,20 * * ? *";System.out.println(cronExpression);System.out.println(CronExpParserUtil.translateToChinese(cronExpression, CRON_TIME_CN) + "--->>");}
}

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

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

相关文章

ReportLab创建合同PDF

一、前言 有一个项目需要将电子签名后的报价合同和生成的发票发送给客户&#xff0c;这种发送给客户的文件一般都是使用PDF格式&#xff0c;主要是因为PDF特别适合阅读且不同平台打开文件格式不会变形&#xff0c;不过要在程序中生成PDF还是比较麻烦的&#xff0c;我们的发票是…

TCP与UDP协议

TCP与UDP协议 1、TCP协议&#xff1a; 1、TCP特性&#xff1a; TCP 提供一种面向连接的、可靠的字节流服务。在一个 TCP 连接中&#xff0c;仅有两方进行彼此通信。广播和多播不能用于 TCP。TCP 使用校验和&#xff0c;确认和重传机制来保证可靠传输。TCP 给数据分节进行排序…

AdaBoost 算法:理解、实现和掌握 AdaBoost

一、介绍 Boosting 是一种集成建模技术&#xff0c;由 Freund 和 Schapire 于 1997 年首次提出。从那时起&#xff0c;Boosting 就成为解决二元分类问题的流行技术。这些算法通过将大量弱学习器转换为强学习器来提高预测能力 。 Boosting 算法背后的原理是&#xff0c;我们首先…

万宾科技智能传感器EN100-C2有什么作用?

在日常生活中井盖是一种常见的城市设施&#xff0c;但井盖出现问题可能会对人们的生活造成什么影响呢&#xff1f;移位或老化的井盖可能会威胁人们的安全&#xff0c;同时也会影响城市生命线的正常运行。然而智能井盖的出现为解决这些问题提供了有效的应对方案。 WITBEE万宾智能…

udp多点通信-广播-组播

单播 每次只有两个实体相互通信&#xff0c;发送端和接收端都是唯一确定的。 广播 主机之间的一对多的通信所有的主机都可以接收到广播消息(不管你是否需要)广播禁止穿过路由器&#xff08;只能做局域网通信&#xff09;只有UDP可以广播广播地址 有效网络号全是1的主机号 192.1…

Pikachu(皮卡丘靶场)初识XSS(常见标签事件及payload总结)

目录 1、反射型xss(get) 2、反射性xss(post) 3、存储型xss 4、DOM型xss 5、DOM型xss-x XSS又叫跨站脚本攻击&#xff0c;是HTML代码注入&#xff0c;通过对网页注入浏览器可执行代码&#xff0c;从而实现攻击。 ​ 1、反射型xss(get) Which NBA player do you like? 由…

nvm安装详细教程(卸载旧的nodejs,安装nvm、node、npm、cnpm、yarn及环境变量配置)

文章目录 一、完全卸载旧的nodejs1、打开系统的控制面板&#xff0c;点击卸载程序&#xff0c;卸载nodejs&#xff08;1&#xff09;打开系统的控制面板&#xff0c;点击程序下的卸载程序&#xff08;2&#xff09;找到node.js&#xff0c;鼠标右击出现下拉框&#xff0c;点卸载…

《Effective C++》条款12

复制对象时勿忘其每一个成分 我们都知道&#xff0c;我们不主动写拷贝构造函数或者赋值重载运算符&#xff0c;那么编译器就会自动生成默认的函数。当我们写时&#xff0c;编译器不会自动生成&#xff0c;它只会找对应我们写的函数&#xff0c;如果此时我们写的函数出现了问题&…

YOLO改进系列之注意力机制(EffectiveSE模型介绍)

模型结构 ESE(Effective Squeeze and Extraction) layer是CenterMask模型中的一个block&#xff0c;基于SE&#xff08;Squeeze and Extraction&#xff09;改进得到。与SE的区别在于&#xff0c;ESE block只有一个fc层&#xff0c;(CenterMask : Real-Time Anchor-Free Insta…

【git】远程远程仓库命令操作详解

这篇文章主要是针对git的命令行操作进行讲解&#xff0c;工具操作的基础也是命令行&#xff0c;如果基本命令操作都不理解&#xff0c;就算是会工具操作&#xff0c;真正遇到问题还是一脸懵逼 如果需要查看本地仓库的详细操作可以看我上篇文件 【git】git本地仓库命令操作详解…

IIC总线概述和通信时序代码详细图文解析

IIC总线 1 IIC总线概述 I2C总线两线制包括&#xff1a;串行数据SDA&#xff08;Serial Data&#xff09;、串行时钟SCL&#xff08;Serial Clock&#xff09;。总线必须由主机&#xff08;通常为微控制器&#xff09;控制&#xff0c;主机产生串行时钟&#xff08;SCL&#x…

【TDSQL-PG数据库简单介绍】

TDSQL-PG数据库简单介绍 TDSQL-PGTDSQL-PG 设计目标 TDSQL-PG 腾讯 TDSQL-PG 分布式关系型数据库是一款面向海量在线实时分布式事务交易和 MPP 实时数据分析 通用型高性能数据库系统。 面对应用业务产生的不定性数据爆炸需求&#xff0c;不管是高并发的交易还是海量的实时数据…

Panda3d 动画序列

动画序列 文章目录 动画序列使用动画序列Lerp动画序列基于 NodePath 的 LerpIntervals 概述一些方便快捷的函数功能其余基于 NodePath 的 LerpIntervals其他类型的 LerpInterval使用 Func 来处理动画序列Actor 动画序列声音动画序列序列和平行运动路径粒子动画序列射弹动画序列…

Linux安装DMETL5与卸载

Linux安装DMETL5与卸载 环境介绍1 DM8数据库配置1.1 DM8数据库安装1.2 初始化达梦数据库1.3 创建DMETL使用的数据库用户 2 配置DMETL52.1 解压DMETL5安装包2.2 安装调度器2.3 安装执行器2.4 安装管理器2.5 启动dmetl5 调度器2.6 启动dmetl5 执行器2.7 启动dmetl5 管理器2.8 查看…

跨境电商与文化多样性:市场中的机遇

在数字时代&#xff0c;跨境电商已经成为全球贸易的主要驱动力之一。随着互联网的普及和物流的改善&#xff0c;企业有机会将产品和服务推向全球市场。 然而&#xff0c;随着全球市场的扩大&#xff0c;文化多样性也成为了一个重要的考虑因素。本文将深入探讨跨境电商与文化多…

【408】计算机学科专业基础 - 操作系统

一、计算机系统概述 1.简介 什么是操作系统&#xff1f; 操作系统&#xff08;Operating Ststem&#xff0c; OS&#xff09;是指控制和管理整个计算机系统的硬件和软件资源&#xff0c;并合理地组织调度计算机的工作和资源的分配&#xff0c;以提供给用户和其他软件方便的接口…

成功解决:文档根元素 “mapper“ 必须匹配 DOCTYPE 根 “null“

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 文章目录 前言错误信息解决方法 前言 错误…

【中间件篇-Redis缓存数据库07】Redis缓存使用问题及互联网运用

Redis缓存使用问题 数据一致性 只要使用到缓存&#xff0c;无论是本地内存做缓存还是使用 redis 做缓存&#xff0c;那么就会存在数据同步的问题。 我以 Tomcat 向 MySQL 中写入和删改数据为例&#xff0c;来给你解释一下&#xff0c;数据的增删改操作具体是如何进行的。 我…

springboot利用redis过期事件处理过期订单

前言 在开发中我们经常会遇到这样的业务需求&#xff0c;某一条数据需要在xxx时间后处理&#xff0c;比如说未支付的订单&#xff0c;30分钟后过期。能够实现这一功能的技术有很多&#xff0c;但需要你根据系统的大小、业务的量的大小以及公司给到该项目的资源而决定。 比如说…

帝国CMS仿核弹头H5小游戏模板/帝国CMS内核仿游戏网整站源码

帝国CMS仿核弹头H5小游戏模板&#xff0c;帝国CMS内核仿游戏网整站源码。比较适合小游戏发布、APP应用资讯类网站使用&#xff0c;有兴趣的可以二次开发试试。 下载地址&#xff1a;https://bbs.csdn.net/topics/617579435