一个简单的定时表达式(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小 ...
随机推荐
- 前端之CSS介绍--选择器
一.CSS简介 介绍 css我们称呼层叠样式表(英文全称:Cascading Style Sheets).它是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等 ...
- python-虎扑爬虫
Python作为一个高级编程语言,不知从何时起就在圈子里流行起来了.个人也是图个鲜,跟上时代步伐学习了一下."鲁迅"说过:不能学以致用,就是耍流氓.我用python对虎扑论坛作了一 ...
- 静态html制作之psd转html
很多时候我们开发拿到的是psd文件,这个时候如果公司有前端,会帮你制作成静态html, 很多小公司是没有这个配置的,所以只能业务开发的自己上马.可以有多种实现方式: 1.对于简单的切图,可以在线网站切 ...
- [one day one question] Vue单页面应用如何保证F5强刷不清空数据
问题描述: Vue单页面用按F5强刷,数据就恢复初始了,这怎么破? 解决方案: store.subscribe((mutation, state) => { sessionStorage.set ...
- 【转】WPF 从FlowDocument中找到Hyperlink
原文地址:How can I get a FlowDocument Hyperlink to launch browser and go to URL in a WPF app? #region Ac ...
- python_斐波那契数列
什么是斐波那契数列? -- 一组第从第三个值开始,每个值都等于前两个值之和的一种有意思的数列 如[1, 1, 2, 3, 5, 8, 13, 21, 34, 55] 如何用程序进行实现? -- 逻辑整 ...
- 转-How to install an SSH Server in Windows Server 2008
window也可以通过ssh客户端连接,具体方式参考下面 1 How to install an SSH Server in Windows Server 2008 2 freeSSHd and fr ...
- linux指令--ls
本篇博客转自http://www.cnblogs.com/peida/archive/2012/10/23/2734829.html,在原作者基础上做了修改和总结. ls命令是linux下最常用的命令 ...
- 禁止img图片拖动在新窗口打开
JS function imgdragstart(){return false;} for(i in document.images)document.images[i].ondragstart=im ...
- 【转】TCHAR
TCHAR 就是当你的字符设置为什么就是什么例如: 当程序编译为 ANSI, TCHAR 相当于 CHAR当程序编译为 UNICODE, TCHAR 相当于WCHAR char ...