C#中的Unix时间转换

37

我正在尝试获取Unix时间下的GMT时间。我使用以下代码:


        public static long GetGMTInMS()
        {
            // 获取当前时间的协调世界时(UTC)并将其转换为时间戳
            var unixTime = DateTime.Now.ToUniversalTime() -
                new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return (long)unixTime.TotalMilliseconds; // 返回毫秒级时间戳 }

要将Unix时间转换回DateTime对象,我使用以下代码:


        // 将 Unix 时间戳转换为日期时间
        public static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
        {
            // 创建一个以 1970 年 1 月 1 日 0 时 0 分 0 秒为基准的 DateTime 对象 
            System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            
            // 添加 Unix 时间戳所表示的毫秒数并将其转换为本地时间
            dtDateTime = dtDateTime.AddMilliseconds(unixTimeStamp).ToLocalTime();
            
            // 返回转换后的日期时间对象
            return dtDateTime;
        }

运行代码时,GetGMTInMS() 返回1320249196267。当我把它传递给 UnixTimeStampToDateTime(),我得到的结果是{11/2/2011 11:53:16 AM}

这很好。那是我运行代码时的正确时间。问题在于,当我尝试将1320249196267放入 Unix 时间转换器(例如此处),它返回了完全错误的时间。

另一个问题是,我在东部时区。这返回了我的时区的时间。这是 DateTime 对象处理的还是我没有获取到 GMT?

2个回答

134

"Unix时间戳"在大多数情况下指的是自纪元以来的秒数,而不是毫秒...请注意!但是,像Java这样的工具使用的是"自纪元以来的毫秒数",这可能是您实际关心的内容 - 尽管您展示的工具可能不是如此。这确实取决于您需要什么。

此外,您不应该对本地时间进行任何操作,应该始终坚持使用世界协调时间。

我的做法是:

private static readonly DateTime UnixEpoch =
    new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

public static long GetCurrentUnixTimestampMillis()
{
    return (long) (DateTime.UtcNow - UnixEpoch).TotalMilliseconds;
}

public static DateTime DateTimeFromUnixTimestampMillis(long millis)
{
    return UnixEpoch.AddMilliseconds(millis);
}

public static long GetCurrentUnixTimestampSeconds()
{
    return (long) (DateTime.UtcNow - UnixEpoch).TotalSeconds;
}

public static DateTime DateTimeFromUnixTimestampSeconds(long seconds)
{
    return UnixEpoch.AddSeconds(seconds);
}

2
返回类型应该是 ulong 而不是 long,因为 UNIX 时间戳不能为负。 - Erik Schierboom
9
@ErikSchierboom:这要看具体情况——在很多场景中,“自 Unix 纪元以来的秒数”或“自 Unix 纪元以来的毫秒数”可以是负数。考虑到long.MaxValue 秒还有很长时间才到,我认为更灵活地接受1970年以前的负时间值更合理。 - Jon Skeet
3
最近,您现在可以使用 DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()。 - code5

5

UNIX时间是自1970年1月1日以来的秒数,而不是毫秒。将代码更改为使用秒而不是毫秒,它应该可以正常工作。


我认为在OP的代码中没有任何使用本地时间的理由。虽然在这种情况下我不认为它会导致任何问题,但它会使代码更难以验证。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接