如何在C#中转换时间?


377

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


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

8
从纪元开始的时间是自UTC 1970年1月1日以来的秒数。
泰勒·莱斯

13
@Taylor这是Unix时间的时代,也许是正确的,但这不是唯一有效的时代。Unix时间用户不应在这一点上混淆自己。
Joel Coehoorn

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

Answers:


563

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

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

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

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

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

213

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

1
我得到了'DateTimeOffset' does not contain a definition for 'FromUnixTimeSeconds'我将如何解决这个问题?
快乐鸟

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

同样的事情-4.7.2且没有DateTimeOffset的FromUnixTimeMilliseconds方法...
Mikhail_Sam

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

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

169

归功于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回报DateTimeKindUtc,这是很好的,但上面ToUnixTime更加犯罪嫌疑人不占什么样的DateTime给定date的。为了允许dateKind存在无论是UtcLocal,使用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);
}

ToUniversalTimeLocal(或Unspecified)转换DateTimeUtc

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

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

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

2
刚刚花了一个小时来弄清楚为什么它不起作用。你需要工作,milliseconds 没有秒!
KristianB 2012年

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

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

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

25

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


这是为什么?epochconverter.com它说您增加自1/1/970以来的秒数,而不是毫秒。
Jamie R Rytlewski 2014年

如果您是从ms AddMillis出发,您显然是想要的;如果您是从几秒钟开始,则您显然是想要的AddSeconds

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

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

9

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

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

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

并转换EpochDateTime下面的方法

private DateTime Epoch2UTCNow(int epoch) 
{
    return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(epoch); 
}

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

8
// 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对象。


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

    }

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

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

0

如果您需要转换包含的timeval结构(秒,微秒)UNIX timeDateTime又不损失精度,可以采用以下方法:

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


-4

这是我的解决方案:

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

7
这说明leap年和leap秒等吗?
乔德雷尔2012年

1
为了扩展之前的评论,以下是一个简短的视频,解释了为什么时间很复杂以及为什么您不应该自己尝试做:youtube.com/watch?
v=-5wpm
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.