以秒为单位的Unix时间戳到C#DateTime不是UTC

时间:2018-01-11 15:50:55

标签: c# datetime unix epoch date-conversion

我知道Unix时间戳本质上是UTC (误导,这不是真的,new Date()将始终在浏览器/服务器时区,.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);
    }
}

2 个答案:

答案 0 :(得分:1)

根据source,UNIX时间戳3869074800是8/8/2092 11:00:00 PM,因此C#正确地在GMT中显示它。 UTC和GMT是......不一样的,但是出于人类阅读的目的,它可以准确地说你可以将它们视为一样。

您的问题在于如何获得UNIX时间戳3869074800。

答案 1 :(得分:1)

问题是JavaScript而不是C#,或者更准确地说是new Date('August, 9 2092').getTime()/1000所代表的前提。

JavaScript将创建一个新的Date作为本地时区而不是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