核心演算法
- 計算兩個
DateTime 的 TimeSpan,取得總秒數 (TotalSeconds)。
- 將總秒數轉為
int,但需處理超出 Int32.MaxValue/MinValue 的情況。
- 決定較小時間為基準,呼叫
Random.Next 產生隨機秒數並 AddSeconds。
關鍵程式碼片段
public static DateTime GetRandomTime(DateTime t1, DateTime t2, Random rnd)
{
TimeSpan ts = new TimeSpan(t1.Ticks - t2.Ticks);
double totalSec = ts.TotalSeconds;
int intSec;
// 處理超出 Int32 範圍
if (totalSec > Int32.MaxValue) intSec = Int32.MaxValue;
else if (totalSec < Int32.MinValue) intSec = Int32.MinValue;
else intSec = (int)totalSec;
DateTime minTime, maxTime;
if (intSec > 0) { minTime = t2; maxTime = t1; }
else if (intSec < 0) { minTime = t1; maxTime = t2; }
else return t1;
// 避免 Math.Abs(Int32.MinValue) 拋出 OverflowException
int maxVal = intSec;
if (intSec <= Int32.MinValue) maxVal = Int32.MinValue + 1;
int offset = rnd.Next(Math.Abs(maxVal));
return minTime.AddSeconds(offset);
}
陷阱與對策
- 直接轉型
(int)double:若 double > Int32.MaxValue 會溢位回傳 Int32.MinValue 且不拋出例外,必須先比較再轉型。
- Math.Abs(Int32.MinValue):會拋出
OverflowException,故需特別判斷並調整 maxVal。
- Random 種子:若短時間多次建立
new Random() 會產生相同序列,建議由呼叫端傳入共用實例。
使用範例
Random rnd = new Random();
DateTime dt = DateTimeHelper.GetRandomTime(DateTime.Now, DateTime.Now.AddDays(30), rnd);