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

问题描述 投票:0回答:15

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

c# time epoch
15个回答
745
投票

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

243
投票

最新版本的.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;
    

190
投票
感谢 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 移动到纪元时创建纪元 DateTime 实例,您也可以这样做:

public static long ToUnixTime(this DateTime date) { return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000; }
    

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


23
投票
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;
    

14
投票
如果您想要更好的性能,可以使用此版本。

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


9
投票
// 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()。


7
投票
目前您可以简单地使用

DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
它将以 64 位长的形式返回


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

3
投票
自.Net 4.6及以上版本请使用

DateTimeOffset.Now.ToUnixTimeSeconds()
    

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 年。


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

0
投票
如果您需要将包含

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

0
投票
从纪元时间开始的日期时间(从秒开始)。

DateTime dateTime = EpochTime.DateTime(unixEpoch)
获取从 1970-01-01T0:0:0Z 起的秒数

int64 unixEpoch = EpochTime.GetIntDate(dateTime);
命名空间:

Microsoft.IdentityModel.Tokens


    


-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); }
    
© www.soinside.com 2019 - 2024. All rights reserved.