2008-10-30 3 views
552

Существует этот пример кода, но затем он начинает говорить о проблемах миллисекунды/наносекунды.Как преобразовать временную метку Unix в DateTime и наоборот?

Тот же вопрос находится на MSDN, Seconds since the Unix epoch in C#.

Это то, что я получил до сих пор:

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

Предстоящий ** NET 4,6 ** (будет выпустить позже в этом году) вводит поддержку для этого.. См. [`DateTimeOffset.FromUnixTimeSeconds`] (https://msdn.microsoft.com/en-us/library/system.datetimeoffset.fromunixtimeseconds.aspx) и [` DateTimeOffset.ToUnixTimeSeconds`] (https://msdn.microsoft. com/en-us/library/system.datetimeoffset.tounixtimeseconds.aspx). Существуют также методы для миллисекундного unix-времени. – 2015-05-05 09:29:29

ответ

773

Вот что вам нужно:

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

Или для Java (который отличается тем, что метка времени в миллисекундах, а не в секундах):

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

AddSeconds не очень хорошо себя ведет при значениях менее 0,1 миллисекунды (iirc) – Luk 2008-11-03 17:32:40

+0

@Luk да, ряд методов DateTime/TimeSpan [необъяснимо сумиминезубренный дефект] (http://stackoverflow.com/questions/4672359/why-does-timespan-fromsecondsdouble-round-to-milliseconds) ... – 2011-04-15 20:36:59

+4

Время в Windows обрабатывается HAL и только близко к точности в пределах от 1 мс до 15 мс. Дополнительная информация доступна в [Windows Internals] (http://shop.oreilly.com/product/0790145305930.do) на стр. 112, если кому-то интересно. – 2012-04-13 14:59:30

2

UNIX-тик 1 второе (если я хорошо помню), и .NET тик 100   наносекунд.

Если у вас возникли проблемы с наносекундами, вы можете попробовать использовать значение AddTick (10000000 *).

+3

Unix - это секунды прошлой эпохи - это 1/1/70. – ScottCher 2008-10-30 14:44:16

4

я нашел правильный ответ только путем сравнения преобразование в 1/1/1970 без локальной настройки времени;

DateTime date = new DateTime(2011, 4, 1, 12, 0, 0, 0); 
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0); 
TimeSpan span = (date - epoch); 
double unixTime =span.TotalSeconds; 
199

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

«UTC не изменяется при смене сезонов, но местное время или гражданское время может измениться, если временная зона юрисдикции наблюдается переход на летнее время (летнее время). Например, UTC на 5 часов раньше (то есть позже в день, чем) местное время на восточном побережье Соединенных Штатов в зимний период, но на 4 часа вперед, в то время как летнее время наблюдается там ».

Так что это мой код:

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

В дополнение ответа 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

мне нужно преобразовать timeval struct (секунды, микросекунды), содержащий 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); 
} 
14

Будьте осторожны, если вам нужна точность выше миллисекунды!

Методы .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); 
} 

DateTime -> 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; 
} 
3
DateTime unixEpoch = DateTime.ParseExact("1970-01-01", "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture); 
DateTime convertedTime = unixEpoch.AddMilliseconds(unixTimeInMillisconds); 

Конечно, можно сделать unixEpoch глобальный статический, поэтому он должен появляться только один раз в вашем проекте, и можно использовать AddSeconds, если время UNIX находится в секундах.

Чтобы пойти другим путем:

double unixTimeInMilliseconds = timeToConvert.Subtract(unixEpoch).TotalMilliseconds; 

Truncate для Int64 и/или использовать TotalSeconds по мере необходимости.

219

latest version of .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; 
12

См 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); 
    } 
} 
-1

Для .NET 4.6 и более поздних:

public static class UnixDateTime 
{ 
    public static DateTimeOffset FromUnixTimeSeconds(long seconds) 
    { 
     if (seconds < -62135596800L || seconds > 253402300799L) 
      throw new ArgumentOutOfRangeException("seconds", seconds, ""); 

     return new DateTimeOffset(seconds * 10000000L + 621355968000000000L, TimeSpan.Zero); 
    } 

    public static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds) 
    { 
     if (milliseconds < -62135596800000L || milliseconds > 253402300799999L) 
      throw new ArgumentOutOfRangeException("milliseconds", milliseconds, ""); 

     return new DateTimeOffset(milliseconds * 10000L + 621355968000000000L, TimeSpan.Zero); 
    } 

    public static long ToUnixTimeSeconds(this DateTimeOffset utcDateTime) 
    { 
     return utcDateTime.Ticks/10000000L - 62135596800L; 
    } 

    public static long ToUnixTimeMilliseconds(this DateTimeOffset utcDateTime) 
    { 
     return utcDateTime.Ticks/10000L - 62135596800000L; 
    } 

    [Test] 
    public void UnixSeconds() 
    { 
     DateTime utcNow = DateTime.UtcNow; 
     DateTimeOffset utcNowOffset = new DateTimeOffset(utcNow); 

     long unixTimestampInSeconds = utcNowOffset.ToUnixTimeSeconds(); 

     DateTimeOffset utcNowOffsetTest = UnixDateTime.FromUnixTimeSeconds(unixTimestampInSeconds); 

     Assert.AreEqual(utcNowOffset.Year, utcNowOffsetTest.Year); 
     Assert.AreEqual(utcNowOffset.Month, utcNowOffsetTest.Month); 
     Assert.AreEqual(utcNowOffset.Date, utcNowOffsetTest.Date); 
     Assert.AreEqual(utcNowOffset.Hour, utcNowOffsetTest.Hour); 
     Assert.AreEqual(utcNowOffset.Minute, utcNowOffsetTest.Minute); 
     Assert.AreEqual(utcNowOffset.Second, utcNowOffsetTest.Second); 
    } 

    [Test] 
    public void UnixMilliseconds() 
    { 
     DateTime utcNow = DateTime.UtcNow; 
     DateTimeOffset utcNowOffset = new DateTimeOffset(utcNow); 

     long unixTimestampInMilliseconds = utcNowOffset.ToUnixTimeMilliseconds(); 

     DateTimeOffset utcNowOffsetTest = UnixDateTime.FromUnixTimeMilliseconds(unixTimestampInMilliseconds); 

     Assert.AreEqual(utcNowOffset.Year, utcNowOffsetTest.Year); 
     Assert.AreEqual(utcNowOffset.Month, utcNowOffsetTest.Month); 
     Assert.AreEqual(utcNowOffset.Date, utcNowOffsetTest.Date); 
     Assert.AreEqual(utcNowOffset.Hour, utcNowOffsetTest.Hour); 
     Assert.AreEqual(utcNowOffset.Minute, utcNowOffsetTest.Minute); 
     Assert.AreEqual(utcNowOffset.Second, utcNowOffsetTest.Second); 
     Assert.AreEqual(utcNowOffset.Millisecond, utcNowOffsetTest.Millisecond); 
    } 
} 
5

Unix-преобразование времени является новым в .NET Framework 4.6.

Теперь вы можете легко преобразовать значения даты и времени в типы .NET Framework и время Unix. Это может потребоваться, например, при преобразовании значений времени между клиентом JavaScript и сервером .NET. Следующие интерфейсы API, которые были добавлены к DateTimeOffset structure:

static DateTimeOffset FromUnixTimeSeconds(long seconds) 
static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds) 
long DateTimeOffset.ToUnixTimeSeconds() 
long DateTimeOffset.ToUnixTimeMilliseconds() 
Смежные вопросы