一个简单的定时表达式(HH:mm:ss)解析
前言
为客户开发了一个日志监控程序,监听各频道是否正常工作。其中有一个功能是这样的,当所有频道正常运行一段时间后,语音提示值班人员系统运行正常。一开始,想法比较简单,设置了一个变量,在线程不断轮询的过程中去统计连续正常运行的总时长,当达到设置的阀值后,提交一条语音播报任务。后来,客户反馈他们需要定点去值班,顺道查看下软件是否正常,听听语音播报。一沟通,好吧,做个类似于cron表达式那样的定时吧,按照设定的时间规则进行语音播报控制。下面写写我的简单示例,聊以自娱。
一、设置一个定时的配置项
<!-- 系统正常运行定时任务,*:/1:00 表示每小时 每隔1分的时候报-->
<SysNormalLong>*:00:00</SysNormalLong>
- 示例1【 *:00:00 】,*表示每小时都执行,分钟配置成*,则表示每小时都执行。该示例意思是 每小时都整点播报;
- 示例2【 *:/15:00】, /表示配置的是间隔。该示例意思是 每隔15分钟播报一次;
- 示例3【 12:20:00】,这个意思是每天 12:20:00 播报一次;
二、解析定时配置,生成时分秒对应的验证函数
private string _sysNormalLong = @"*:00:00";
/// <summary>
/// 正常播报时分秒
/// </summary>
private string[] _normals; private Func<int, bool>[] _normalFuncs = new Func<int, bool>[]; /// <summary>
/// 单项验证
/// </summary>
/// <param name="val"></param>
/// <returns></returns>
public Func<int,bool> GetValidFunc(string val)
{
if (val == "*") return t=>true;
int temp = ;
if (val.StartsWith("/"))
{
//按间隔播报
if (Int32.TryParse(val.Replace("/", ""), out temp))
{
return t=> (t%temp==);
}
}
else
{
//定点播报
if (Int32.TryParse(val, out temp))
{
return t=>t==temp;
}
}
//解析失败,则按照整点播报的逻辑来做
return t=>t==;
} private SoundWarnThread()
{
……
_normals = _sysNormalLong.Split(':');
_normalFuncs[] = GetValidFunc(_normals[]);
_normalFuncs[] = GetValidFunc(_normals[]);
_normalFuncs[] = GetValidFunc(_normals[]);
_nextNormalTime = GetNextNormalTime(DateTime.Now.AddSeconds());
……
}
主要方法为GetValidFunc。改方法为时分秒每个时间部分都生成一个匿名的判断函数,确保对配置项做一次解析,避免后期在验证过程中不断去分析配置字符串,提升性能。判断逻辑为:1、当配置*,则都验证为true;2、当配置以/开头,则说明配置的是间隔时间,这时从0开始计算,若当前时间是间隔时间的整数倍,则验证为true;3、配置的是纯数字则是固定时间,直接比对是否相等即可。
三、传入一个时间,验证当前时间是否符合定时规则
public bool ValidNormal(DateTime now)
{
//变动快的部分先验证,代码执行速度快
bool bS = _normalFuncs[](now.Second);
if (!bS) return false;
bool bM = _normalFuncs[](now.Minute);
if (!bM) return false;
bool bH = _normalFuncs[](now.Hour);
if (!bH) return false;
return true;
}
四、获取最近一次即将到达的定时时间
/// <summary>
/// 获取下次正常播报的时间
/// </summary>
/// <returns></returns>
public DateTime GetNextNormalTime(DateTime date)
{
while (!ValidNormal(date))
{
date = date.AddSeconds();
}
return date;
}
五、判断某一个时间是否该进行语音播报了(这种方案主要是为了防止线程轮询时执行时间过长,错过定时任务执行时间)
public bool VoiceNormal(DateTime now)
{
if (now >= _nextNormalTime)
{
_nextNormalTime = GetNextNormalTime(now.AddSeconds());
//如果超过1分钟的偏差都没能报出正常运行,则认为软件在这个时间段内捕获到了异常,丢弃这一次的正常运行播报
if (now - _nextNormalTime > TimeSpan.FromMinutes()) return false;
_lastNormalTime = now;
return true;
}
return false;
}
六、定义一个调用线程
#region 线程处理 private Thread _mainThread = null;
public void Start()
{
_mainThread = new Thread(new ThreadStart(MainProcess));
_mainThread.IsBackground = true;
_mainThread.Start();
} /// <summary>
/// 正常运行的提示信息
/// </summary>
private const string _normalMsg = "播出系统日志监听正常"; private DateTime? _nextNormalTime;
/// <summary>
/// 主要的处理逻辑
/// </summary>
private void MainProcess()
{
//1秒读取一次
TimeSpan interval = TimeSpan.FromSeconds();
while (true)
{
if (!WarningQueue.Any())
{
Thread.Sleep(interval);
if (VoiceNormal(DateTime.Now))
{
Voice(_normalMsg);
}
continue;
}
……
}
}
一个简单的定时表达式(HH:mm:ss)解析的更多相关文章
- Java continue break 制作简单聊天室程序,屏蔽不文明语言,显示每句话聊天时间 for(;;) SimpleDateFormat("yyyy-MM-dd hh:mm:ss") equalsIgnoreCase
package com.swift; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Scanne ...
- vue中插值表达式中时间转换yyyy-MM-dd HH:mm:ss
vue插值表达式中将时间转换两种方式:一.定义方法 <div id="app">当前实时时间:{{dateFormat(date)}}</div> //时间 ...
- hh:mm:ss时间格式那些事儿
怎么把hh:mm:ss.45 时间格式换算成秒? 比较简单点的格式,比如hh:mm:ss是比较容易的,但是怎么样把hh:mm:ss.45,这样的格式,就是秒不是整数的时间格式换算成秒? ans:将时间 ...
- 修改springfox-swagger源码,使example中时间格式默认为“yyyy-MM-dd HH:mm:ss”
修改swagger源码,使example中时间格式默认为"yyyy-MM-dd HH:mm:ss" 前言 简单点说,在swagger中,怎么能针对以下vo中的java.util.D ...
- js Date format(日期格式化:yyyy-MM-dd HH:mm:ss.S)
今天在做日期显示的时候,那个显示格式困扰了很久,各种组件都尝试了,总是不如意,最后自己网上找了一个,然后稍微修改一下,感觉这个Util挺常用的,这里mark一下 Date.prototype.form ...
- vue实时显示当前时间且转化为“yyyy-MM-dd hh:mm:ss”格式
在实际运用中时间格式"yyyy-MM-dd hh:mm:ss"用的最多,如果需要其他格式可根据需求自行修改,下面直接上代码: 引入相应的js即可运行 <!DOCTYPE ht ...
- YYYY-mm-dd HH:MM:SS
备忘:YYYY-mm-dd HH:MM:SS部分解释 d 月中的某一天.一位数的日期没有前导零. dd 月中的某一天.一位数的日期有一个前导零 ...
- PHP 日期格式:yyyy-MM-dd'T'HH:mm:ss.SSSZ 的写法
今日在写一个接口是,其中有一个时间参数的格式是 yyyy-MM-dd'T'HH:mm:ss.SSSZ 查了一下最后的SSSZ SSS毫秒 Z代表时区 'T' 就是固定字符T,也有的指的是任意字符,本接 ...
- 日期格式化{0:yyyy-MM-dd HH:mm:ss.fff}和{0:yyyy-MM-dd hh:mm:ss.fff}的区别
原文:日期格式化{0:yyyy-MM-dd HH:mm:ss.fff}和{0:yyyy-MM-dd hh:mm:ss.fff}的区别 {0:yyyy-MM-dd HH:mm:ss.fff}:使用24小 ...
随机推荐
- phthon网络编程
软件开发架构 既然谈起网络编程,就得说说软件开发的架构: c/s架构 C/S结构软件(即客户机/服务器模式)分为客户机和服务器两层,客户机不是毫无运算能力的输入.输出设备,而是具有了一定的数据处理和数 ...
- oracle02
SQL语句完整结构: select from where group by having order by 今天分享的知识点:(1)分组查询 select 中非组函数的列需要在group by 进行参 ...
- (1-1)SpringCloud-Eureka:服务的注册与发现
SpringCloud Eureka是SpringCloud Netflix服务套件中的一部分,它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能.下面来做一个示例 ...
- fopen fclose feof fgets fetl
fopen :Open file, or obtain information about open files 例如 fid = fopen(filename, permission)%许可包括: ...
- 9 C. Hexadecimal's Numbers
题目链接 http://codeforces.com/contest/9/problem/C 题目大意 输入n,计算出n之内只有0和1组成的数字的数量 分析 k从1开始,只要小于n,就给sum++,并 ...
- 13 Basic Cat Command Examples in Linux(转) Linux中cat命令的13中基本用法
Cat (串联) 命令是Linux/Unix开源系统中比较常用的一个命令.我们可以通过Cat命令创建一个或多个文件,查看文件内容,串联文件并将内容输出到终端设备或新的文件当中,这篇文章我们将会以实例的 ...
- js发展历史
1992年Nombas开发和醋C-minus-minus(c--),的嵌入式脚本语言,最初是绑定在Cenvi软件中,后将其改名scriptEase(客户端执行的语言) Netscape 接受Nomba ...
- jupyter扩展插件Nbextensions使用
本节主要解释jupyter中各种插件 原创文章,转载请务必注明原作者出处:http://www.cnblogs.com/cloud-ken/p/7401534.html Exercise Exerci ...
- CORS跨域请求之简单请求与非简单请求
先来看一个例子 定义server01的项目,在路由表中添加一条路由记录 url(r'^getData.html$',views.get_data) 对应的视图函数 from django.shortc ...
- 根据 inotify 自己开发软件监控文件系统活动
了解 inotify Inotify 是一个 Linux 内核特性,它监控文件系统,并且及时向专门的应用程序发出相关的事件警告,比如删除.读.写和卸载操作等.您还可以跟踪活动的源头和目标等细节. 使用 ...