一个简单的定时表达式(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小 ...
随机推荐
- Java数据持久层框架 MyBatis之背景知识二
对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...
- Django之Model组件
Model组件在django基础篇就已经提到过了,本章介绍更多高级部分. 一.回顾 1.定义表(类) ##单表 from django.db import models class user(mode ...
- python基础7之python3的内置函数
官方介绍: python3:https://docs.python.org/3/library/functions.html?highlight=built#ascii python2:https:/ ...
- 安装新的int 9中断例程2
body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...
- 移动端 iphone锁屏文字效果
简易的仿照iphone 效果 笔记备份 <!DOCTYPE HTML> <html> <head> <meta http-equiv="Conten ...
- [搬运] .NET Core 2.1中改进的堆栈信息
原文 : Stacktrace improvements in .NET Core 2.1 作者 : Ben Adams 译者 : 张很水 . NET Core 2.1 现在具有可读的异步堆栈信息!使 ...
- 腾讯工程师教你玩转 RocksDB
欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:腾讯云数据库内核团队 原文标题:[腾讯云CDB]教你玩转MyRocks/RocksDB-STATISTICS与后台线程篇 0. Intro ...
- node 在控制台打印有色彩的输出
在学习 node 过程中,因为没有找到有断点的调试方法,只能退而次之,在控制台打印调试. 但整个控制台的输出都是一种颜色,有时候很难找到自己需要的信息,这时,有颜色的打印就会帮上很大的忙. conso ...
- jQuery的标签选择器$('p')、类选择器$('.myClass')、id选择器$('#myId')
$()可以是$(expresion),即css选择器 $("a")构造的这个对象,是用CSS选择器构建了一个jQuery对象——它选择了所有的<a/>这个标签 $(&q ...
- PHP如何读取json数据
1的 <?php $json = '{"a":1,"b":2,"c":3,"d":4,"e": ...