转换负纪元时间的公式是什么?

what is the formula for converting negative epoch time?

我对负纪元时间有疑问。我有一个第三方程序可以为我生成纪元时间。我正在使用该程序为我生成纪元时间,我将所有日期和时间保持相同,同时只更改年份以获得下面的纪元时间以进行测试。我的日期和时间应该是 01/01/yyyy 12:00:00 AM 对于所有 yyyy。

这是我的:

 var epoch = new DateTime(1904, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        var ofset = 6*60*60; // 6hr different

        Console.WriteLine("1900: " + epoch.AddSeconds(-126122400 - ofset)); // 1900
        Console.WriteLine("1904: " + epoch.AddSeconds(21600 - ofset)); // 1904
        Console.WriteLine("1905: " + epoch.AddSeconds(31644000 - ofset)); // 1905
        Console.WriteLine("1970: " + epoch.AddSeconds(2082866400 - ofset)); // 1970
        Console.WriteLine("1971: " + epoch.AddSeconds(2114402400 - ofset)); // 1971
        Console.WriteLine("1972: " + epoch.AddSeconds(2145938400 - ofset)); // 1972
        Console.WriteLine("1973: " + epoch.AddSeconds(-2117406496 - ofset)); // 1973
        Console.WriteLine("1974: " + epoch.AddSeconds(-2085870496 - ofset)); // 1974
        Console.WriteLine("2016: " + epoch.AddSeconds(-760494496 - ofset)); // 2016

输出为:

1900: 1/1/1900 12:00:00 AM
1904: 1/1/1904 12:00:00 AM
1905: 1/1/1905 12:00:00 AM
1970: 1/1/1970 12:00:00 AM
1971: 1/1/1971 12:00:00 AM
1972: 1/1/1972 12:00:00 AM
1973: 11/24/1836 5:31:44 PM
1974: 11/24/1837 5:31:44 PM
2016: 11/24/1879 5:31:44 PM

如您所见,从第 1973 行(纪元时间为负数)开始,日期和年份以及时间输出都是错误的。我应该怎么做才能获得正确的日期、年份和时间?

更新:

对于日期设置为 10:11:45.654 AM 5/26/2016 的原始数据,这就是我在数据库中看到的:

<Timestamp>
            <Name>Date Created</Name>
            <Cluster>
                <Name></Name>
                <NumElts>4</NumElts>
                <I32>
                    <Name></Name>
                    <Val>0</Val>
                </I32>
                <I32>
                    <Name></Name>
                    <Val>-1482223616</Val>
                </I32>
                <I32>
                    <Name></Name>
                    <Val>-747850591</Val>
                </I32>
                <I32>
                    <Name></Name>
                    <Val>0</Val>
                </I32>
            </Cluster>
        </Timestamp>

我想我发现了问题:整数溢出。我不知道哪里发生了,但这就是问题所在。

考虑一下,从 1904/01/01 到 1973/01/01 的秒数是 2,177,539,200。整数的最大值为 2,147,483,648。因此 1973 的偏移值大于整数。

如果将数字 2,177,539,200 转换为 int,则得到的值为 -2,117,428,096。如果将该数字代入日期计算,则会得到 1836/11/24 17:31:44。这是测试代码:

private static void Main(string[] args)
{
    var epoch = new DateTime(1904, 01, 01, 0, 0, 0, DateTimeKind.Utc);
    var offset = TimeSpan.FromHours(6);

    // How many seconds between 1904/01/01 and 1973/01/01?
    var timestamp1973 = (new DateTime(1973, 01, 01, 0, 0, 0, DateTimeKind.Local) - epoch).TotalSeconds;
    Console.WriteLine("1973 timestamp = {0:N0}", timestamp1973);
    Console.WriteLine("Verify calculation: {0}", epoch.AddSeconds(timestamp1973));

    // How many seconds is that different from int.MaxValue?
    var overflow = timestamp1973 - int.MaxValue;
    Console.WriteLine("Overflow = {0:N0}", overflow);

    // So take int.MaxValue and add the overflow
    var wrongTimeStamp = int.MaxValue;
    wrongTimeStamp += (int) overflow;
    Console.WriteLine("wrong time stamp = {0:N0}", wrongTimeStamp);

    // And the calculation with that value is:
    Console.WriteLine("Wrong date = {0}", epoch.AddSeconds(wrongTimeStamp));
    Console.ReadLine();
}

并且输出:

1973 timestamp = 2,177,539,200
Verify calculation: 1973-01-01 00:00:00
Overflow = 30,055,553
wrong time stamp = -2,117,428,096
Wrong date = 1836-11-24 17:31:44

因此,第三方程序错误地向您发送了数据中的带符号 32 位整数,或者您程序中的某些内容错误地将 LabView 创建的带符号 64 位数字转换为带符号的 32 位数字. 某处有人将 64 位转换为 32 位,但事情进展顺利。

评论后

如果数据确实是有符号整数,那么您唯一的选择就是将其视为无符号整数。这将阻止您显示 1904 年之前的日期,但它会让您的范围达到 2040 年 2 月。要做到这一点:

int signedValue = ReadFromDatabase();
uint unsignedValue = (uint)signedValue;
var theDate = epoch.AddSeconds(unsignedValue);