447

如何在 C# 中将 Unix纪元时间转换为实时时间?(从 1970 年 1 月 1 日开始的纪元)

4

14 回答 14

675

2020 年更新

您可以使用 DateTimeOffset 执行此操作

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(epochSeconds);
DateTimeOffset dateTimeOffset2 = DateTimeOffset.FromUnixTimeMilliseconds(epochMilliseconds);

如果您需要DateTime对象而不是DateTimeOffset,那么您可以调用该DateTime属性

DateTime dateTime = dateTimeOffset.DateTime;

原始答案

我假设您的意思是Unix time,它定义为自 1970 年 1 月 1 日午夜 (UTC) 以来的秒数。

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

public static DateTime FromUnixTime(long unixTime)
{
    return epoch.AddSeconds(unixTime);
}
于 2010-05-21T16:04:43.253 回答
235

最新版本的.Net (v4.6)刚刚添加了对 Unix 时间转换的内置支持。这包括以秒或毫秒表示的往返 Unix 时间。

  • Unix 时间以秒为单位DateTimeOffset

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
  • DateTimeOffset以秒为单位的 Unix 时间:

long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
  • Unix 时间以毫秒为单位DateTimeOffset

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
  • DateTimeOffset以毫秒为单位的 Unix 时间:

long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds();

注意:这些方法转换为DateTimeOffset. 要获得DateTime表示,只需使用以下DateTimeOffset.DateTime属性:

DateTime dateTime = dateTimeOffset.UtcDateTime;
于 2014-10-06T22:38:01.157 回答
183

归功于 LukeH,我整理了一些易于使用的扩展方法:

public static DateTime FromUnixTime(this long unixTime)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return epoch.AddSeconds(unixTime);
}

public static long ToUnixTime(this DateTime date)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return Convert.ToInt64((date - epoch).TotalSeconds);
}

请注意下面来自 CodesInChaos 的评论,上面FromUnixTime返回 aDateTime和 a KindUtc这很好,但上面ToUnixTime更令人怀疑,因为它没有说明DateTime给定date的类型。要允许date'Kind成为Utcor Local,请使用ToUniversalTime

public static long ToUnixTime(this DateTime date)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return Convert.ToInt64((date.ToUniversalTime() - epoch).TotalSeconds);
}

ToUniversalTime将 a Local(or Unspecified)转换DateTimeUtc.

如果你不想在从 DateTime 移动到纪元时创建纪元 DateTime 实例,你也可以这样做:

public static long ToUnixTime(this DateTime date)
{
    return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}
于 2011-10-21T03:44:19.567 回答
25

您实际上想要添加毫秒(毫秒),而不是秒。添加秒数会给你一个超出范围的异常。

于 2012-03-19T22:02:14.590 回答
19

Unix 纪元是自 1970 年 1 月 1 日午夜 UTC 时间以来经过的秒数减去闰秒。这意味着在 1970 年 1 月 1 日午夜,Unix 时间为 0。Unix 纪元也称为 Unix 时间、POSIX 时间或 Unix 时间戳。

使用.Net Framework 4.6或更高版本 使用方法DateTimeOffset.ToUnixTimeMilliseconds() 它返回自 以来经过的毫秒数1970-01-01T00:00:00.000Z

var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

这里有很好的记录DateTimeOffset.ToUnixTimeMilliseconds

要在几秒钟内获得EPOCH,您可以使用

 var Epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;

并使用以下方法转换EpochDateTime

private DateTime Epoch2UTCNow(int epoch) 
{
    return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(epoch); 
}

但由于

在 Unix 时间表示为带符号 32 位数字的系统上,表示将在 231 - 1 秒后结束,这将发生在 2038 年 1 月 19 日 3:14:08 UTC。这被称为 2038 年问题,32 位带符号的 Unix 时间将溢出。

我建议只要不保存intEPOCH_2038_SAFE

long EPOCH_2038_SAFE = 
(long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;

如果您正在寻找更多,请使用以下更精确的刻度

long EPOCH = DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1,0,0,0,0).Ticks;
于 2019-05-29T15:13:24.653 回答
13

如果你想要更好的性能,你可以使用这个版本。

public const long UnixEpochTicks = 621355968000000000;
public const long TicksPerMillisecond = 10000;
public const long TicksPerSecond = TicksPerMillisecond * 1000;

