Unix Timestamp 有 UTC 差异

Posted

技术标签:

【中文标题】Unix Timestamp 有 UTC 差异【英文标题】:Unix Timestamp has a UTC difference 【发布时间】:2021-05-11 16:25:46 【问题描述】:

我需要将日期和时间字符串转换为纪元时间戳。我得到了 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, 1, 0, 0, 0, DateTimeKind.Utc);
        DateTime date = DateTime.ParseExact(dateString, currentFormat, System.Globalization.CultureInfo.InvariantCulture);
        return Convert.ToInt64((date - epoch).TotalMilliseconds);
    

当我检查时,纪元和本地时间是 UTC,但是 (UTC-UTC).TotalMilliseconds,当转换回来时是本地时间。 我非常感谢我可以更新 StringDateToUnixString 函数,以便 Main 可以按预期工作。

【问题讨论】:

所以不要打电话给ToLocalTime 还是不行。我会更新问题。 你为什么期待 1612789199000 因为当我转换它时,我得到“08-02-2021 23:59:59”。我添加了freeformatter.com/epoch-timestamp-to-date-converter.html 的截图 尝试其他网站 【参考方案1】:

你试过这个吗?获取unix时间戳:

DateTimeOffset.Now.ToUnixTimeMilliseconds();

以及将时间戳转换为日期时间:

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

【讨论】:

没用,除非你想给我提供完整的代码。我可能做错了什么。【参考方案2】:

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

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

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

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

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

DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 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, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime dateTime = DateTime.ParseExact(dateString, currentFormat, CultureInfo.InvariantCulture,
    DateTimeStyles.AssumeLocal | DateTimeStyles.AdjustToUniversal);
return (dateTime - epoch).TotalMilliseconds;

您可以将值解析为DateTimeOffset 而不是DateTime。这样做时,如果输入字符串中没有偏移量,则使用本地时区。这种方法还有一个优点是可以使用内置的ToUnixTimeMilliseconds方法:

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

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

【讨论】:

以上是关于Unix Timestamp 有 UTC 差异的主要内容,如果未能解决你的问题,请参考以下文章

在 Lua 中获取 UTC UNIX 时间戳

将带时区的字符串转换为 unix 时间戳

go 的时间与时间戳计算

mysql获取当前系统日期和时间

将 unix_timestamp 转换为 spark 中的普通时间戳(以秒为单位)

impala系列: 时间函数