Unix 时间戳具有 UTC 差异

问题描述

我需要将日期和时间字符串转换为纪元时间戳。我得到了 11 小时的时差(我认为这是 UTC 与本地时差)。

using System;
                    
public class Program
{
    public static void Main()
    {
        var output = StringDatetoUnixString("08-02-2021 23:59:59","dd-MM-yyyy HH:mm:ss");
        Console.WriteLine($"Result : {output}");
        Console.WriteLine("Expected: 1612789199000");
        if(output == 1612789199000)
        {
            Console.WriteLine("Match");
        }
        else
        {
            Console.WriteLine("Not a match");
        }
    }
    
    public static double StringDatetoUnixString(string dateString,string currentFormat)
    {
        var epoch = new DateTime(1970,1,DateTimeKind.Utc);
        DateTime date = DateTime.ParseExact(dateString,currentFormat,System.Globalization.CultureInfo.InvariantCulture);
        return Convert.ToInt64((date - epoch).TotalMilliseconds);
    }
}

Sample from https://www.freeformatter.com/epoch-timestamp-to-date-converter.html

当我检查时,epoch 和 local 是 UTC,但是 (UTC-UTC)。TotalMilliseconds,当转换回来时是本地时间。 我真的很感激我可以更新 StringDatetoUnixString 函数,以便 Main 可以按预期工作。

解决方法

你有没有试过这个。获取unix时间戳:

DateTimeOffset.Now.ToUnixTimeMilliseconds();

并将时间戳转换为日期时间:

return new DateTimeOffset(1970,1,TimeSpan.Zero).AddMilliseconds(1612789199000).UtcDateTime;
,

问题是因为您减去了两个具有不同含义的 DateTime 值。您的 epoch 变量基于 UTC 并且其 Kind 属性设置为 DateTimeKind.Utc,而您的 date 变量基于本地时间并且其 Kind 属性设置到DateTimeKind.Unspecified

但是,在减去或比较 DateTime 值时 - 不考虑 Kind 属性。该操作完全基于 Ticks 属性。

将此与 DateTimeOffset 值进行对比,其中偏移量被考虑用于此类操作。

有几种不同的方法可以在代码中解决这个问题,并且仍然可以从基于本地时间的日期/时间字符串调整为 Unix 时间戳(本质上是基于 UTC):

  • 您可以在解析后将 date 值转换为 UTC,然后再减去:

    DateTime epoch = new DateTime(1970,DateTimeKind.Utc);
    DateTime dateTime = DateTime.ParseExact(dateString,currentFormat,CultureInfo.InvariantCulture);
    return (dateTime.ToUniversalTime() - epoch).TotalMilliseconds;
    
  • 您可以告诉 DateTime.ParseExact 您希望输入字符串假定为本地时间并且输出值应调整为 UTC 的行为。这是通过组合 AssumeLocalAdjustToUniversal DateTimeStyles 标志来完成的,如下所示:

    DateTime epoch = new DateTime(1970,CultureInfo.InvariantCulture,DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal);
    return (dateTime - epoch).TotalMilliseconds;
    
  • 您可以将该值解析为 DateTimeOffset 而不是 DateTime。这样做时,如果输入字符串中没有偏移量,则使用本地时区。这种方法还具有能够使用内置 ToUnixTimeMilliseconds 方法的优点:

    DateTimeOffset dateTimeOffset = DateTimeOffset.ParseExact(dateString,CultureInfo.InvariantCulture);
    return dateTimeOffset.ToUnixTimeMilliseconds();
    

请注意,在所有三种情况下,我都假设 using System.Globalization; 包含在您的程序顶部,并且我从结果中删除了 Convert.ToInt64,因为它是无关紧要的。