如何在c#中转换纪元时间?

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

317033 次浏览

更新2020

您可以使用DateTimeOffset来实现这一点

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

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

DateTime dateTime = dateTimeOffset.DateTime;

原来的答案

我假定你指的是Unix时间,它被定义为自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);
}

感谢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返回一个KindUtcDateTime,这很好,但上面的ToUnixTime更可疑,因为它没有说明给定的date是什么样的DateTime。为了允许dateKindUtcDateTime0,使用DateTime2:

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

ToUniversalTimeLocal(或Unspecified) DateTime转换为Utc

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

public static long ToUnixTime(this DateTime date)
{
return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}
// 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);
}

应该对DateTime对象使用ToUniversalTime()。

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

以下是我的解决方案:

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

如果你需要在不损失精度的情况下将包含UNIX timetimeval结构(秒,微秒)转换为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);
}

.Net的最新版本(v4.6)刚刚增加了对Unix时间转换的内置支持。这包括以秒或毫秒表示的到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();

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

DateTime dateTime = dateTimeOffset.UtcDateTime;

如果你没有使用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;
}

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

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


}

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

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时间戳。

使用DateTimeOffset.ToUnixTimeMilliseconds ()方法返回从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时间将溢出。

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

.Net 4.6及以上版本请使用

DateTimeOffset.Now.ToUnixTimeSeconds()

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

    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年就不可能增加毫秒。

目前您可以简单地使用

DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()

它将以64位的形式返回