将秒添加到具有有效双精度的DateTime会导致ArgumentOutOfRangeException

本文关键字:DateTime ArgumentOutOfRangeException 双精度 有效 添加 | 更新日期: 2023-09-27 18:29:13

以下代码崩溃和烧录,我不明白为什么:

DateTime dt = new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc);
double d = double.Parse("1332958778172");
Console.Write(dt.AddSeconds(d));

有人能告诉我发生了什么事吗?我似乎不明白为什么。。。

编辑

这个值来自Salesforce REST API和我所理解的Unix epoch时间戳"令牌发布时间,表示为自Unix epoch(1970年1月1日00:00:00 UTC)以来的秒数。"

解决方案

Salesforce REST API实际上在执行OAuth请求时为issued_at字段发回毫秒,而他们说他们正在发送秒。。。

将秒添加到具有有效双精度的DateTime会导致ArgumentOutOfRangeException

正如其他人所说,问题在于值太大。

仔细看了一下,我相信它代表了自Unix时代以来的毫秒,而不是所以你想要:

DateTime dt = new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc);
double d = double.Parse("1332958778172");  // Or avoid parsing if possible :)
Console.Write(dt.AddMilliseconds(d));

要么这样,要么在调用AddSeconds之前除以1000——但显然这会丢失数据。

您添加的值导致日期超出DateTime支持的有效日期范围。

DateTime支持01/01/0001 00:00:00至31/12/9999 23:59:59。

1332958778172/3600/24/365的简单计算得出42267年。

我认为double值确实太大了。它代表了42267年多一点(如果我的数学计算正确的话),DateTime.MaxValue是23:59:59.999999999999年12月31日

DateTime dt = new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc);    
Console.Write(dt.AddSeconds(1332958778172D));

除了。。。

1332958778172/60/60/24/365=42267年。。。日期时间只能截止到23:59:59.999999999999年12月31日

我遇到了类似的问题,需要在日期时间中添加一个可配置的时间跨度。如果配置不正确,我必须假设"最坏的情况":MaxValue。

我通过实现DateTime的扩展(仍处于测试阶段)解决了这个问题:

    /// <summary>
    /// Removes a timespan from a date, returning MinValue or MaxValue instead of throwing exception when if the resulting date
    /// is behind the Min/Max values
    /// </summary>
    /// <returns></returns>
    public static DateTime SafeAdd(this DateTime source, TimeSpan value)
    {
        // Add or remove ?
        if (value.Ticks > 0)
        {
            // add
            var maxTicksToAdd = DateTime.MaxValue - source;
            if (value.Ticks > maxTicksToAdd.Ticks)
                return DateTime.MaxValue;
        }
        else
        {
            var maxTicksToRemove = source - DateTime.MinValue;
            // get the value to remove in unsigned representation.
            // negating MinValues is impossible because it would result in a value bigger than MaxValue : (-32768 .. 0 .. 32767)
            var absValue = value == TimeSpan.MinValue ? TimeSpan.MaxValue : -value;
            if (absValue.Ticks > maxTicksToRemove.Ticks)
                return DateTime.MinValue;
        }
        return source + value;
    }

看起来这个时间戳是以毫秒为单位的,请尝试下面的代码,它应该可以正常工作。

DateTime nDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
double epoch = 1585008000000;
DateTime rDate = nDateTime.AddMilliseconds(epoch);

在添加值为dynamically calculated且将超过DateTime范围的逻辑中,我遇到了这种情况。

double expiredAfter = Math.Pow(10, value);
        
var expirationDate = DateTime.UtcNow.AddSeconds(expiredAfter + 5));

在我的场景中,value从1开始,并在每一步递增,运行10次后,它将超过DateTime的限制。

在我的例子中,我不得不使用一个api对象作为double,并将unix时间转换为DateTime:

DateTime Date = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(Double.Parse("1596225600000"));