转换负纪元时间的公式是什么?
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);
我对负纪元时间有疑问。我有一个第三方程序可以为我生成纪元时间。我正在使用该程序为我生成纪元时间,我将所有日期和时间保持相同,同时只更改年份以获得下面的纪元时间以进行测试。我的日期和时间应该是 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);