時間處理是業務系統的高頻需求:顯示「3分鐘前」、計算兩日期相差天數、生日提醒、英文星期轉中文等。本文整理一個静态类 DateTimeHelper,封裝 7 個實用方法,代碼緊湊、邊界處理完善,可直接納入公共庫。
| 方法 | 功能 | 典型場景 |
|---|---|---|
DateStringFromNow | 返回相對時間字符串 (如「2天前」、「1個月前」) | 動態列表、消息流時間顯示 |
DateDiff (重載1) | 兩日期差值,可選返回總天數(含小數)或整天數 | 訂單超時判斷、會員剩餘天數 |
DateDiff (重載2) | 返回「X天Y小時Z分鐘W秒」格式字符串 | 倒計時、運行時長顯示 |
WhichDay | 英文星期名轉中文 (\"Monday\"→\"星期一\") | 日曆組件、日誌本地化 |
CompareDate | 判斷當前日期是否超過指定日期 N 天 | 預發布審核、臨期預警 |
GetBirthdayTip | 根據出生日期返回提示 (「今天」、「本月15號」、「下月3號」...) | 會員生日營銷、HR 生日提醒 |
public static class DateTimeHelper {
// 1. 相對時間
public static string DateStringFromNow(DateTime dt) {
TimeSpan span = DateTime.Now - dt;
if (span.TotalDays > 60) return dt.ToShortDateString();
if (span.TotalDays > 30) return "1個月前";
if (span.TotalDays > 14) return "2周前";
if (span.TotalDays > 7) return "1周前";
if (span.TotalDays > 1) return $"{(int)Math.Floor(span.TotalDays)}天前";
if (span.TotalHours > 1) return $"{(int)Math.Floor(span.TotalHours)}小時前";
if (span.TotalMinutes > 1) return $"{(int)Math.Floor(span.TotalMinutes)}分鐘前";
if (span.TotalSeconds >= 1) return $"{(int)Math.Floor(span.TotalSeconds)}秒前";
return "1秒前";
}
// 2. 日期差值 (總天數/整天數)
public static string DateDiff(DateTime dt1, DateTime dt2, bool isTotal) {
TimeSpan ts = dt2 - dt1;
return isTotal ? ts.TotalDays.ToString() : ts.Days.ToString();
}
// 3. 詳細差值字符串
public static string DateDiff(DateTime dt1, DateTime dt2) {
TimeSpan ts = new TimeSpan(dt1.Ticks).Subtract(new TimeSpan(dt2.Ticks)).Duration();
return $"{ts.Days}天{ts.Hours}小時{ts.Minutes}分鐘{ts.Seconds}秒";
}
// 4. 英文星期轉中文
public static string WhichDay(string enWeek) {
return enWeek.Trim() switch {
"Sunday" => "星期日", "Monday" => "星期一", "Tuesday" => "星期二",
"Wednesday" => "星期三", "Thursday" => "星期四", "Friday" => "星期五",
"Saturday" => "星期六", _ => enWeek
};
}
// 5. 日期比較 (當前是否 >= 目標日期+N天)
public static bool CompareDate(string today, string writeDate, int n) {
DateTime t = Convert.ToDateTime(today);
DateTime w = Convert.ToDateTime(writeDate).AddDays(n);
return t < w; // 未超過返回 true
}
// 6. 生日提醒
public static string GetBirthdayTip(DateTime birthday) {
DateTime now = DateTime.Now;
int nowM = now.Month, birM = birthday.Month;
// 跨年邊界處理
if (nowM == 12 && birM == 1) return $"下月{birthday.Day}號";
if (nowM == 1 && birM == 12) return $"上月{birthday.Day}號";
int diffM = nowM - birM;
if (diffM == 1) return $"上月{birthday.Day}號";
if (diffM == -1) return $"下月{birthday.Day}號";
if (diffM == 0) {
if (now.Day == birthday.Day) return "今天";
return $"本月{birthday.Day}號";
}
if (diffM > 1) return $"已過{diffM}月";
return $"{birM}月{birthday.Day}日";
}
}
// 動態流時間
var postTime = DateTime.Now.AddHours(-3);
lblTime.Text = DateTimeHelper.DateStringFromNow(postTime); // "3小時前"
// 會員剩餘天數
string daysLeft = DateTimeHelper.DateDiff(DateTime.Now, vip.ExpireDate, false); // 整天數
// 活動倒計時
string countdown = DateTimeHelper.DateDiff(DateTime.Now, act.EndTime); // "2天5小時30分鐘10秒"
// 星期本地化
string cnWeek = DateTimeHelper.WhichDay(DateTime.Now.DayOfWeek.ToString()); // "星期三"
// 生日營銷短信
string tip = DateTimeHelper.GetBirthdayTip(user.BirthDate); // "下月5號"
SendSms($"親,{tip}就是您的生日啦,提前祝壽!");
AddDays、AddMonths 已正確處理,但手動計算月份差 (如 now.Month - birth.Month) 跨年會出錯,代碼中已通過 12↔1 判斷修正。DateTime.Now 減少系統調用。WhichDay 可改用 CultureInfo.CurrentCulture.DateTimeFormat.GetDayName 獲取系統當前語言的星期名,避免硬編碼。將 DateTimeHelper 引入項目,即可在 Controller、ViewModel、Service 中一行代碼解決 90% 時間顯示需求。