284 lines
9.3 KiB
C#
284 lines
9.3 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
|
||
namespace CoreCms.Net.Utility.Helper
|
||
{
|
||
/// <summary>
|
||
/// 时段工具类
|
||
/// </summary>
|
||
public static class TimeSlotHelper
|
||
{
|
||
#region 时段常量定义
|
||
|
||
/// <summary>
|
||
/// 凌晨时段
|
||
/// </summary>
|
||
public const int DAWN = 0;
|
||
|
||
/// <summary>
|
||
/// 上午时段
|
||
/// </summary>
|
||
public const int MORNING = 1;
|
||
|
||
/// <summary>
|
||
/// 下午时段
|
||
/// </summary>
|
||
public const int AFTERNOON = 2;
|
||
|
||
/// <summary>
|
||
/// 晚上时段
|
||
/// </summary>
|
||
public const int EVENING = 3;
|
||
|
||
#endregion
|
||
|
||
#region 时段时间范围
|
||
|
||
/// <summary>
|
||
/// 时段开始小时配置
|
||
/// </summary>
|
||
private static readonly Dictionary<int, int> SlotStartHours = new Dictionary<int, int>
|
||
{
|
||
{ DAWN, 0 }, // 凌晨 00:00
|
||
{ MORNING, 6 }, // 上午 06:00
|
||
{ AFTERNOON, 12 }, // 下午 12:00
|
||
{ EVENING, 18 } // 晚上 18:00
|
||
};
|
||
|
||
/// <summary>
|
||
/// 时段结束小时配置(23点59分需要特殊处理)
|
||
/// </summary>
|
||
private static readonly Dictionary<int, int> SlotEndHours = new Dictionary<int, int>
|
||
{
|
||
{ DAWN, 5 }, // 凌晨 05:59
|
||
{ MORNING, 11 }, // 上午 11:59
|
||
{ AFTERNOON, 17 }, // 下午 17:59
|
||
{ EVENING, 23 } // 晚上 23:59
|
||
};
|
||
|
||
/// <summary>
|
||
/// 时段名称配置
|
||
/// </summary>
|
||
private static readonly Dictionary<int, string> SlotNames = new Dictionary<int, string>
|
||
{
|
||
{ DAWN, "凌晨" },
|
||
{ MORNING, "上午" },
|
||
{ AFTERNOON, "下午" },
|
||
{ EVENING, "晚上" }
|
||
};
|
||
|
||
#endregion
|
||
|
||
#region 公共方法
|
||
|
||
/// <summary>
|
||
/// 根据时间获取时段类型
|
||
/// </summary>
|
||
/// <param name="time">时间</param>
|
||
/// <returns>时段类型:0=凌晨,1=上午,2=下午,3=晚上</returns>
|
||
public static int GetTimeSlotType(DateTime time)
|
||
{
|
||
int hour = time.Hour;
|
||
|
||
if (hour >= 0 && hour < 6)
|
||
return DAWN;
|
||
else if (hour >= 6 && hour < 12)
|
||
return MORNING;
|
||
else if (hour >= 12 && hour < 18)
|
||
return AFTERNOON;
|
||
else
|
||
return EVENING;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据时段类型获取时段名称
|
||
/// </summary>
|
||
/// <param name="timeSlotType">时段类型</param>
|
||
/// <returns>时段名称</returns>
|
||
public static string GetTimeSlotName(int timeSlotType)
|
||
{
|
||
return SlotNames.ContainsKey(timeSlotType) ? SlotNames[timeSlotType] : "未知时段";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取时段的起止时间
|
||
/// </summary>
|
||
/// <param name="date">日期</param>
|
||
/// <param name="timeSlotType">时段类型</param>
|
||
/// <returns>起止时间元组 (开始时间, 结束时间)</returns>
|
||
public static (DateTime startTime, DateTime endTime) GetTimeRange(DateTime date, int timeSlotType)
|
||
{
|
||
if (!SlotStartHours.ContainsKey(timeSlotType))
|
||
{
|
||
throw new ArgumentException($"无效的时段类型:{timeSlotType}");
|
||
}
|
||
|
||
// 使用日期的Date部分,确保从00:00:00开始
|
||
var dayStart = date.Date;
|
||
|
||
// 计算开始时间
|
||
var startHour = SlotStartHours[timeSlotType];
|
||
var startTime = dayStart.AddHours(startHour);
|
||
|
||
// 计算结束时间(设置为该时段最后一分钟的最后一秒)
|
||
var endHour = SlotEndHours[timeSlotType];
|
||
var endTime = dayStart.AddHours(endHour).AddMinutes(59).AddSeconds(59);
|
||
|
||
return (startTime, endTime);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取时段的起止时间(返回分离的开始和结束时间)
|
||
/// </summary>
|
||
/// <param name="date">日期</param>
|
||
/// <param name="timeSlotType">时段类型</param>
|
||
/// <param name="startTime">输出参数:开始时间</param>
|
||
/// <param name="endTime">输出参数:结束时间</param>
|
||
public static void GetTimeRange(DateTime date, int timeSlotType, out DateTime startTime, out DateTime endTime)
|
||
{
|
||
var range = GetTimeRange(date, timeSlotType);
|
||
startTime = range.startTime;
|
||
endTime = range.endTime;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 校验时间是否在指定时段内
|
||
/// </summary>
|
||
/// <param name="time">要校验的时间</param>
|
||
/// <param name="timeSlotType">时段类型</param>
|
||
/// <returns>是否在时段内</returns>
|
||
public static bool ValidateTimeSlot(DateTime time, int timeSlotType)
|
||
{
|
||
var (startTime, endTime) = GetTimeRange(time.Date, timeSlotType);
|
||
return time >= startTime && time <= endTime;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有时段类型列表
|
||
/// </summary>
|
||
/// <returns>时段类型列表</returns>
|
||
public static List<int> GetAllTimeSlotTypes()
|
||
{
|
||
return new List<int> { DAWN, MORNING, AFTERNOON, EVENING };
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有时段信息(类型和名称)
|
||
/// </summary>
|
||
/// <returns>时段信息字典</returns>
|
||
public static Dictionary<int, string> GetAllTimeSlots()
|
||
{
|
||
return new Dictionary<int, string>(SlotNames);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断时段类型是否有效
|
||
/// </summary>
|
||
/// <param name="timeSlotType">时段类型</param>
|
||
/// <returns>是否有效</returns>
|
||
public static bool IsValidTimeSlotType(int timeSlotType)
|
||
{
|
||
return timeSlotType >= DAWN && timeSlotType <= EVENING;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取时段的时间范围描述
|
||
/// </summary>
|
||
/// <param name="timeSlotType">时段类型</param>
|
||
/// <returns>时间范围描述,如"00:00-05:59"</returns>
|
||
public static string GetTimeRangeDescription(int timeSlotType)
|
||
{
|
||
if (!SlotStartHours.ContainsKey(timeSlotType))
|
||
{
|
||
return "未知时段";
|
||
}
|
||
|
||
var startHour = SlotStartHours[timeSlotType];
|
||
var endHour = SlotEndHours[timeSlotType];
|
||
|
||
return $"{startHour:D2}:00-{endHour:D2}:59";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取完整的时段描述
|
||
/// </summary>
|
||
/// <param name="timeSlotType">时段类型</param>
|
||
/// <returns>完整描述,如"凌晨(00:00-05:59)"</returns>
|
||
public static string GetFullTimeSlotDescription(int timeSlotType)
|
||
{
|
||
var name = GetTimeSlotName(timeSlotType);
|
||
var range = GetTimeRangeDescription(timeSlotType);
|
||
return $"{name}({range})";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查两个时段是否有重叠
|
||
/// </summary>
|
||
/// <param name="date">日期</param>
|
||
/// <param name="slot1">时段1</param>
|
||
/// <param name="slot2">时段2</param>
|
||
/// <returns>是否重叠</returns>
|
||
public static bool IsTimeSlotOverlap(DateTime date, int slot1, int slot2)
|
||
{
|
||
// 同一时段必然重叠
|
||
if (slot1 == slot2)
|
||
return true;
|
||
|
||
var (start1, end1) = GetTimeRange(date, slot1);
|
||
var (start2, end2) = GetTimeRange(date, slot2);
|
||
|
||
// 判断时间段是否重叠
|
||
return start1 < end2 && start2 < end1;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前时段类型
|
||
/// </summary>
|
||
/// <returns>当前时段类型</returns>
|
||
public static int GetCurrentTimeSlotType()
|
||
{
|
||
return GetTimeSlotType(DateTime.Now);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断指定时段是否已过去
|
||
/// </summary>
|
||
/// <param name="date">日期</param>
|
||
/// <param name="timeSlotType">时段类型</param>
|
||
/// <returns>是否已过去</returns>
|
||
public static bool IsTimeSlotPassed(DateTime date, int timeSlotType)
|
||
{
|
||
var (startTime, endTime) = GetTimeRange(date, timeSlotType);
|
||
return DateTime.Now > endTime;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断指定时段是否正在进行中
|
||
/// </summary>
|
||
/// <param name="date">日期</param>
|
||
/// <param name="timeSlotType">时段类型</param>
|
||
/// <returns>是否正在进行中</returns>
|
||
public static bool IsTimeSlotCurrent(DateTime date, int timeSlotType)
|
||
{
|
||
var (startTime, endTime) = GetTimeRange(date, timeSlotType);
|
||
var now = DateTime.Now;
|
||
return now >= startTime && now <= endTime;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断指定时段是否在未来
|
||
/// </summary>
|
||
/// <param name="date">日期</param>
|
||
/// <param name="timeSlotType">时段类型</param>
|
||
/// <returns>是否在未来</returns>
|
||
public static bool IsTimeSlotFuture(DateTime date, int timeSlotType)
|
||
{
|
||
var (startTime, endTime) = GetTimeRange(date, timeSlotType);
|
||
return DateTime.Now < startTime;
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|
||
|