Skip to content

Commit 29146d8

Browse files
committed
test: 添加 TimerHelper 时区功能测试用例
- 验证默认时区为 UTC - 测试 SetTimeZone 更新当前时区功能 - 确保 GetTodayStart、GetWeekStart、GetMonthStart、GetYearStart 系列函数遵循时区设置 - 验证 Unix 时间戳的绝对性(不受时区影响) - 测试空值和无效时区 ID 的默认回退行为
1 parent c13a18f commit 29146d8

1 file changed

Lines changed: 200 additions & 0 deletions

File tree

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
using System;
2+
using GameFrameX.Foundation.Utility;
3+
using Xunit;
4+
using Xunit.Abstractions;
5+
6+
namespace GameFrameX.Foundation.Tests.Utility
7+
{
8+
/// <summary>
9+
/// TimerHelper 时区功能测试
10+
/// </summary>
11+
public class TimerHelperTimeZoneTests : IDisposable
12+
{
13+
private readonly ITestOutputHelper _output;
14+
15+
/// <summary>
16+
/// 构造函数,初始化测试环境
17+
/// </summary>
18+
/// <param name="output">测试输出帮助类</param>
19+
public TimerHelperTimeZoneTests(ITestOutputHelper output)
20+
{
21+
_output = output;
22+
// Ensure default state is UTC before each test
23+
TimerHelper.SetTimeZone(TimeZoneInfo.Utc);
24+
}
25+
26+
/// <summary>
27+
/// 释放资源,重置测试环境
28+
/// </summary>
29+
public void Dispose()
30+
{
31+
// Reset to UTC after each test to avoid side effects
32+
TimerHelper.SetTimeZone(TimeZoneInfo.Utc);
33+
}
34+
35+
/// <summary>
36+
/// 测试默认时区应为 UTC
37+
/// </summary>
38+
[Fact]
39+
public void DefaultTimeZone_ShouldBeUtc()
40+
{
41+
Assert.Equal(TimeZoneInfo.Utc.Id, TimerHelper.CurrentTimeZone.Id);
42+
43+
var now = TimerHelper.GetNow();
44+
var utcNow = DateTime.UtcNow;
45+
46+
// Allow small difference for execution time
47+
Assert.True((now - utcNow).Duration().TotalSeconds < 1);
48+
}
49+
50+
/// <summary>
51+
/// 测试 SetTimeZone 应正确更新当前时区
52+
/// </summary>
53+
[Fact]
54+
public void SetTimeZone_ShouldUpdateCurrentTimeZone()
55+
{
56+
// Use a fixed offset timezone for reliable testing
57+
var offset = TimeSpan.FromHours(8);
58+
var customTimeZone = TimeZoneInfo.CreateCustomTimeZone("Test+8", offset, "Test+8", "Test+8");
59+
60+
TimerHelper.SetTimeZone(customTimeZone);
61+
Assert.Equal(customTimeZone.Id, TimerHelper.CurrentTimeZone.Id);
62+
63+
var now = TimerHelper.GetNow();
64+
var utcNow = DateTime.UtcNow;
65+
66+
// Expected: Now = UtcNow + 8 hours
67+
var expectedNow = utcNow + offset;
68+
Assert.True((now - expectedNow).Duration().TotalSeconds < 1);
69+
}
70+
71+
/// <summary>
72+
/// 测试 GetTodayStart 系列函数应遵循时区设置
73+
/// </summary>
74+
[Fact]
75+
public void GetTodayStart_ShouldRespectTimeZone()
76+
{
77+
var offset = TimeSpan.FromHours(8);
78+
var customTimeZone = TimeZoneInfo.CreateCustomTimeZone("Test+8", offset, "Test+8", "Test+8");
79+
TimerHelper.SetTimeZone(customTimeZone);
80+
81+
var now = TimerHelper.GetNow();
82+
var todayStart = TimerHelper.GetTodayStartTime();
83+
var todayStartTimestamp = TimerHelper.GetTodayStartTimestamp();
84+
85+
// Verify DateTime parts
86+
Assert.Equal(now.Date, todayStart);
87+
Assert.Equal(0, todayStart.Hour);
88+
89+
// Verify Timestamp
90+
// Construct expected DateTimeOffset
91+
var expectedTime = new DateTimeOffset(todayStart, offset);
92+
Assert.Equal(expectedTime.ToUnixTimeSeconds(), todayStartTimestamp);
93+
}
94+
95+
/// <summary>
96+
/// 测试 GetWeekStart 系列函数应遵循时区设置
97+
/// </summary>
98+
[Fact]
99+
public void GetWeekStart_ShouldRespectTimeZone()
100+
{
101+
var offset = TimeSpan.FromHours(8);
102+
var customTimeZone = TimeZoneInfo.CreateCustomTimeZone("Test+8", offset, "Test+8", "Test+8");
103+
TimerHelper.SetTimeZone(customTimeZone);
104+
105+
var now = TimerHelper.GetNow();
106+
var weekStart = TimerHelper.GetWeekStartTime();
107+
var weekStartTimestamp = TimerHelper.GetWeekStartTimestamp();
108+
109+
// Verify it is indeed the start of the week (Monday)
110+
Assert.Equal(DayOfWeek.Monday, weekStart.DayOfWeek);
111+
Assert.True(weekStart <= now);
112+
Assert.True((now - weekStart).TotalDays < 7);
113+
Assert.Equal(0, weekStart.Hour);
114+
115+
// Verify Timestamp
116+
var expectedTime = new DateTimeOffset(weekStart, offset);
117+
Assert.Equal(expectedTime.ToUnixTimeSeconds(), weekStartTimestamp);
118+
}
119+
120+
/// <summary>
121+
/// 测试 GetMonthStart 系列函数应遵循时区设置
122+
/// </summary>
123+
[Fact]
124+
public void GetMonthStart_ShouldRespectTimeZone()
125+
{
126+
var offset = TimeSpan.FromHours(-5); // Test negative offset
127+
var customTimeZone = TimeZoneInfo.CreateCustomTimeZone("Test-5", offset, "Test-5", "Test-5");
128+
TimerHelper.SetTimeZone(customTimeZone);
129+
130+
var now = TimerHelper.GetNow();
131+
var monthStart = TimerHelper.GetMonthStartTime();
132+
var monthStartTimestamp = TimerHelper.GetMonthStartTimestamp();
133+
134+
Assert.Equal(now.Year, monthStart.Year);
135+
Assert.Equal(now.Month, monthStart.Month);
136+
Assert.Equal(1, monthStart.Day);
137+
Assert.Equal(0, monthStart.Hour);
138+
139+
// Verify Timestamp
140+
var expectedTime = new DateTimeOffset(monthStart, offset);
141+
Assert.Equal(expectedTime.ToUnixTimeSeconds(), monthStartTimestamp);
142+
}
143+
144+
/// <summary>
145+
/// 测试 GetYearStart 系列函数应遵循时区设置
146+
/// </summary>
147+
[Fact]
148+
public void GetYearStart_ShouldRespectTimeZone()
149+
{
150+
var offset = TimeSpan.FromHours(9);
151+
var customTimeZone = TimeZoneInfo.CreateCustomTimeZone("Test+9", offset, "Test+9", "Test+9");
152+
TimerHelper.SetTimeZone(customTimeZone);
153+
154+
var now = TimerHelper.GetNow();
155+
var yearStart = TimerHelper.GetYearStartTime();
156+
var yearStartTimestamp = TimerHelper.GetYearStartTimestamp();
157+
158+
Assert.Equal(now.Year, yearStart.Year);
159+
Assert.Equal(1, yearStart.Month);
160+
Assert.Equal(1, yearStart.Day);
161+
Assert.Equal(0, yearStart.Hour);
162+
163+
// Verify Timestamp
164+
var expectedTime = new DateTimeOffset(yearStart, offset);
165+
Assert.Equal(expectedTime.ToUnixTimeSeconds(), yearStartTimestamp);
166+
}
167+
168+
/// <summary>
169+
/// 测试 Unix 时间戳应保持绝对性(不受时区设置影响,始终基于 UTC)
170+
/// </summary>
171+
[Fact]
172+
public void UnixTimestamp_ShouldBeAbsolute()
173+
{
174+
// Timestamp should be the same regardless of timezone setting because it represents absolute time
175+
176+
TimerHelper.SetTimeZone(TimeZoneInfo.Utc);
177+
var ts1 = TimerHelper.UnixTimeSeconds();
178+
179+
var customTimeZone = TimeZoneInfo.CreateCustomTimeZone("Test+10", TimeSpan.FromHours(10), "Test+10", "Test+10");
180+
TimerHelper.SetTimeZone(customTimeZone);
181+
var ts2 = TimerHelper.UnixTimeSeconds();
182+
183+
// Allow small difference for execution time
184+
Assert.True(Math.Abs(ts2 - ts1) < 2);
185+
}
186+
[Fact]
187+
public void SetTimeZone_WithNull_ShouldDefaultToUtc()
188+
{
189+
TimerHelper.SetTimeZone((TimeZoneInfo)null);
190+
Assert.Equal(TimeZoneInfo.Utc.Id, TimerHelper.CurrentTimeZone.Id);
191+
}
192+
193+
[Fact]
194+
public void SetTimeZone_WithInvalidId_ShouldDefaultToUtc()
195+
{
196+
TimerHelper.SetTimeZone("InvalidTimeZoneId");
197+
Assert.Equal(TimeZoneInfo.Utc.Id, TimerHelper.CurrentTimeZone.Id);
198+
}
199+
}
200+
}

0 commit comments

Comments
 (0)