如何在C#中将Unix时代转换为实时? (始于1970年1月1日的时代)

评论

除非我缺少任何东西,否则“纪元”只是特定计时计划的起点。示例包括1/1 / 0001、1 / 1/1970和1/1/2000。它更多是方案本身的属性,而不是方案本身(例如朱利安(Julian))。

自纪元以来的时间是自UTC 1970年1月1日以来的秒数。

@Taylor这是Unix时间的纪元,也许是正确的,但这不是唯一有效的纪元。 Unix时间用户不应在这一点上感到困惑。

Dup,以及其他答案:stackoverflow.com/q/3354893/712526

#1 楼

我假设您的意思是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);
}
 

UPDATE 2020
您可以使用DateTimeOffset
 DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(epochSeconds);
DateTimeOffset dateTimeOffset2 = DateTimeOffset.FromUnixTimeMilliseconds(epochMilliseconds);
 

完成此操作,如果需要DateTime对象而不是DateTimeOffset ,则可以调用DateTime属性
 DateTime dateTime = dateTimeOffset .DateTime;
 


评论


为了使其正常工作,我必须将.AddSeconds更改为.AddMilliseconds。您将需要知道您的数字是秒还是毫秒,以便获得正确的结果。因此,例如以下日期:1406310305188(2014年7月25日)。 epochconverter.com还将让您检查转换结果。

– jrandomuser
2014年7月30日在16:58



您应该将参数类型更改为double(因为AddSeconds接受double,因此将向下转换为double),或者在方法描述中添加免责声明,即在参数的64位精度中仅保留53。

– tomosius
16年5月3日在17:04

@jrandomuser:Unix纪元时间通常表示为自纪元以来的秒数。自从大纪元以来(例如JavaScript),使用毫秒已经很普遍了,但是经典的定义是秒。底线是,只要知道您的输入值是什么(秒,毫秒,刻度线等),然后使用正确的AddXYZ方法即可。

– T.J.拥挤者
17年7月16日在8:11

首先尝试使用AddMilliseconds,如果年份仍为1970,则执行AddSeconds。这样,它将一直工作,而不必担心毫秒或秒。另外,您可以防止溢出异常。大量传递给AddSeconds将使代码崩溃

– Tono Nam
19-10-16在18:52

#2 楼

.Net(v4.6)的最新版本刚刚添加了对Unix时间转换的内置支持。这包括以秒或毫秒表示的往返Unix时间。


以秒为单位的Unix时间到DateTimeOffset




DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);




DateTimeOffset到Unix的时间,以秒为单位:



long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();


< br Unix时间以毫秒为单位:DateTimeOffset



DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);




DateTimeOffset以毫秒为单位的Unix时间:



long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds();



注意:这些方法与DateTimeOffset之间相互转换。要获得DateTime表示形式,只需使用DateTimeOffset.DateTime属性:

DateTime dateTime = dateTimeOffset.UtcDateTime;


评论


我得到的“ DateTimeOffset”不包含“ FromUnixTimeSeconds”的定义,我该如何解决呢?

–快乐鸟
17年7月24日在14:44

@HappyBird您是否在.NET 4.6或更高版本上?

– i3arnon
17年7月24日在15:31

一样-4.7.2且DateTimeOffset没有FromUnixTimeMilliseconds方法...

– Mikhail_Sam
18-10-9在8:51

我知道了。我不需要创建新对象。这是一种静态方法。

– Mikhail_Sam
18-10-9在9:23

乍一看,我发现默认值有点令人困惑。公元前1000是从毫秒转换为秒的因子。

–蓝光
6月9日在1:41



#3 楼

归功于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返回一个带有DateTimeKind是可以的,但是上面的Utc更令人怀疑,因为它并不说明给定ToUnixTime是哪种DateTime。要允许datedateKindUtc,请使用Local

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


ToUniversalTimeToUniversalTime(或LocalUnspecified转换为DateTime

如果您不希望在从DateTime移到epoch时创建epoch DateTime实例,也可以执行以下操作:

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


评论


仅当日期在Utc中时,ToUnixTime才能正常工作。添加支票,或将其转换。 (我个人更喜欢支票)

– CodesInChaos
2012年2月26日14:07

刚刚花了一个小时来弄清楚为什么这行不通。您需要以毫秒为单位而不是秒!

– KristianB
2012年9月13日14:14



@KristianB:自大纪元以来,“ Unix时间”通常是秒,而不是毫秒,尽管这些天我一直在仔细检查某人使用的定义。秒过去曾经足够好,并且以带符号的32位值为我们提供了The Epoch两侧的合理范围。 (这就是为什么在2038年1月19日凌晨3:14之后对某些人来说可能是个糟糕的时间...)由于我们通常能够抛出64位值(均为整数),因此使用毫秒是更现代的做法。和双精度IEEE-754)...

– T.J.拥挤者
13年1月20日在14:04

感谢您的代码。在创建纪元基础时,只是一个小小的建议:确保将毫秒值显式设置为0。即var epoch = new DateTime(1970,1,1,0 / * h * /,0 / * m * /,0 / * s * /,0 / * ms * /,DateTimeKind.Utc);如果未明确设置,则毫秒值似乎为1。这导致我的测试有些不一致。

–ctrlplusb
2014年4月28日13:20



您应该使用AddMilliseconds,并且应该使用Double NOT Float。否则,您将获得错误的时间。

–轴
16年3月31日在16:51

#4 楼

您实际上想要的是AddMilliseconds(毫秒),而不是秒。增加秒数将使您超出范围。

评论


这是为什么? epochconverter.com它说您增加自1/1/970以来的秒数,而不是ms。

–杰米·Rytlewski
2014年6月5日17:51

如果您要从ms出发,则显然需要AddMillis,如果您要从几秒钟开始,则显然需要AddSeconds。

–鞋子
2014年7月17日在13:28



我有一个同样的问题,我使用秒数时一直超出范围。我尝试转换的Unix时间以毫秒为单位。我以为是几秒钟。我猜一些Unix时间以毫秒为单位。

–DoodleKana
15年5月13日在17:47

Unix时间通常以秒表示,但是0.001是有效的秒数(= 1 ms)。如有疑问,请使用最大可能的精度。

–他
17年7月10日在16:56

#5 楼

使用方法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); 
}
 


评论


DateTime.Ticks-每个刻度是“一百纳秒”,使其成为需要记住的额外“东西”。如果省略两个.Ticks,则将从DateTime减法中获得一个不错的TimeSpan实例。

–user2864740
19年7月25日在17:21



#6 楼

如果您想获得更好的性能,可以使用此版本。

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

#7 楼

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


应将ToUniversalTime()用于DateTime对象。

#8 楼

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

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

    }


#9 楼

目前,您只需使用
DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()

它就会以64位长的形式返回

#10 楼

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

    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年添加毫秒。

#11 楼

如果您未使用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;
    }    


评论


感谢JWT提供的示例。顺便说一下,要使用它,只需使用:using Microsoft.IdentityModel.Tokens; ... EpochTime.GetIntDate(dateTime);

– Liquide
19年8月6日在15:38



#12 楼

如果需要在不损失精度的情况下将包含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);
}


#13 楼

从.Net 4.6及更高版本开始,请使用DateTimeOffset.Now.ToUnixTimeSeconds()

#14 楼

这是我的解决方案:

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


评论


这说明leap年和leap秒等吗?

–乔德雷尔
2012年8月22日13:41

为了扩展之前的评论,以下是一段简短的视频,解释了为什么时间很复杂以及为什么您不应该自己尝试做:youtube.com/watch?v=-5wpm-gesOY

–vmrob
15年7月19日在18:31