演算法邏輯
- 計算兩時間差
TimeSpan,取得總秒數 double。
- 轉換為
int,處理超出 Int32 範圍邊界。
- 以
Random.Next(Math.Abs(seconds)) 產生隨機秒數偏移。
- 加到較早時間點,得到隨機 DateTime。
健壯實作
using System;
public static class DateTimeHelper
{
// 公開簡易版,內部 new Random(注意:短時間重複呼叫會產生相同種子)
public static DateTime GetRandomTime(DateTime t1, DateTime t2) => GetRandomTime(t1, t2, new Random());
// 建議外部傳入共用 Random 實例
public static DateTime GetRandomTime(DateTime t1, DateTime t2, Random rnd)
{
TimeSpan ts = t1 - t2;
double totalSec = ts.TotalSeconds;
int sec;
if (totalSec > int.MaxValue) sec = int.MaxValue;
else if (totalSec < int.MinValue) sec = int.MinValue;
else sec = (int)totalSec;
DateTime minT, maxT;
if (sec > 0) { minT = t2; maxT = t1; }
else if (sec < 0) { minT = t1; maxT = t2; }
else return t1;
// 避免 Abs(Int32.MinValue) 溢位
int range = sec == int.MinValue ? int.MaxValue : Math.Abs(sec);
int offset = rnd.Next(range);
return minT.AddSeconds(offset);
}
}
邊界測試
[TestFixture]
public class DateTimeHelperTest
{
[Test]
public void BoundaryTest()
{
DateTime min = DateTime.MinValue, max = DateTime.MaxValue;
Random r = new Random();
for (int i = 0; i < 10000; i++)
{
DateTime rt = DateTimeHelper.GetRandomTime(max, min, r);
Assert.IsTrue(rt >= min && rt <= max);
rt = DateTimeHelper.GetRandomTime(min, max, r);
Assert.IsTrue(rt >= min && rt <= max);
}
}
}
常見陷阱
Random 預設種子為 Environment.TickCount,短時間多次 new Random() 會產生相同序列 → 共用單一實例。
Math.Abs(int.MinValue) 擲回 OverflowException,需特殊處理。
TimeSpan.TotalSeconds 可能超出 Int32 範圍(約 68 年),長跨度需用 long 版 Random.Next(long)(.NET 6+)或自行實作。