如何在C#中将Unix 时代转换为实时?(始于1970年1月1日的时代)
如何在C#中将Unix 时代转换为实时?(始于1970年1月1日的时代)
Answers:
我假设您的意思是Unix time,它定义为自1970年1月1日午夜(UTC)起的秒数。
public static DateTime FromUnixTime(long unixTime)
{
return epoch.AddSeconds(unixTime);
}
private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
AddXYZ
方法即可。
.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;
'DateTimeOffset' does not contain a definition for 'FromUnixTimeSeconds'
我将如何解决这个问题?
归功于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
回报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移到epoch时创建epoch DateTime实例,也可以执行以下操作:
public static long ToUnixTime(this DateTime date)
{
return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}
ToUnixTime
仅当日期在Utc中时才能正常工作。添加支票,或将其转换。(我个人更喜欢支票)
milliseconds
没有秒!
AddMilliseconds
并且应该使用Double NOT Float。否则,您将获得错误的时间。
您实际上想要的是AddMilliseconds(毫秒),而不是秒。增加秒数将使您超出范围。
AddMillis
出发,您显然是想要的;如果您是从几秒钟开始,则您显然是想要的AddSeconds
。
如果您想要更好的性能,可以使用此版本。
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在内部的工作方式。
使用方法DateTimeOffset.ToUnixTimeMilliseconds() 返回自1970-01-01T00:00:00.000Z以来经过的毫秒数。
只有Framework 4.6或更高版本才支持
var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
在此处有充分的记录DateTimeOffset.ToUnixTimeMilliseconds
另一种方法是使用以下内容
long EPOCH = DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1,0,0,0,0).Ticks;
要仅用几秒钟获得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);
}
.Ticks
,则可以从DateTime减法中获得一个不错的TimeSpan实例。
我使用以下扩展方法进行时代转换
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 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年加毫秒数。
如果您未使用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;
}
using Microsoft.IdentityModel.Tokens; ... EpochTime.GetIntDate(dateTime);
如果您需要转换包含的timeval结构(秒,微秒)UNIX time
而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);
}
这是我的解决方案:
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);
}