一、实现效果
1.1、实现功能
①获取到两个时间的差值;
②获取到指定时间的间隔;
③可以启用多个定时器定时分别执行不同的任务;
1.2、效果图
二、实现核心 2.1、TimeSpan介绍TimeSpan的官方文档说明https://docs.microsoft.com/zh-cn/dotnet/api/system.timespan?view=net-6.0 TimeSpan表示一个时间间隔,可以用来表示指定的天数、小时、分钟、秒和毫秒(或指定日期等效的总天数、总小时、总分钟、总秒、总毫秒数).
| 序号 | TimeSpan的属性 | 说明 |
| 1 | Days | 表示指定时间间隔的天数部分 |
| 2 | Hours | 表示指定时间间隔的小时部分 |
| 3 | Minutes | 表示指定时间间隔的分钟部分 |
| 4 | Seconds | 表示指定时间间隔的秒数部分 |
| 5 | Milliseconds | 表示指定时间间隔的毫秒部分 |
| 6 | Ticks | DateTime.Tick刻度是最小的时间单位;表示计算机的一个计时周期,单位是一百纳秒,1毫秒=10000刻度;1秒=1000毫秒=10000000刻度; |
| 7 | TotalDays | 表示时间转为等效的整天和小数天 |
| 8 | TotalHours | 表示时间转为等效的整小时和小数小时 |
| 9 | TotalMinutes | 表示时间转为等效的整分钟和小数分钟 |
| 10 | TotalSeconds | 表示时间转为等效的整秒和小数秒 |
| 11 | TotalMilliseconds | 表示时间转为等效的整毫秒和小数毫秒 |
| 序号 | TimeSpan的方法 | 说明 |
| 1 | Add(TimeSpan) | 返回该TimeSpan实例与指定TimeSpan相加后的新TimeSpan对象 |
| 2 | Compare(TimeSpan, TimeSpan) | 比较两个TimeSpan的值,结果为第一个值小于、等于、大于第二个值的一个整数 |
| 3 | CompareTo(Object) | 将此TimeSpan实例与指定对象比较,结果为第一个值小于、等于、大于第二个值的一个整数 |
| 4 | CompareTo(TimeSpan) | 将此TimeSpan实例与指定TimeSpan比较,结果为第一个值小于、等于、大于第二个值的一个整数 |
| 5 | Divide(Double) | 返回该TimeSpan实例与指定值相除后的新TimeSpan对象 |
| 6 | Divide(TimeSpan) | 返回该TimeSpan实例与指定TimeSpan相除后的新TimeSpan对象 |
| 7 | Duration() | 返回当前TimeSpan实例的绝对值 |
| 8 | Equals(Object) | 比较当前的TimeSpan实例是否等于指定的对象 |
| 9 | Equals(TimeSpan) | 比较当前的TimeSpan实例是否等于指定的TimeSpan |
| 10 | Equals(TimeSpan, TimeSpan) | 比较两个TimeSpan实例是否相等 |
| 11 | Parse(String) | 将时间间隔的字符串表示形式转换为等效的TimeSpan |
using System;
using System.Collections.Generic;
using System.Text;
namespace Utils
{
public class TimeSpanHelper
{
///
/// 获取两个日期的时间间隔
///
/// 开始时间
/// 结束时间
/// 返回两个时间的时间间隔
public static TimeSpan GetTwoDateTimeInterval(DateTime startTime,DateTime endTime)
{
TimeSpan timeSpan = endTime - startTime;
return timeSpan;
}
///
/// 获取到指定百纳秒(一百纳秒=一千万分之一秒)的时间间隔
///
/// 百纳秒(单位是:一百纳秒)
///
public static TimeSpan GetTimeInterval(long ticks)
{
TimeSpan ts = new TimeSpan(ticks);
return ts;
}
///
/// 获取到指定间隔的天数
///
/// 间隔的天数
///
public static TimeSpan GetDaysInterval(int intervalDay)
{
TimeSpan ts = new TimeSpan(intervalDay, 0, 0, 0);
return ts;
}
///
/// 获取到指定间隔的小时数
///
/// 间隔的小时数
///
public static TimeSpan GetHoursInterval(int intervalHour)
{
TimeSpan ts = new TimeSpan(0, intervalHour, 0, 0);
return ts;
}
///
/// 获取到指定间隔的分钟数
///
/// 间隔的分钟数
///
public static TimeSpan GetMinutesInterval(int intervalMinute)
{
TimeSpan ts = new TimeSpan(0, 0, intervalMinute, 0);
return ts;
}
///
/// 获取到指定间隔的秒数
///
/// 间隔的秒数
///
public static TimeSpan GetSecondsInterval(int intervalSecond)
{
TimeSpan ts = new TimeSpan(0, 0, 0, intervalSecond);
return ts;
}
///
/// 获取到指定间隔的毫秒数
///
/// 间隔的毫秒数
///
public static TimeSpan GetMillisecondsInterval(int intervalMillisecond)
{
TimeSpan ts = new TimeSpan(0, 0, 0, 0,intervalMillisecond);
return ts;
}
///
/// 获取到指定小时、分钟、秒数的时间间隔
///
/// 小时
/// 分钟
/// 秒数
///
public static TimeSpan GetTimeInterval(int hours, int minutes, int seconds)
{
TimeSpan ts = new TimeSpan(hours,minutes,seconds);
return ts;
}
///
/// 获取到指定天、小时、分钟、秒数的时间间隔
///
/// 天
/// 小时
/// 分钟
/// 秒数
///
public static TimeSpan GetTimeInterval(int days, int hours, int minutes, int seconds)
{
TimeSpan ts = new TimeSpan(days,hours, minutes, seconds);
return ts;
}
///
/// 获取到指定天、小时、分钟、秒数、毫秒的时间间隔
///
/// 天
/// 小时
/// 分钟
/// 秒数
/// 毫秒
///
public static TimeSpan GetTimeInterval(int days, int hours, int minutes, int seconds, int milliseconds)
{
TimeSpan ts = new TimeSpan(days, hours, minutes, seconds,milliseconds);
return ts;
}
}//Class_end
}
三、使用方法
3.1、引用命名空间
在项目中引用如下命名空间:
using Utils;3.2、使用示例
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Utils;
using Timer = System.Threading.Timer;
namespace Test_TimeSpan
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
#region 两个时间的差值
DateTime startTime =new DateTime(2022, 05, 11, 09, 59, 36);
DateTime endTime = new DateTime(2022, 06, 01, 00, 00, 00);
Console.WriteLine($"开始时间:{startTime} 结束时间:{endTime}");
TimeSpan ts = TimeSpanHelper.GetTwoDateTimeInterval(startTime,endTime);
Console.WriteLine($"相差间隔:{ts}");
Console.WriteLine($"相差天:{ts.Days} 相差小时:{ts.Hours} 相差分钟:{ts.Minutes} 相差秒:{ts.Seconds} 相差毫秒:{ts.Milliseconds} 相差的百纳秒:{ts.Ticks}");
Console.WriteLine($"rn相差总天:{ts.TotalDays} 相差总小时:{ts.TotalHours} 相差总分钟:{ts.TotalMinutes} 相差总秒:{ts.TotalSeconds} 相差总毫秒:{ts.TotalMilliseconds} 相差的百纳秒:{ts.Ticks}");
#endregion
#region 指定时间间隔
Console.WriteLine($"rn当前间隔100 毫秒");
//指定间隔100毫秒
TimeSpan MillisecondsInterval = TimeSpanHelper.GetTimeInterval(0,0,0,0,100);
TimeSpan MillisecondsInterval2 = TimeSpanHelper.GetMillisecondsInterval(100);
Console.WriteLine($"时间间隔: {MillisecondsInterval} 间隔毫秒:{MillisecondsInterval.Milliseconds} 间隔总毫秒:{MillisecondsInterval.TotalMilliseconds}");
Console.WriteLine($"时间间隔2:{MillisecondsInterval2} 间隔毫秒:{MillisecondsInterval2.Milliseconds} 间隔总毫秒:{MillisecondsInterval2.TotalMilliseconds}");
Console.WriteLine($"rn当前间隔30 秒");
//指定间隔30秒
TimeSpan secondsInterval = TimeSpanHelper.GetTimeInterval(0, 0, 30);
TimeSpan secondsInterval2 = TimeSpanHelper.GetSecondsInterval(30);
Console.WriteLine($"时间间隔: {secondsInterval} 间隔秒:{secondsInterval.Seconds} 间隔总秒数:{secondsInterval.TotalSeconds}");
Console.WriteLine($"时间间隔2:{secondsInterval2} 间隔秒2:{secondsInterval.Seconds} 间隔总秒数2:{secondsInterval.TotalSeconds}");
Console.WriteLine($"rn当前间隔30 分钟");
//指定间隔30分钟
TimeSpan minutesInterval = TimeSpanHelper.GetTimeInterval(0, 30, 0);
TimeSpan minutesInterval2 = TimeSpanHelper.GetMinutesInterval(30);
Console.WriteLine($"时间间隔: {minutesInterval} 间隔分:{minutesInterval.Minutes} 间隔总分钟:{minutesInterval.TotalMinutes}");
Console.WriteLine($"时间间隔2:{minutesInterval2} 间隔分:{minutesInterval2.Minutes} 间隔总分钟:{minutesInterval2.TotalMinutes}");
Console.WriteLine($"rn当前间隔15 天");
//指定间隔15天
TimeSpan daysInterval = TimeSpanHelper.GetTimeInterval(15,0, 0, 0);
TimeSpan daysInterval2 = TimeSpanHelper.GetDaysInterval(15);
Console.WriteLine($"时间间隔: {daysInterval} 间隔天:{daysInterval.Days} 间隔总天数:{daysInterval.TotalDays}");
Console.WriteLine($"时间间隔2:{daysInterval2} 间隔天:{daysInterval2.Days} 间隔总天数:{daysInterval2.TotalDays}");
#endregion
#region 定时器
int inputSeconds = 5;
try
{
Console.WriteLine("请输入定时器的间隔时间(单位:秒)");
int.TryParse(Console.ReadLine(), out inputSeconds);
}
catch (Exception)
{
inputSeconds = 5;
}
List listContainsMinInterval = new List();
for (int i = 0; i < 3; i++)
{
DeviceOpcAddress deviceOpcAddress = new DeviceOpcAddress();
deviceOpcAddress.DeviceId = $"C2_01_0{i}";
deviceOpcAddress.DeviceName = $"0{i}设备";
deviceOpcAddress.RefreshInterval = inputSeconds.ToString();
listContainsMinInterval.Add(deviceOpcAddress);
}
StartNewTimer(listContainsMinInterval, DataCollection);
#endregion
Console.ReadLine();
}
#region 定时器
//实例化定时器
private static ConcurrentDictionary _timers = new ConcurrentDictionary();
//给列表中的内容都开启定时器定时执行业务
private static void StartNewTimer(List deviceOpcAddresses, TimerCallback callback)
{
foreach (var item in deviceOpcAddresses)
{
int seconds = 0;
if (!string.IsNullOrEmpty(item.RefreshInterval))
{
seconds = int.Parse(item.RefreshInterval.Trim());
}
Console.WriteLine($"{nameof(StartNewTimer)} 调用定时任务{callback.Method.Name}, 设备地址数量{deviceOpcAddresses.Count()}");
var timer = new Timer(callback, item, TimeSpanHelper.GetSecondsInterval(seconds), Timeout.InfiniteTimeSpan);
_timers.TryAdd(item, timer);
}
}
private static void DataCollection(object state)
{
var model = (DeviceOpcAddress)state;
try
{
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} 设备:{model.DeviceName} 执行数据采集");
}
catch (Exception exception)
{
Console.WriteLine($"数据采集出错:{DateTime.Now.ToLongTimeString()}_{exception.Message}");
}
int seconds = 0;
if (!string.IsNullOrEmpty(model.RefreshInterval))
{
seconds = int.Parse(model.RefreshInterval.Trim());
}
_timers[model].Change(TimeSpanHelper.GetSecondsInterval(seconds), Timeout.InfiniteTimeSpan);
}
///
/// 设备的OPC地址实体模型
///
public class DeviceOpcAddress
{
public string DeviceId { get; set; }
public string DeviceName { get; set; }
public string RefreshInterval { get; set; }
public string DeviceAddress { get; set; }
}
#endregion
}//Class_end
}



