首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 產生隨機日期時間:邊界條件完美處理的 DateTimeHelper

     編輯:關於C語言

核心演算法

  1. 計算兩 DateTime 差值的 TimeSpan。
  2. 取總秒數 TotalSeconds(double)。
  3. 安全轉換為 int,處理超出 Int32 範圍情況。
  4. 決定較早/較晚時間為起訖點。
  5. 用 Random.Next(Math.Abs(seconds)) 產生隨機秒數偏移。
  6. 以 AddSeconds() 加到起始時間。

關鍵邊界處理

風險原始碼問題解決方案
TotalSeconds > Int32.MaxValue直接 (int)d 會溢位回繞成負數截斷為 Int32.MaxValue
TotalSeconds < Int32.MinValue同理溢位截斷為 Int32.MinValue
Math.Abs(Int32.MinValue)拋出 OverflowException(因絕對值 2,147,483,648 > MaxValue)若 seconds == Int32.MinValue,改用 Int32.MinValue + 1
Random 種子重複短時間多次 new Random() 產生相同序列提供多載接受外部 Random 實例

完整實作碼

using System;

public static class DateTimeHelper
{
    /// 
    /// 產生隨機日期時間(內部建立 Random,適合單次呼叫)
    /// 
    public static DateTime GetRandomTime(DateTime time1, DateTime time2)
        => GetRandomTime(time1, time2, new Random());

    /// 
    /// 產生隨機日期時間(接受外部 Random,適合迴圈/高頻呼叫)
    /// 
    public static DateTime GetRandomTime(DateTime time1, DateTime time2, Random random)
    {
        // 1. 計算差值(用 Ticks 避免 TimeSpan 建構溢位)
        long ticksDiff = time1.Ticks - time2.Ticks;
        double totalSeconds = ticksDiff / (double)TimeSpan.TicksPerSecond;

        // 2. 安全轉 int
        int totalSecs;
        if (totalSeconds > int.MaxValue) totalSecs = int.MaxValue;
        else if (totalSeconds < int.MinValue) totalSecs = int.MinValue;
        else totalSecs = (int)totalSeconds;

        // 3. 決定起訖
        DateTime minTime, maxTime;
        if (totalSecs > 0) { minTime = time2; maxTime = time1; }
        else if (totalSecs < 0) { minTime = time1; maxTime = time2; }
        else return time1; // 同一時間

        // 4. 處理 Abs(Int32.MinValue) 例外
        int maxVal = totalSecs;
        if (totalSecs <= int.MinValue) maxVal = int.MinValue + 1;

        // 5. 產生偏移並回傳
        int offset = random.Next(Math.Abs(maxVal));
        return minTime.AddSeconds(offset);
    }
}

單元測試驗證邊界


using NUnit.Framework;

[TestFixture]
public class DateTimeHelperTests
{
    [Test]
    public void FullRange_RandomTimes_AlwaysWithinBounds()
    {
        var rand = new Random();
        DateTime min = DateTime.MinValue;
        DateTime max = DateTime.MaxValue;

        for (int i = 0; i < 10000; i++)
        {
            DateTime r1 = DateTimeHelper.GetRandomTime(min, max, rand);
            Assert.That(r1, Is.GreaterThanOrEqualTo(min).And.LessThanOrEqualTo(max));

            DateTime r2 = DateTimeHelper.GetRandomTime(max, min, rand); // 參數順序互換
            Assert.That(r2, Is.GreaterThanOrEqualTo(min).And.LessThanOrEqualTo(max));
        }
    }

    [Test]
    public void SameTime_ReturnsSameTime()
    {
        var now = DateTime.Now;
        Assert.AreEqual(now, DateTimeHelper.GetRandomTime(now, now));
    }
}

實務補充

  • 精度需求: 若需毫秒級隨機,改用 ticksDiff 直接 random.NextLong()(.NET 6+)或自行實作 64 位元隨機。
  • 密碼學安全: 需不可預測隨機時,改用 RandomNumberGenerator(System.Security.Cryptography)。
  • 效能: 高頻呼叫務必重複使用 Random 實例,避免種子衝突。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved