using Common.ExpandFun;
namespace Common.Test;
///
/// DateTimeExpand 日期时间扩展测试
/// 展示日期格式化、时间戳转换、时区转换、日期计算等功能
///
[TestClass]
public class DateTimeExpandTests
{
#region 日期格式化测试
///
/// 测试:中文日期格式化
///
[TestMethod]
public void ToChineseDateString_FormatsCorrectly()
{
// Arrange
var dt = new DateTime(2024, 1, 15);
// Act
var result = dt.ToChineseDateString();
// Assert
Assert.AreEqual("2024年01月15日", result);
}
///
/// 测试:中文日期时间格式化
///
[TestMethod]
public void ToChineseDateTimeString_FormatsCorrectly()
{
// Arrange
var dt = new DateTime(2024, 1, 15, 14, 30, 45);
// Act
var result = dt.ToChineseDateTimeString();
// Assert
Assert.AreEqual("2024年01月15日 14:30:45", result);
}
///
/// 测试:友好的相对时间字符串
///
[TestMethod]
public void ToFriendlyString_ReturnsCorrectString()
{
// 测试"刚刚"
var justNow = DateTime.Now.AddSeconds(-30);
Assert.AreEqual("刚刚", justNow.ToFriendlyString());
// 测试"分钟前"
var minutesAgo = DateTime.Now.AddMinutes(-5);
Assert.AreEqual("5分钟前", minutesAgo.ToFriendlyString());
// 测试"小时前"
var hoursAgo = DateTime.Now.AddHours(-3);
Assert.AreEqual("3小时前", hoursAgo.ToFriendlyString());
// 测试"昨天"
var yesterday = DateTime.Now.AddDays(-1);
Assert.AreEqual("昨天", yesterday.ToFriendlyString());
}
///
/// 测试:ISO 8601 格式化
///
[TestMethod]
public void ToIso8601String_FormatsCorrectly()
{
// Arrange
var dt = new DateTime(2024, 1, 15, 12, 30, 45, 123, DateTimeKind.Utc);
// Act
var result = dt.ToIso8601String();
// Assert
Assert.AreEqual("2024-01-15T12:30:45.123Z", result);
}
///
/// 测试:标准日期格式化
///
[TestMethod]
public void ToDateString_FormatsCorrectly()
{
// Arrange
var dt = new DateTime(2024, 3, 5);
// Act
var result = dt.ToDateString();
// Assert
Assert.AreEqual("2024-03-05", result);
}
#endregion
#region 时间戳转换测试
///
/// 测试:转换为 Unix 时间戳(秒)
///
[TestMethod]
public void ToUnixTimeSeconds_ConvertsCorrectly()
{
// Arrange
var dt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc);
// Act
var timestamp = dt.ToUnixTimeSeconds();
// Assert
Assert.AreEqual(1704067200, timestamp);
}
///
/// 测试:从 Unix 时间戳创建 DateTime
///
[TestMethod]
public void FromUnixTimeSeconds_CreatesCorrectDateTime()
{
// Arrange
long timestamp = 1704067200; // 2024-01-01 00:00:00 UTC
// Act
var dt = DateTimeExpand.FromUnixTimeSeconds(timestamp);
// Assert
Assert.AreEqual(2024, dt.Year);
Assert.AreEqual(1, dt.Month);
Assert.AreEqual(1, dt.Day);
}
///
/// 测试:时间戳往返转换
///
[TestMethod]
public void UnixTimestamp_RoundTrip_MaintainsValue()
{
// Arrange
var original = new DateTime(2024, 6, 15, 12, 30, 45, DateTimeKind.Utc);
// Act
var timestamp = original.ToUnixTimeSeconds();
var restored = DateTimeExpand.FromUnixTimeSeconds(timestamp);
// Assert: 精确到秒
Assert.AreEqual(original.Year, restored.Year);
Assert.AreEqual(original.Month, restored.Month);
Assert.AreEqual(original.Day, restored.Day);
Assert.AreEqual(original.Hour, restored.Hour);
Assert.AreEqual(original.Minute, restored.Minute);
Assert.AreEqual(original.Second, restored.Second);
}
///
/// 测试:毫秒级时间戳转换
///
[TestMethod]
public void ToUnixTimeMilliseconds_ConvertsCorrectly()
{
// Arrange
var dt = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc);
// Act
var timestamp = dt.ToUnixTimeMilliseconds();
// Assert
Assert.AreEqual(1704067200000, timestamp);
}
#endregion
#region 日期计算测试
///
/// 测试:获取月份第一天
///
[TestMethod]
public void StartOfMonth_ReturnsFirstDay()
{
// Arrange
var dt = new DateTime(2024, 3, 15, 14, 30, 45);
// Act
var result = dt.StartOfMonth();
// Assert
Assert.AreEqual(2024, result.Year);
Assert.AreEqual(3, result.Month);
Assert.AreEqual(1, result.Day);
Assert.AreEqual(0, result.Hour);
Assert.AreEqual(0, result.Minute);
Assert.AreEqual(0, result.Second);
}
///
/// 测试:获取月份最后一天
///
[TestMethod]
public void EndOfMonth_ReturnsLastDay()
{
// Arrange
var dt = new DateTime(2024, 2, 15); // 2024 是闰年
// Act
var result = dt.EndOfMonth();
// Assert
Assert.AreEqual(2024, result.Year);
Assert.AreEqual(2, result.Month);
Assert.AreEqual(29, result.Day); // 闰年 2 月有 29 天
Assert.AreEqual(23, result.Hour);
Assert.AreEqual(59, result.Minute);
Assert.AreEqual(59, result.Second);
}
///
/// 测试:获取年份第一天和最后一天
///
[TestMethod]
public void StartOfYear_AndEndOfYear_Work()
{
// Arrange
var dt = new DateTime(2024, 6, 15);
// Act
var start = dt.StartOfYear();
var end = dt.EndOfYear();
// Assert
Assert.AreEqual(new DateTime(2024, 1, 1, 0, 0, 0), start);
Assert.AreEqual(2024, end.Year);
Assert.AreEqual(12, end.Month);
Assert.AreEqual(31, end.Day);
}
///
/// 测试:获取当天开始和结束时间
///
[TestMethod]
public void StartOfDay_AndEndOfDay_Work()
{
// Arrange
var dt = new DateTime(2024, 3, 15, 14, 30, 45);
// Act
var start = dt.StartOfDay();
var end = dt.EndOfDay();
// Assert
Assert.AreEqual(new DateTime(2024, 3, 15, 0, 0, 0), start);
Assert.AreEqual(2024, end.Year);
Assert.AreEqual(3, end.Month);
Assert.AreEqual(15, end.Day);
Assert.AreEqual(23, end.Hour);
Assert.AreEqual(59, end.Minute);
}
///
/// 测试:获取周的第一天和最后一天
///
[TestMethod]
public void StartOfWeek_AndEndOfWeek_Work()
{
// Arrange: 2024年3月15日是星期五
var dt = new DateTime(2024, 3, 15);
// Act: 周一作为一周的开始
var start = dt.StartOfWeek(DayOfWeek.Monday);
var end = dt.EndOfWeek(DayOfWeek.Monday);
// Assert
Assert.AreEqual(DayOfWeek.Monday, start.DayOfWeek);
Assert.AreEqual(DayOfWeek.Sunday, end.DayOfWeek);
}
///
/// 测试:添加工作日
///
[TestMethod]
public void AddWorkDays_SkipsWeekends()
{
// Arrange: 2024年3月15日是星期五
var friday = new DateTime(2024, 3, 15);
// Act: 添加 1 个工作日应该跳到下周一
var nextWorkDay = friday.AddWorkDays(1);
// Assert: 应该是星期一
Assert.AreEqual(DayOfWeek.Monday, nextWorkDay.DayOfWeek);
Assert.AreEqual(18, nextWorkDay.Day);
// Act: 添加 5 个工作日
var fiveDaysLater = friday.AddWorkDays(5);
// Assert: 应该是下周五
Assert.AreEqual(22, fiveDaysLater.Day);
}
///
/// 测试:计算工作日数量
///
[TestMethod]
public void WorkDaysBetween_CountsCorrectly()
{
// Arrange: 2024年3月11日(周一)到 3月15日(周五)
var monday = new DateTime(2024, 3, 11);
var friday = new DateTime(2024, 3, 15);
// Act
var workDays = monday.WorkDaysBetween(friday);
// Assert: 周一到周五共 5 个工作日
Assert.AreEqual(5, workDays);
// 测试包含周末的情况
var nextMonday = new DateTime(2024, 3, 18);
var workDaysWithWeekend = monday.WorkDaysBetween(nextMonday);
// 周一到下周一:5 + 1 = 6 个工作日(跳过周末)
Assert.AreEqual(6, workDaysWithWeekend);
}
///
/// 测试:计算年龄
///
[TestMethod]
public void CalculateAge_ComputesCorrectly()
{
// Arrange
var birthDate = new DateTime(1990, 5, 15);
var referenceDate = new DateTime(2024, 6, 20);
// Act
var age = birthDate.CalculateAge(referenceDate);
// Assert
Assert.AreEqual(34, age);
// 测试生日还没到的情况
var beforeBirthday = new DateTime(2024, 5, 14);
var ageBeforeBirthday = birthDate.CalculateAge(beforeBirthday);
Assert.AreEqual(33, ageBeforeBirthday);
}
///
/// 测试:获取季度
///
[TestMethod]
public void GetQuarter_ReturnsCorrectQuarter()
{
Assert.AreEqual(1, new DateTime(2024, 1, 1).GetQuarter());
Assert.AreEqual(1, new DateTime(2024, 3, 31).GetQuarter());
Assert.AreEqual(2, new DateTime(2024, 4, 1).GetQuarter());
Assert.AreEqual(2, new DateTime(2024, 6, 30).GetQuarter());
Assert.AreEqual(3, new DateTime(2024, 7, 1).GetQuarter());
Assert.AreEqual(3, new DateTime(2024, 9, 30).GetQuarter());
Assert.AreEqual(4, new DateTime(2024, 10, 1).GetQuarter());
Assert.AreEqual(4, new DateTime(2024, 12, 31).GetQuarter());
}
///
/// 测试:获取季度第一天和最后一天
///
[TestMethod]
public void StartOfQuarter_AndEndOfQuarter_Work()
{
// Arrange: 2024年5月15日(第二季度)
var dt = new DateTime(2024, 5, 15);
// Act
var start = dt.StartOfQuarter();
var end = dt.EndOfQuarter();
// Assert
Assert.AreEqual(new DateTime(2024, 4, 1, 0, 0, 0), start);
Assert.AreEqual(6, end.Month);
Assert.AreEqual(30, end.Day);
}
#endregion
#region 时间范围判断测试
///
/// 测试:判断是否在时间范围内
///
[TestMethod]
public void IsBetween_ChecksCorrectly()
{
// Arrange
var dt = new DateTime(2024, 3, 15);
var start = new DateTime(2024, 3, 1);
var end = new DateTime(2024, 3, 31);
// Act & Assert
Assert.IsTrue(dt.IsBetween(start, end));
Assert.IsFalse(dt.IsBetween(start, new DateTime(2024, 3, 10)));
}
///
/// 测试:判断是否是周末
///
[TestMethod]
public void IsWeekend_ChecksCorrectly()
{
// Arrange
var saturday = new DateTime(2024, 3, 16); // 周六
var sunday = new DateTime(2024, 3, 17); // 周日
var monday = new DateTime(2024, 3, 18); // 周一
// Act & Assert
Assert.IsTrue(saturday.IsWeekend());
Assert.IsTrue(sunday.IsWeekend());
Assert.IsFalse(monday.IsWeekend());
Assert.IsTrue(monday.IsWorkDay());
}
///
/// 测试:判断是否是闰年
///
[TestMethod]
public void IsLeapYear_ChecksCorrectly()
{
// Arrange
var leapYear = new DateTime(2024, 1, 1);
var normalYear = new DateTime(2023, 1, 1);
// Act & Assert
Assert.IsTrue(leapYear.IsLeapYear());
Assert.IsFalse(normalYear.IsLeapYear());
}
///
/// 测试:判断是否在过去或未来
///
[TestMethod]
public void IsPast_AndIsFuture_Work()
{
// Arrange
var past = DateTime.Now.AddDays(-1);
var future = DateTime.Now.AddDays(1);
// Act & Assert
Assert.IsTrue(past.IsPast());
Assert.IsFalse(past.IsFuture());
Assert.IsFalse(future.IsPast());
Assert.IsTrue(future.IsFuture());
}
#endregion
#region 时间舍入测试
///
/// 测试:舍入到小时
///
[TestMethod]
public void RoundToHour_RemovesMinutesAndSeconds()
{
// Arrange
var dt = new DateTime(2024, 3, 15, 14, 30, 45);
// Act
var result = dt.RoundToHour();
// Assert
Assert.AreEqual(new DateTime(2024, 3, 15, 14, 0, 0), result);
}
///
/// 测试:舍入到分钟
///
[TestMethod]
public void RoundToMinute_RemovesSeconds()
{
// Arrange
var dt = new DateTime(2024, 3, 15, 14, 30, 45);
// Act
var result = dt.RoundToMinute();
// Assert
Assert.AreEqual(new DateTime(2024, 3, 15, 14, 30, 0), result);
}
///
/// 测试:向上/向下舍入到指定分钟间隔
///
[TestMethod]
public void CeilingAndFloorToMinutes_Work()
{
// Arrange: 14:23
var dt = new DateTime(2024, 3, 15, 14, 23, 0);
// Act: 舍入到 15 分钟间隔
var ceiling = dt.CeilingToMinutes(15); // 向上舍入到 14:30
var floor = dt.FloorToMinutes(15); // 向下舍入到 14:15
// Assert
Assert.AreEqual(30, ceiling.Minute);
Assert.AreEqual(15, floor.Minute);
}
#endregion
#region 实际应用场景测试
///
/// 场景测试:生日提醒功能
///
[TestMethod]
public void Scenario_BirthdayReminder()
{
// Arrange: 用户生日是 1990年5月15日
var birthDate = new DateTime(1990, 5, 15);
var today = new DateTime(2024, 5, 10);
// Act: 计算年龄和距离生日的天数
var age = birthDate.CalculateAge(today);
var thisYearBirthday = new DateTime(today.Year, birthDate.Month, birthDate.Day);
var daysUntilBirthday = (thisYearBirthday - today).Days;
// Assert
Assert.AreEqual(33, age); // 生日还没到,所以是 33 岁
Assert.AreEqual(5, daysUntilBirthday);
}
///
/// 场景测试:工作日计算(项目排期)
///
[TestMethod]
public void Scenario_ProjectScheduling()
{
// Arrange: 项目开始日期是周一
var projectStart = new DateTime(2024, 3, 11); // 周一
var estimatedWorkDays = 10;
// Act: 计算项目预计完成日期(只计算工作日)
var projectEnd = projectStart.AddWorkDays(estimatedWorkDays - 1);
// Assert: 10 个工作日后应该是下下周五
Assert.AreEqual(DayOfWeek.Friday, projectEnd.DayOfWeek);
Assert.AreEqual(22, projectEnd.Day);
}
///
/// 场景测试:营业时间判断
///
[TestMethod]
public void Scenario_BusinessHoursCheck()
{
// Arrange: 营业时间是工作日 9:00-18:00
var workdayMorning = new DateTime(2024, 3, 15, 10, 30, 0); // 周五 10:30
var weekend = new DateTime(2024, 3, 16, 10, 30, 0); // 周六 10:30
var afterHours = new DateTime(2024, 3, 15, 19, 30, 0); // 周五 19:30
// Act & Assert
Assert.IsTrue(workdayMorning.IsWorkDay());
Assert.IsTrue(workdayMorning.Hour >= 9 && workdayMorning.Hour < 18);
Assert.IsFalse(weekend.IsWorkDay());
Assert.IsTrue(afterHours.Hour >= 18);
}
///
/// 场景测试:会员到期提醒
///
[TestMethod]
public void Scenario_MembershipExpiration()
{
// Arrange: 会员到期日期
var expirationDate = new DateTime(2024, 12, 31);
var today = new DateTime(2024, 12, 20);
// Act: 计算剩余天数
var daysRemaining = (expirationDate - today).Days;
var friendlyText = expirationDate.GetTimeSpanFrom(today);
// Assert
Assert.AreEqual(11, daysRemaining);
Assert.AreEqual("11天", friendlyText);
}
///
/// 场景测试:活动报名截止时间
///
[TestMethod]
public void Scenario_EventRegistrationDeadline()
{
// Arrange: 活动时间是 2024年3月20日,报名截止时间是前3个工作日
var eventDate = new DateTime(2024, 3, 20); // 周三
var workDaysBeforeEvent = 3;
// Act: 计算报名截止日期
var deadline = eventDate.AddWorkDays(-workDaysBeforeEvent).EndOfDay();
// Assert: 应该是周五(3月15日)的 23:59:59
Assert.AreEqual(15, deadline.Day);
Assert.AreEqual(23, deadline.Hour);
}
///
/// 场景测试:数据统计(按季度)
///
[TestMethod]
public void Scenario_QuarterlyStatistics()
{
// Arrange: 获取当前季度的起止日期
var today = new DateTime(2024, 5, 15);
// Act
var quarterStart = today.StartOfQuarter();
var quarterEnd = today.EndOfQuarter();
var quarter = today.GetQuarter();
// Assert
Assert.AreEqual(2, quarter); // 第二季度
Assert.AreEqual(new DateTime(2024, 4, 1, 0, 0, 0), quarterStart);
Assert.AreEqual(6, quarterEnd.Month);
Assert.AreEqual(30, quarterEnd.Day);
}
#endregion
}