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 }