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


当前回答

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

使用。net Framework 4.6或更高版本使用datetimeoffset . tounixtimemillisecseconds()方法,它返回从1970-01-01T00:00:00.000Z开始经过的毫秒数。

var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

DateTimeOffset在这里有很好的文档。ToUnixTimeMilliseconds

要获得纪元只有秒你可以使用

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

并使用以下方法将Epoch转换为DateTime

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

但自

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

我建议保存它,只要不是int为EPOCH_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;

其他回答

如果您没有使用4.6,这可能会有所帮助

    /// <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;
    }    

目前您可以简单地使用

DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()

它将以64位的形式返回

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

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内部的工作方式。

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

使用。net Framework 4.6或更高版本使用datetimeoffset . tounixtimemillisecseconds()方法,它返回从1970-01-01T00:00:00.000Z开始经过的毫秒数。

var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

DateTimeOffset在这里有很好的文档。ToUnixTimeMilliseconds

要获得纪元只有秒你可以使用

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

并使用以下方法将Epoch转换为DateTime

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

但自

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

我建议保存它,只要不是int为EPOCH_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;

如果您需要将包含UNIX时间的timeval结构体(秒,微秒)转换为DateTime而不损失精度,如下所示:

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);
}