如何将Unix时间戳转换为日期时间格式,反之亦然?

976

这里有一个示例代码,但是接下来它开始谈论毫秒/纳秒的问题。

相同的问题出现在MSDN上,C#中自Unix时代以来的秒数

到目前为止,我得到了以下内容:

public Double CreatedEpoch
{
  get
  {
    DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime();
    TimeSpan span = (this.Created.ToLocalTime() - epoch);
    return span.TotalSeconds;
  }
  set
  {
    DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime();
    this.Created = epoch.AddSeconds(value);
  }
}

174
即将发布的 .NET 4.6(计划在今年晚些时候发布)将引入对此的支持。请参阅 DateTimeOffset.FromUnixTimeSecondsDateTimeOffset.ToUnixTimeSeconds 方法。还有毫秒级 Unix 时间的方法。 - Jeppe Stig Nielsen
7
另一个新增加的内容是DateTime.UnixEpoch。除非你需要使用DateTimeOffset而不是DateTime,否则我认为DateTime.UnixEpoch.AddMilliseconds(...)DateTimeOffset.FromUnixTimeMilliseconds(...).UtcDateTime更易读。 - M-Pixel
24个回答

1254

以下是您需要的内容:

public static DateTime UnixTimeStampToDateTime( double unixTimeStamp )
{
    // Unix timestamp is seconds past epoch
    DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
    dateTime = dateTime.AddSeconds( unixTimeStamp ).ToLocalTime();
    return dateTime;
}

或者,对于Java(与其他语言不同的是时间戳以毫秒而不是秒为单位):


public static DateTime JavaTimeStampToDateTime( double javaTimeStamp )
{
    // Java timestamp is milliseconds past epoch
    DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
    dateTime = dateTime.AddMilliseconds( javaTimeStamp ).ToLocalTime();
    return dateTime;
}

6
Windows中的时间由HAL处理,精度在1毫秒到15毫秒之间。如果有人感兴趣,可以在《Windows Internals》第112页附近找到更多信息。 - Joseph Yaduvanshi
30
此回答可能会截断秒数... double是一种浮点数。参数应为int/long等整数型变量。 - ccook
52
这些方法应该接受一个长整型或整型,而不是双精度浮点数。对于Java时间戳,不需要除以1000并四舍五入。只需执行 dtDateTime.AddMilliseconds(javaTimeStamp).ToLocalTime() 即可。 - Justin Johnson
11
你刚才是不是漏掉了“反之亦然”?我们如何将 DateTime 转换为时间戳? - Jonny
59
对于.NET Framework 4.6及以上版本,现在有static DateTimeOffset.FromUnixMillisecondsDateTimeOffset.ToUnixMilliseconds两个静态方法。 - rookie1024
显示剩余5条评论

629

最新版本的.NET(v4.6)已经增加了对Unix时间转换的内置支持,包括以秒或毫秒表示的Unix时间的转换。

  • 将Unix时间(以秒为单位)转换为UTC DateTimeOffset

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
  • DateTimeOffset转换为Unix时间(秒):

long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
  • 毫秒级Unix时间转UTC DateTimeOffset

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
  • DateTimeOffset转换为毫秒级Unix时间:

long unixTimeStampInMilliseconds = dateTimeOffset.ToUnixTimeMilliseconds();

注意:这些方法将转换为UTC DateTimeOffset。要获得DateTime表示,只需使用DateTimeOffset.UtcDateTimeDateTimeOffset.LocalDateTime属性:
DateTime dateTime = dateTimeOffset.UtcDateTime;

1
https://learn.microsoft.com/en-us/dotnet/api/system.datetimeoffset.fromunixtimeseconds?view=netframework-4.6.2#System_DateTimeOffset_FromUnixTimeSeconds_System_Int64_ - yedevtxt
1
这不会将时间转换为本地时间。如果使用DateTimeOffset.FromUnixTimeSeconds(),则会得到UTC。 - Berend de Boer
6
如果你想的话,你可以使用 ToLocalTime - i3arnon
6
获取当前时间,您可以使用 long unixMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds(); - Dan Diplo
1
一个绝对优质的答案。 - user1514042
var DateTime1 = DateTimeOffset.FromUnixTimeMilliseconds(Timestamp).LocalDateTime 和 var DateTime2 = DateTimeOffset.FromUnixTimeMilliseconds(Timestamp).UtcDateTime.ToLocalTime() 产生相同的结果。 - Ricko..

226

将DateTime转换为UNIX时间戳:

public static double DateTimeToUnixTimestamp(DateTime dateTime)
{
    return (TimeZoneInfo.ConvertTimeToUtc(dateTime) - 
           new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc)).TotalSeconds;
}

如果我从云端运行或者从本地主机运行,我会得到不同的结果。这有道理吗? - Rony Tesler

50

你可以使用 DateTimeOffset

例如,我有一个 DateTime 对象。

var dateTime1 = DateTime.Now;

如果我想将其转换为Unix时间戳,可以按以下方式实现

var unixTimeSeconds = new DateTimeOffset(dateTime1).ToUnixTimeSeconds()

如果您想将Unix时间戳转换为普通日期时间格式,可以使用以下代码片段:

var dateTime2 = DateTimeOffset.FromUnixTimeSeconds(unixTimeSeconds).LocalDateTime;
或者
var dateTime2 = DateTimeOffset.FromUnixTimeSeconds(unixTimeSeconds).UtcDateTime;