//[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static DateTime FromUnixTimestamp(this long unixTime)
{
    return new DateTime(UnixEpochTicks + unixTime * TicksPerSecond);
}

从 net471 下的快速基准测试 (BenchmarkDotNet) 我得到这个数字:

        Method |     Mean |     Error |    StdDev | Scaled |
-------------- |---------:|----------:|----------:|-------:|
         LukeH | 5.897 ns | 0.0897 ns | 0.0795 ns |   1.00 |
      MyCustom | 3.176 ns | 0.0573 ns | 0.0536 ns |   0.54 |

比LukeH 的版本快 2 倍(如果性能好的话)

这类似于 DateTime 内部的工作方式。

于 2018-01-28T17:01:19.550 回答
8
// convert datetime to unix epoch seconds
public static long ToUnixTime(DateTime date)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return Convert.ToInt64((date.ToUniversalTime() - epoch).TotalSeconds);
}

应将 ToUniversalTime() 用于 DateTime 对象。

于 2012-03-13T06:36:46.407 回答
5

我使用以下扩展方法进行纪元转换

public static int GetEpochSeconds(this DateTime date)
    {
        TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);
        return (int)t.TotalSeconds;
    }

public static DateTime FromEpochSeconds(this DateTime date, long EpochSeconds)
    {
        var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        return epoch.AddSeconds(EpochSeconds);

    }
于 2015-10-31T06:32:25.257 回答
5

目前你可以简单地使用

DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()

它将作为 64 位长返回

于 2020-06-18T13:26:54.103 回答
2

不用担心使用毫秒或秒,只需执行以下操作:

    public static DateTime _ToDateTime(this long unixEpochTime)
    {
        DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        var date = epoch.AddMilliseconds(unixEpochTime);

        if (date.Year > 1972)
            return date;

        return epoch.AddSeconds(unixEpochTime);
    }

如果纪元时间以秒为单位,那么您将无法通过 1972 年添加毫秒。

于 2019-10-16T18:45:40.610 回答
1

如果您不使用 4.6,这可能会有所帮助来源: System.IdentityModel.Tokens

    /// <summary>
    /// DateTime as UTV for UnixEpoch
    /// </summary>
    public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

    /// <summary>
    /// Per JWT spec:
    /// Gets the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the desired date/time.
    /// </summary>
    /// <param name="datetime">The DateTime to convert to seconds.</param>
    /// <remarks>if dateTimeUtc less than UnixEpoch, return 0</remarks>
    /// <returns>the number of seconds since Unix Epoch.</returns>
    public static long GetIntDate(DateTime datetime)
    {
        DateTime dateTimeUtc = datetime;
        if (datetime.Kind != DateTimeKind.Utc)
        {
            dateTimeUtc = datetime.ToUniversalTime();
        }

        if (dateTimeUtc.ToUniversalTime() <= UnixEpoch)
        {
            return 0;
        }

        return (long)(dateTimeUtc - UnixEpoch).TotalSeconds;
    }    
于 2015-10-14T05:00:51.640 回答
0

如果您需要在不丢失精度的情况下将包含的timeval结构(秒、微秒)转换为,方法如下UNIX timeDateTime

DateTime _epochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private DateTime UnixTimeToDateTime(Timeval unixTime)
{
    return _epochTime.AddTicks(
        unixTime.Seconds * TimeSpan.TicksPerSecond +
        unixTime.Microseconds * TimeSpan.TicksPerMillisecond/1000);
}
于 2014-06-06T00:11:15.470 回答
0

由于 .Net 4.6 及更高版本,请使用 DateTimeOffset.Now.ToUnixTimeSeconds()

于 2019-10-11T10:32:59.457 回答
-5

这是我的解决方案:

public long GetTime()
{
    DateTime dtCurTime = DateTime.Now.ToUniversalTime();

    DateTime dtEpochStartTime = Convert.ToDateTime("1/1/1970 0:00:00 AM");

    TimeSpan ts = dtCurTime.Subtract(dtEpochStartTime);

    double epochtime;

    epochtime = ((((((ts.Days * 24) + ts.Hours) * 60) + ts.Minutes) * 60) + ts.Seconds);   

    return Convert.ToInt64(epochtime);
}
于 2012-07-18T10:13:42.793 回答