目錄
時間日期工具類DateTimeHelper
功能說明
日期格式化
時間戳轉換
時間間隔計算
日期邊界與調整
時區轉換
日期解析
時間相等性判斷
時間范圍與先后判斷
日期合法性與特殊判斷
截斷時間到指定精度
完整代碼
? ? ?本篇文章分享一下時間日期工具類DateTimeHelper,包含了時間日期的常用操作,使用該類更便捷地完成時間相關的操作。
時間日期工具類DateTimeHelper
功能說明
日期格式化
? ? ? ?提供多種日期字符串轉換方法,包括純數字格式(如20240101)、日志格式(如[yyyy/MM/dd HH:mm:ss])、自定義格式轉換,以及帶星期的日期格式(如2024年01月01日 星期一)。
時間戳轉換
? ? ? ?實現 DateTime 與 Unix 時間戳的雙向轉換,支持秒級和毫秒級精度,包括直接轉換和安全轉換(異常時返回 null)。
時間間隔計算
? ? ? ?計算兩個時間的間隔,支持秒、毫秒、天數(忽略時間部分)和月份差(按自然月計算),結果可為負數。
日期邊界與調整
? ? ? ?獲取指定日期的天 / 月起始與結束時間(如2024-01-01 00:00:00和2024-01-31 23:59:59.999),并支持對日期進行年、月、日、時、分、秒的加減調整。
時區轉換
? ? ? ?提供本地時間與 UTC 時間的雙向轉換,自動處理不同DateTimeKind的時間類型。
日期解析
? ? ? ?支持按指定格式或多個可能格式將字符串轉換為 DateTime,轉換失敗時返回 null。
時間相等性判斷
? ? ? ?可判斷兩個時間是否完全相同(精確到毫秒),或按指定精度(年、月、日等)判斷是否相同,還提供同年、同月、同日的快捷判斷。
時間范圍與先后判斷
? ? ? ?判斷時間是否在指定范圍內(含邊界),比較兩個時間的先后關系(早于、晚于),并返回比較結果(1/-1/0)。
日期合法性與特殊判斷
? ? ? ?驗證日期是否為有效 DateTime 實例,判斷年份是否為閏年,以及指定日期是否為當月第一天或最后一天。
截斷時間到指定精度
? ? ? ?按指定精度(年、月、日、時等)截斷時間,忽略更低精度的部分(如截斷到 “小時” 則分鐘和秒設為 0)。
完整代碼
using System;
using System.Globalization;/// <summary>
/// 日期時間工具類,提供格式化、轉換等常用操作
/// </summary>
public static class DateTimeHelper
{#region 日期格式化/// <summary>/// 日期 僅數字格式(如20240101)/// </summary>public static string DateOnlyNum(DateTime dateTime){return dateTime.ToString("yyyy/MM/dd").Replace("/", "");}/// <summary>/// 格式化日志時間 [yyyy/MM/dd HH:mm:ss]/// </summary>public static string DateLogFormat(DateTime dateTime){return $"[{dateTime:yyyy/MM/dd HH:mm:ss}] ";}/// <summary>/// 根據格式返回日期字符串(默認格式:yyyy/MM/dd HH:mm:ss)/// </summary>/// <param name="dateTime">待格式化的時間</param>/// <param name="format">格式字符串(如"yyyy-MM-dd")</param>/// <returns>格式化后的字符串</returns>public static string GetDateTimeStringByFormat(DateTime dateTime, string format = "yyyy/MM/dd HH:mm:ss"){return dateTime.ToString(format);}/// <summary>/// 將日期轉換為帶星期的格式(如:2024年01月01日 星期一)/// </summary>/// <param name="dateTime">待格式化的日期</param>/// <returns>帶星期的日期字符串</returns>public static string GetDateWithWeek(DateTime dateTime){//中文星期名稱映射(默認CultureInfo為中文時,DayOfWeek對應的值可直接轉換)var weekNames = new[] { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };return $"{dateTime:yyyy年MM月dd日} {weekNames[(int)dateTime.DayOfWeek]}";}#endregion#region 時間戳轉換/// <summary>/// DateTime轉秒級時間戳(Unix時間戳:1970-01-01 00:00:00 UTC起的秒數)/// </summary>public static long DateTimeToTimestampSeconds(DateTime dateTime){DateTime unixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);DateTime targetUtcTime = dateTime.ToUniversalTime();return (long)(targetUtcTime - unixStartTime).TotalSeconds;}/// <summary>/// DateTime轉毫秒級時間戳(Unix時間戳:1970-01-01 00:00:00 UTC起的毫秒數)/// </summary>public static long DateTimeToTimestampMilliseconds(DateTime dateTime){DateTime unixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);DateTime targetUtcTime = dateTime.ToUniversalTime();return (long)(targetUtcTime - unixStartTime).TotalMilliseconds;}/// <summary>/// 秒級時間戳轉DateTime(直接返回本地時間,不處理異常)/// </summary>public static DateTime SecondsTimestampToDateTime(long timestampSeconds){DateTime unixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);return unixStartTime.AddSeconds(timestampSeconds).ToLocalTime();}/// <summary>/// 毫秒級時間戳轉DateTime(直接返回本地時間,不處理異常)/// </summary>public static DateTime MillisecondsTimestampToDateTime(long timestampMilliseconds){DateTime unixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);return unixStartTime.AddMilliseconds(timestampMilliseconds).ToLocalTime();}/// <summary>/// 秒級時間戳轉DateTime(安全轉換,異常時返回null)/// </summary>public static DateTime? SecondsTimestampToDateTimeNull(long seconds){if (seconds <= 0) return null;try{DateTime unixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);return unixStartTime.AddSeconds(seconds).ToLocalTime();}catch (ArgumentOutOfRangeException)//時間戳過大導致溢出{return null;}}/// <summary>/// 毫秒級時間戳轉DateTime(安全轉換,異常時返回null)/// </summary>public static DateTime? MillisecondsTimestampToDateTimeNull(long milliseconds){if (milliseconds <= 0) return null;try{DateTime unixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);return unixStartTime.AddMilliseconds(milliseconds).ToLocalTime();}catch (ArgumentOutOfRangeException)//時間戳過大導致溢出{return null;}}#endregion#region 時間間隔計算/// <summary>/// 獲取兩個時間的間隔秒數(dateTime1 - dateTime2的秒數差,可為負數)/// </summary>public static long GetTimestampSecondsInterval(DateTime dateTime1, DateTime dateTime2){return (long)(dateTime1 - dateTime2).TotalSeconds;}/// <summary>/// 獲取兩個時間的間隔毫秒數(dateTime1 - dateTime2的毫秒數差,可為負數)/// </summary>public static long GetTimestampMillisecondsInterval(DateTime dateTime1, DateTime dateTime2){return (long)(dateTime1 - dateTime2).TotalMilliseconds;}/// <summary>/// 獲取兩個日期之間的總天數(忽略時間部分,dateTime1 - dateTime2的天數差)/// </summary>/// <param name="dateTime1">結束日期</param>/// <param name="dateTime2">開始日期</param>/// <returns>天數差(可為負數)</returns>public static int GetDayInterval(DateTime dateTime1, DateTime dateTime2){//截斷時間部分,僅保留日期DateTime date1 = dateTime1.Date;DateTime date2 = dateTime2.Date;return (int)(date1 - date2).TotalDays;}/// <summary>/// 獲取兩個日期之間的月份差(按自然月計算,如2024-03-01與2024-01-15的差為2)/// </summary>/// <param name="dateTime1">結束日期</param>/// <param name="dateTime2">開始日期</param>/// <returns>月份差(可為負數)</returns>public static int GetMonthInterval(DateTime dateTime1, DateTime dateTime2){int months = (dateTime1.Year - dateTime2.Year) * 12 + dateTime1.Month - dateTime2.Month;//若結束日期的天數小于開始日期,需減1(如2024-02-28與2024-01-31,實際不足1個月)if (dateTime1.Day < dateTime2.Day){months--;}return months;}#endregion#region 日期邊界與調整/// <summary>/// 獲取指定日期所在天的開始時間(如2024-01-01 00:00:00.000)/// </summary>public static DateTime GetDayStart(DateTime dateTime){return new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 0, 0, 0, 0);}/// <summary>/// 獲取指定日期所在天的結束時間(如2024-01-01 23:59:59.999)/// </summary>public static DateTime GetDayEnd(DateTime dateTime){return new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59, 999);}/// <summary>/// 獲取指定日期所在月的開始時間(如2024-01-01 00:00:00.000)/// </summary>public static DateTime GetMonthStart(DateTime dateTime){return new DateTime(dateTime.Year, dateTime.Month, 1, 0, 0, 0, 0);}/// <summary>/// 獲取指定日期所在月的結束時間(如2024-01-31 23:59:59.999)/// </summary>public static DateTime GetMonthEnd(DateTime dateTime){// 獲取當月最后一天(下個月1號減1天)DateTime nextMonthFirstDay = new DateTime(dateTime.Year, dateTime.Month, 1).AddMonths(1);return nextMonthFirstDay.AddDays(-1).AddTicks(-1); //減1 tick確保是當月最后一刻}/// <summary>/// 調整日期(加減年/月/日/時/分/秒)/// </summary>/// <param name="dateTime">原日期</param>/// <param name="years">年數(正數加,負數減)</param>/// <param name="months">月數(正數加,負數減)</param>/// <param name="days">天數(正數加,負數減)</param>/// <param name="hours">小時數(正數加,負數減)</param>/// <param name="minutes">分鐘數(正數加,負數減)</param>/// <param name="seconds">秒數(正數加,負數減)</param>/// <returns>調整后的日期</returns>public static DateTime AddDateTime(DateTime dateTime, int years = 0, int months = 0, int days = 0, int hours = 0, int minutes = 0, int seconds = 0){return dateTime.AddYears(years).AddMonths(months).AddDays(days).AddHours(hours).AddMinutes(minutes).AddSeconds(seconds);}#endregion#region 時區轉換/// <summary>/// 將本地時間轉換為UTC時間/// </summary>/// <param name="localTime">本地時間</param>/// <returns>UTC時間(帶DateTimeKind.Utc標記)</returns>public static DateTime LocalTimeToUtc(DateTime localTime){if (localTime.Kind == DateTimeKind.Utc)//若已是UTC時間,直接返回{return localTime;}return TimeZoneInfo.ConvertTimeToUtc(localTime, TimeZoneInfo.Local);}/// <summary>/// 將UTC時間轉換為本地時間/// </summary>/// <param name="utcTime">UTC時間</param>/// <returns>本地時間(帶DateTimeKind.Local標記)</returns>public static DateTime UtcToLocalTime(DateTime utcTime){if (utcTime.Kind == DateTimeKind.Local)//若已是本地時間,直接返回{return utcTime;}return TimeZoneInfo.ConvertTimeFromUtc(utcTime, TimeZoneInfo.Local);}#endregion#region 日期解析/// <summary>/// 將字符串按指定格式轉換為DateTime(失敗返回null)/// </summary>/// <param name="dateTimeString">日期字符串(如"2024/01/01 12:30:45")</param>/// <param name="format">解析格式(如"yyyy/MM/dd HH:mm:ss")</param>/// <returns>轉換后的DateTime?,失敗返回null</returns>public static DateTime? GetDateTimeByFormat(string dateTimeString, string format = "yyyy/MM/dd HH:mm:ss"){if (string.IsNullOrWhiteSpace(dateTimeString)) return null;//調用單格式重載:TryParseExact(string s, string format, ...)bool success = DateTime.TryParseExact(dateTimeString, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result);if (success) return result;return null;}/// <summary>/// 將字符串按多個可能格式嘗試轉換為DateTime(失敗返回null)/// </summary>/// <param name="dateTimeString">日期字符串(如"20240101"或"2024-01-01")</param>/// <param name="formats">可能的解析格式列表,/// 不填為 "yyyy-MM-dd", "yyyy/MM/dd", "yyyy.MM.dd", "yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss", "yyyyMMdd", "yyyyMMddHHmmss"</param>/// <returns>轉換后的DateTime?,所有格式均失敗則返回null</returns>public static DateTime? GetDateTimeByFormats(string dateTimeString, string[] formats = null){if (string.IsNullOrWhiteSpace(dateTimeString) || formats == null || formats.Length == 0) return null;if (formats == null) formats = new string[] { "yyyy-MM-dd", "yyyy/MM/dd", "yyyy.MM.dd", "yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss", "yyyyMMdd", "yyyyMMddHHmmss" };//調用多格式重載:TryParseExact(string s, string[] formats, ...)bool success = DateTime.TryParseExact(dateTimeString, formats, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result);if (success) return result;return null;}#endregion#region 時間相等性判斷/// <summary>/// 判斷兩個時間是否完全相同(精確到毫秒,基于Ticks值)/// </summary>/// <param name="dateTime1">第一個時間</param>/// <param name="dateTime2">第二個時間</param>/// <returns>true=完全相同;false=不同</returns>public static bool IsSameDateTime(DateTime dateTime1, DateTime dateTime2){//Ticks以100納秒為單位,可精確到毫秒級(1毫秒=10000 Ticks)return dateTime1.Ticks == dateTime2.Ticks;}/// <summary>/// 判斷兩個時間是否相同(可指定比較精度,忽略更低精度部分)/// </summary>/// <param name="dateTime1">第一個時間</param>/// <param name="dateTime2">第二個時間</param>/// <param name="precision">比較精度(如Year/Month/Day等)</param>/// <returns>true=指定精度下相同;false=不同</returns>public static bool IsSameDateTime(DateTime dateTime1, DateTime dateTime2, DateTimePrecision precision){DateTime truncated1 = TruncateDateTime(dateTime1, precision);DateTime truncated2 = TruncateDateTime(dateTime2, precision);return truncated1 == truncated2;}/// <summary>/// 判斷兩個時間是否同年/// </summary>/// <param name="dateTime1">第一個時間</param>/// <param name="dateTime2">第二個時間</param>/// <returns>true=同年;false=不同年</returns>public static bool IsSameYear(DateTime dateTime1, DateTime dateTime2){return dateTime1.Year == dateTime2.Year;}/// <summary>/// 判斷兩個時間是否同月(含同年判斷)/// </summary>/// <param name="dateTime1">第一個時間</param>/// <param name="dateTime2">第二個時間</param>/// <returns>true=同年同月;false=不同</returns>public static bool IsSameMonth(DateTime dateTime1, DateTime dateTime2){return dateTime1.Year == dateTime2.Year && dateTime1.Month == dateTime2.Month;}/// <summary>/// 判斷兩個時間是否同日(含同年同月判斷)/// </summary>/// <param name="dateTime1">第一個時間</param>/// <param name="dateTime2">第二個時間</param>/// <returns>true=同年同月同日;false=不同</returns>public static bool IsSameDay(DateTime dateTime1, DateTime dateTime2){return dateTime1.Year == dateTime2.Year && dateTime1.Month == dateTime2.Month && dateTime1.Date == dateTime2.Date;//Date屬性自動截斷時分秒}#endregion#region 時間范圍與先后判斷/// <summary>/// 判斷日期是否在指定時間范圍內(含邊界值)/// </summary>/// <param name="dateTime">待判斷日期</param>/// <param name="minDateTime">范圍最小值(下界)</param>/// <param name="maxDateTime">范圍最大值(上界)</param>/// <returns>true=在范圍內;false=超出范圍</returns>public static bool DateTimeIsInRange(DateTime dateTime, DateTime minDateTime, DateTime maxDateTime){//先校驗min和max的合法性(避免min > max導致邏輯錯誤)if (minDateTime > maxDateTime){(minDateTime, maxDateTime) = (maxDateTime, minDateTime); //交換值,確保min <= max}return dateTime >= minDateTime && dateTime <= maxDateTime;}/// <summary>/// 判斷dateTime1是否早于dateTime2/// </summary>/// <param name="dateTime1">待比較時間</param>/// <param name="dateTime2">基準時間</param>/// <returns>true=dateTime1早于dateTime2;false=否則</returns>public static bool IsDateTimeBefore(DateTime dateTime1, DateTime dateTime2){return dateTime1 < dateTime2;}/// <summary>/// 判斷dateTime1是否晚于dateTime2/// </summary>/// <param name="dateTime1">待比較時間</param>/// <param name="dateTime2">基準時間</param>/// <returns>true=dateTime1晚于dateTime2;false=否則</returns>public static bool IsDateTimeAfter(DateTime dateTime1, DateTime dateTime2){return dateTime1 > dateTime2;}/// <summary>/// 比較兩個時間的先后關系/// </summary>/// <param name="dateTime1">第一個時間</param>/// <param name="dateTime2">第二個時間</param>/// <returns>1=dateTime1晚于dateTime2;-1=dateTime1早于dateTime2;0=兩者相等</returns>public static int CompareDateTime(DateTime dateTime1, DateTime dateTime2){return DateTime.Compare(dateTime1, dateTime2);}#endregion#region 日期合法性與特殊判斷/// <summary>/// 判斷日期是否為有效DateTime實例(避免極端值)/// </summary>/// <param name="dateTime">待判斷日期</param>/// <returns>true=有效;false=無效(如超出DateTime支持的范圍)</returns>public static bool DateTimeIsValid(DateTime dateTime){//DateTime.MinValue=0001-01-01,MaxValue=9999-12-31,超出此范圍為無效return dateTime >= DateTime.MinValue && dateTime <= DateTime.MaxValue;}/// <summary>/// 判斷指定年份是否為閏年/// </summary>/// <param name="year">年份(如2024)</param>/// <returns>true=閏年;false=平年</returns>public static bool IsLeapYear(int year){//閏年規則:能被4整除且不能被100整除,或能被400整除return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);}/// <summary>/// 判斷指定日期是否為當月第一天/// </summary>/// <param name="dateTime">待判斷日期</param>/// <returns>true=當月第一天;false=否則</returns>public static bool IsFirstDayOfMonth(DateTime dateTime){return dateTime.Day == 1;}/// <summary>/// 判斷指定日期是否為當月最后一天/// </summary>/// <param name="dateTime">待判斷日期</param>/// <returns>true=當月最后一天;false=否則</returns>public static bool IsLastDayOfMonth(DateTime dateTime){//當月最后一天 = 下月第一天減1天DateTime nextMonthFirstDay = new DateTime(dateTime.Year, dateTime.Month, 1).AddMonths(1);DateTime lastDayOfMonth = nextMonthFirstDay.AddDays(-1);return dateTime.Date == lastDayOfMonth.Date;}#endregion#region 截斷時間到指定精度/// <summary>/// 截斷時間到指定精度(忽略更低精度的部分)/// </summary>/// <param name="dateTime">待截斷時間</param>/// <param name="precision">截斷精度</param>/// <returns>截斷后的時間</returns>private static DateTime TruncateDateTime(DateTime dateTime, DateTimePrecision precision){return precision switch{DateTimePrecision.Year => new DateTime(dateTime.Year, 1, 1),DateTimePrecision.Month => new DateTime(dateTime.Year, dateTime.Month, 1),DateTimePrecision.Day => dateTime.Date, //Date屬性直接返回"年-月-日 00:00:00"DateTimePrecision.Hour => new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, 0, 0),DateTimePrecision.Minute => new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, 0),DateTimePrecision.Second => new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second),DateTimePrecision.Millisecond => dateTime, //保留毫秒級精度_ => dateTime //默認返回原時間};}#endregion
}
/// <summary>
/// 時間比較精度枚舉
/// </summary>
public enum DateTimePrecision
{Year, // 年Month, // 月Day, // 日Hour, // 時Minute, // 分Second, // 秒Millisecond // 毫秒
}
? ? ? ?還可以參考Unity、C#常用的時間處理類
? ? ? ?好了,本次的分享到這里就結束啦,希望對你有所幫助~