【问题标题】:Unix Timestamp in seconds to C# DateTime is not UTC以秒为单位的 Unix 时间戳到 C# DateTime 不是 UTC
【发布时间】:2018-06-21 00:22:29
【问题描述】:

我知道 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(2092 年 8 月 8 日晚上 11:00:00)?即使 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);
    }
}

【问题讨论】:

  • 根据unixtimestamp.com/index.php August 9, 2092 00:00:00 是 3869078400 ,而不是 ... 4800 和 3869074800 确实是 8/8/2092 11:00:00 PM UTC
  • 使用双精度表示秒数看起来很可疑。我建议使用 long,尤其是对于这么大的值。
  • @Fildor,如果 getTime() 旨在返回 UTC 时间戳,那么 new Date('August, 9 2092').getTime()/1000 怎么会不正确?
  • 我不知道。关键是:您的代码可能是正确的。它只是输入了错误的值。

标签: c# datetime unix epoch date-conversion


【解决方案1】:

问题是 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 得到的 epoch 不是你想要的。

您应该减去时区偏移量(以分钟为单位乘以 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

【讨论】:

  • 好的,有道理,新日期是当地时间。但是,如何在 C# 中确保转换时间戳?不幸的是,我无法更改时间戳的来源,它来自服务提供商。
  • 是的,我知道问题出在 Javascript,但是我不太可能更改它,因为它来自服务提供商。
  • @PedroCosta 你所做的在 C# 中是正确的。垃圾进垃圾出。正如 Derek 所指出的,您代码中的时间戳 (3869074800) 不是午夜 (UTC)。如果这是您所拥有的并且无法更改它,那么除了假设它是当地时间 (GMT) 并相应地捏造之外,您无能为力。
  • 我想我可能已经破解了它,看看我的编辑,你怎么看?
  • 如果时间戳表示 GMT+0000(非 DST),则 dt.Hour 小时将为零,现在您已获得 24 小时后的时间。最好假设时间戳是本地时间并且是格林威治标准时间。
【解决方案2】:

根据https://www.epochconverter.com/,UNIX 时间戳 3869074800 是 2092 年 8 月 8 日晚上 11:00:00,因此 C# 在 GMT 中正确显示它。 UTC 和 GMT……不一样,但为了便于阅读,准确地说可以将它们视为相同。

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

【讨论】:

  • 这正是我的观点,如果时间戳 3869074800 是 UTC 但在 C# 上却不是...我需要 c# 在晚上 11 点返回第 9 个而不是第 8 个
  • document.write(new Date(3869074800 *1000)) 按预期返回日期..
  • 我已编辑我的答案以使其更清晰。 3869074800 不是正确的 UNIX 时间戳。它可能会使用您从中获取的任何内容正确地来回转换(似乎不是 C# 的内置内容?),但它不是 UTC。
  • 正确,它是一个 SaaS 产品 (Agile CRM) 日期存储在时间戳中,我猜他们没有将它存储在 UTC 中。
猜你喜欢
  • 1970-01-01
  • 2021-08-06
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
  • 1970-01-01
  • 1970-01-01
  • 2018-01-04
相关资源
最近更新 更多