以秒为单位的 Unix 时间戳到 C# DateTime 不是 UTC
Unix Timestamp in seconds to C# DateTime is not UTC
我知道 Unix 时间戳本质上是 UTC(误导,这不是真的,new Date()
将始终在 browser/server 时区, .getTime()
反映了这一点)。
为什么转换为 C# DateTime 时不是 UTC。
我已将日期 2092 年 8 月 9 日转换为以秒为单位的时间戳 (3869074800),
new Date('August, 9 2092').getTime()/1000
或https://codepen.io/pnmcosta/pen/rpvjVp
但是当转换为 C# 日期时,它不是 UTC (8/8/2092 11:00:00 PM)?即使 EPOCH 已创建为 UTC:
using System;
public class Program
{
public readonly static DateTime EPOCH_UNIX = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private readonly static double MaxUnixSeconds = (DateTime.MaxValue.ToUniversalTime() - EPOCH_UNIX).TotalSeconds;
public static void Main()
{
Console.WriteLine(FromUnixTimeStamp(3869074800));
}
public static DateTime FromUnixTimeStamp(long value)
{
return value > MaxUnixSeconds ? EPOCH_UNIX.AddMilliseconds(value) : EPOCH_UNIX.AddSeconds(value);
}
}
或https://dotnetfiddle.net/ERySea
如何最好地处理这种情况,记住时间并不重要,但日期应该是正确的?
编辑 2
我想我可能已经破解了日期以计算出偏移量(更新 https://dotnetfiddle.net/ERySea)到:
using System;
public class Program
{
public readonly static DateTime EPOCH_UNIX = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private readonly static long MaxUnixSeconds = (long)(DateTime.MaxValue.ToUniversalTime() - EPOCH_UNIX).TotalSeconds;
public static void Main()
{
// date with DST (Daylight savings time), e.g. 08/09/2092 (DD/MM/yyyy)
// is stored as, e.g. 3869074800 seconds, from EPOCH_UNIX
// instead of 3869078400 (UTC, without offsets) as it should be!
DateTime dt = FromUnixTimeStamp(3869074800);
Console.WriteLine("Date: {0:dd MMM yyyy HH:mm}", dt);
// fix DST offset
if (dt.Hour != 0)
{
int offset = 24 - dt.Hour;
dt = dt.AddHours(offset);
Console.WriteLine("Offset: {0}", offset);
}
// fix century (if date of birth)
if (dt.Year >= DateTime.UtcNow.Year)
dt = dt.AddYears(-100);
Console.WriteLine("Fixed Date: {0:dd MMM yyyy HH:mm}", dt);
}
public static DateTime FromUnixTimeStamp(long value)
{
return value > MaxUnixSeconds ? EPOCH_UNIX.AddMilliseconds(value) : EPOCH_UNIX.AddSeconds(value);
}
}
根据 https://www.epochconverter.com/ 3869074800 的 UNIX 时间戳是 2092 年 8 月 8 日 11:00:00 下午,因此 C# 在 GMT 中正确显示它。 UTC 和 GMT 是......不一样,但为了人类阅读的目的,准确地说你可以将它们视为相同。
你的问题在于你如何获得 UNIX 时间戳 3869074800。
问题是 JavaScript 不是 C#,或者更正确地说,你的前提是 new Date('August, 9 2092').getTime()/1000
代表什么。
JavaScript 将创建一个新日期,因为它处于本地时区而不是 UTC。所以
new Date('August, 9 2092')
实际上是
Sat Aug 09 2092 00:00:00 GMT+0100 (GMT Daylight Time)
注意到偏移了吗?这实际上是 Fri Aug 08 2092 23:00:00 UTC+0000
所以你从 JavaScript 得到的纪元不是你想要的。
您应该减去 时区偏移量(以分钟为单位乘以 60)以获得 UTC。
var date = new Date('August, 9 2092');
var timestamp = date.getTime()/1000 - date.getTimezoneOffset()*60;
// timestamp == 3869078400
编辑
与其伪造计算,不如假设时间戳是本地的...
改变
public readonly static DateTime EPOCH_UNIX = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
到
public readonly static DateTime EPOCH_UNIX = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
至少结果是08 Aug 2092 23:00 Local
。
我知道 Unix 时间戳本质上是 UTC(误导,这不是真的,new Date()
将始终在 browser/server 时区, .getTime()
反映了这一点)。
为什么转换为 C# DateTime 时不是 UTC。
我已将日期 2092 年 8 月 9 日转换为以秒为单位的时间戳 (3869074800),
new Date('August, 9 2092').getTime()/1000
或https://codepen.io/pnmcosta/pen/rpvjVp
但是当转换为 C# 日期时,它不是 UTC (8/8/2092 11:00:00 PM)?即使 EPOCH 已创建为 UTC:
using System;
public class Program
{
public readonly static DateTime EPOCH_UNIX = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private readonly static double MaxUnixSeconds = (DateTime.MaxValue.ToUniversalTime() - EPOCH_UNIX).TotalSeconds;
public static void Main()
{
Console.WriteLine(FromUnixTimeStamp(3869074800));
}
public static DateTime FromUnixTimeStamp(long value)
{
return value > MaxUnixSeconds ? EPOCH_UNIX.AddMilliseconds(value) : EPOCH_UNIX.AddSeconds(value);
}
}
或https://dotnetfiddle.net/ERySea
如何最好地处理这种情况,记住时间并不重要,但日期应该是正确的?
编辑 2
我想我可能已经破解了日期以计算出偏移量(更新 https://dotnetfiddle.net/ERySea)到:
using System;
public class Program
{
public readonly static DateTime EPOCH_UNIX = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private readonly static long MaxUnixSeconds = (long)(DateTime.MaxValue.ToUniversalTime() - EPOCH_UNIX).TotalSeconds;
public static void Main()
{
// date with DST (Daylight savings time), e.g. 08/09/2092 (DD/MM/yyyy)
// is stored as, e.g. 3869074800 seconds, from EPOCH_UNIX
// instead of 3869078400 (UTC, without offsets) as it should be!
DateTime dt = FromUnixTimeStamp(3869074800);
Console.WriteLine("Date: {0:dd MMM yyyy HH:mm}", dt);
// fix DST offset
if (dt.Hour != 0)
{
int offset = 24 - dt.Hour;
dt = dt.AddHours(offset);
Console.WriteLine("Offset: {0}", offset);
}
// fix century (if date of birth)
if (dt.Year >= DateTime.UtcNow.Year)
dt = dt.AddYears(-100);
Console.WriteLine("Fixed Date: {0:dd MMM yyyy HH:mm}", dt);
}
public static DateTime FromUnixTimeStamp(long value)
{
return value > MaxUnixSeconds ? EPOCH_UNIX.AddMilliseconds(value) : EPOCH_UNIX.AddSeconds(value);
}
}
根据 https://www.epochconverter.com/ 3869074800 的 UNIX 时间戳是 2092 年 8 月 8 日 11:00:00 下午,因此 C# 在 GMT 中正确显示它。 UTC 和 GMT 是......不一样,但为了人类阅读的目的,准确地说你可以将它们视为相同。
你的问题在于你如何获得 UNIX 时间戳 3869074800。
问题是 JavaScript 不是 C#,或者更正确地说,你的前提是 new Date('August, 9 2092').getTime()/1000
代表什么。
JavaScript 将创建一个新日期,因为它处于本地时区而不是 UTC。所以
new Date('August, 9 2092')
实际上是
Sat Aug 09 2092 00:00:00 GMT+0100 (GMT Daylight Time)
注意到偏移了吗?这实际上是 Fri Aug 08 2092 23:00:00 UTC+0000
所以你从 JavaScript 得到的纪元不是你想要的。
您应该减去 时区偏移量(以分钟为单位乘以 60)以获得 UTC。
var date = new Date('August, 9 2092');
var timestamp = date.getTime()/1000 - date.getTimezoneOffset()*60;
// timestamp == 3869078400
编辑
与其伪造计算,不如假设时间戳是本地的...
改变
public readonly static DateTime EPOCH_UNIX = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
到
public readonly static DateTime EPOCH_UNIX = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
至少结果是08 Aug 2092 23:00 Local
。