以秒为单位的 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