如何在 C# 中将 Unix 纪元时间转换为实时时间? (纪元从 1970 年 1 月 1 日开始)
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);
}
最新版本的.Net (v4.6)刚刚添加了对 Unix 时间转换的内置支持。这包括以秒或毫秒表示的往返 Unix 时间。
DateTimeOffset
:
DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
DateTimeOffset
转换为 Unix 时间(以秒为单位):
long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
DateTimeOffset
:
DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
DateTimeOffset
转换为 Unix 时间(以毫秒为单位):
long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds();
DateTimeOffset
相互转换。要获得
DateTime
表示,只需使用
DateTimeOffset.DateTime
属性:
DateTime dateTime = dateTimeOffset.UtcDateTime;
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
返回一个
DateTime
,其中
Kind
为
Utc
,这很好,但是上面的
ToUnixTime
更可疑,因为它没有解释什么给定的
DateTime
是一种
date
。要允许
date
的
Kind
为
Utc
或
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
会将
Local
(或
Unspecified
)
DateTime
转换为
Utc
。如果您不想在从 DateTime 移动到纪元时创建纪元 DateTime 实例,您也可以这样做:
public static long ToUnixTime(this DateTime date)
{
return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}
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;
并使用以下方法将Epoch
转换为
DateTime
private DateTime Epoch2UTCNow(int epoch)
{
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(epoch);
}
但是自从
在 Unix 时间表示为有符号 32 位数字的系统上,该表示将在 231 - 1 秒后结束,这将在 UTC 2038 年 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;
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 内部的工作方式。
// 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()。
DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
它将以 64 位长的形式返回
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);
}
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 年。
来源: 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;
}
UNIX time
的 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);
}
DateTime dateTime = EpochTime.DateTime(unixEpoch)
获取从 1970-01-01T0:0:0Z 起的秒数
int64 unixEpoch = EpochTime.GetIntDate(dateTime);
命名空间:Microsoft.IdentityModel.Tokens
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);
}