欲了解更多信息,请访问此链接:

DateTimeOffset.ToUnixTimeSeconds 方法
DateTimeOffset.FromUnixTimeSeconds 方法


2
如果您确实想要将“现在”表示为UNIX时间,可以使用“DateTimeOffset.UtcNow.ToUnixTimeSeconds()”。 - Simon_Weaver

49

来自维基百科

协调世界时(UTC)不随季节变化,但是当一个时区的管辖范围内观察夏令时时,当地时间或民用时间可能会改变。例如,在冬天,美国东海岸的当地时间比UTC晚五个小时,但在观察夏令时时,当地时间只比UTC晚四个小时。

这是我的代码:

TimeSpan span = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0,DateTimeKind.Utc));
double unixTime = span.TotalSeconds;

3
但是这个返回的是一个双精度浮点数,我猜需要转换为长整型? - knocte

40

如果您需要超过毫秒级别的精度,请小心!

.NET(v4.6)方法(例如 FromUnixTimeMilliseconds)不提供此精度。

AddSeconds 和 AddMilliseconds 也会截断双精度的微秒部分。

以下版本具有高精度:

Unix -> DateTime

public static DateTime UnixTimestampToDateTime(double unixTime)
{
    DateTime unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
    long unixTimeStampInTicks = (long) (unixTime * TimeSpan.TicksPerSecond);
    return new DateTime(unixStart.Ticks + unixTimeStampInTicks, System.DateTimeKind.Utc);
}

日期时间 -> Unix 时间戳

public static double DateTimeToUnixTimestamp(DateTime dateTime)
{
    DateTime unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
    long unixTimeStampInTicks = (dateTime.ToUniversalTime() - unixStart).Ticks;
    return (double) unixTimeStampInTicks / TimeSpan.TicksPerSecond;
}

2
这是正确答案。其他答案在从时间戳转换回来时会得到错误的时区。 - IamIC
1
对于DateTime->Java,只需返回以下代码:[code] return (long) unixTimeStampInTicks / TimeSpan.TicksPerMilliSecond; [/code] - Max

18

请查看IdentityModel.EpochTimeExtensions

public static class EpochTimeExtensions
{
    /// <summary>
    /// Converts the given date value to epoch time.
    /// </summary>
    public static long ToEpochTime(this DateTime dateTime)
    {
        var date = dateTime.ToUniversalTime();
        var ticks = date.Ticks - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).Ticks;
        var ts = ticks / TimeSpan.TicksPerSecond;
        return ts;
    }

    /// <summary>
    /// Converts the given date value to epoch time.
    /// </summary>
    public static long ToEpochTime(this DateTimeOffset dateTime)
    {
        var date = dateTime.ToUniversalTime();
        var ticks = date.Ticks - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).Ticks;
        var ts = ticks / TimeSpan.TicksPerSecond;
        return ts;
    }

    /// <summary>
    /// Converts the given epoch time to a <see cref="DateTime"/> with <see cref="DateTimeKind.Utc"/> kind.
    /// </summary>
    public static DateTime ToDateTimeFromEpoch(this long intDate)
    {
        var timeInTicks = intDate * TimeSpan.TicksPerSecond;
        return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddTicks(timeInTicks);
    }

    /// <summary>
    /// Converts the given epoch time to a UTC <see cref="DateTimeOffset"/>.
    /// </summary>
    public static DateTimeOffset ToDateTimeOffsetFromEpoch(this long intDate)
    {
        var timeInTicks = intDate * TimeSpan.TicksPerSecond;
        return new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).AddTicks(timeInTicks);
    }
}

这很好,但我建议做一个小改变:使用类型“Int32”或“int”来替换“long”。 “Long”意味着有重要的精度,但实际上并没有。所有的数学计算只精确到1秒,因此Int32更能表达Unix时间戳的预期。 - JamesHoux
3
我认为这是由于 DateTime.Ticks 是 Int64 (长整型) 类型,所以他们避免了额外的未经检查的强制转换。 - orad

14
在C# 8.0 (.NET Core 2.1)中,这是一个简单的一句话代码:
DateTime.UnixEpoch.AddSeconds(unixTimeInSeconds)

12

Unix纪元现在是DateTime类的一部分。将毫秒转换为DateTime就像这样简单:

DateTime.UnixEpoch.AddMilliseconds(millis)

11
为了补充ScottCher的回答,我最近发现自己处于一个非常烦人的情况中,我的输入数据集中有秒和毫秒UNIX时间戳任意混合在一起。下面的代码似乎可以很好地处理这个问题:
static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
static readonly double MaxUnixSeconds = (DateTime.MaxValue - UnixEpoch).TotalSeconds;

public static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
{
   return unixTimeStamp > MaxUnixSeconds
      ? UnixEpoch.AddMilliseconds(unixTimeStamp)
      : UnixEpoch.AddSeconds(unixTimeStamp);
}

1
当不使用DateTimeKind参数时要小心,因为构造的DateTime将会是计算机本地时间(感谢代码,Chris)! - Sam Grondahl
2
注意 - 如果Unix时间戳以毫秒表示,那么对于1978年1月11日之前的日期,此方法将无法正常工作。Unix日期戳253324800(秒)给出了正确的日期,即1978年1月11日,而毫秒表示253324800000则给出了9997年7月18日的日期。这种方法可能适用于您的数据集,但它并不是一个通用解决方案。 - Øyvind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接