Как преобразовать временную метку Unix в DateTime и наоборот?

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

Тот же вопрос относится к MSDN, Секунды с эпохи 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);
  }
}

Ответ 1

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

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

Ответ 2

В последней версии.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.UtcDateTime или DateTimeOffset.LocalDateTime:

DateTime dateTime = dateTimeOffset.UtcDateTime;

Ответ 3

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

Ответ 4

Из Википедии:

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

Итак, это мой код:

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

Чтобы дополнить ответ 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);
}

Ответ 8

Преобразование времени в Unix впервые в .NET Framework 4.6.

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

static DateTimeOffset FromUnixTimeSeconds(long seconds)
static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds)
long DateTimeOffset.ToUnixTimeSeconds()
long DateTimeOffset.ToUnixTimeMilliseconds()

Ответ 9

Я нашел правильный ответ, просто сравнив преобразование с 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;

Ответ 10

var dt = DateTime.Now; 
var unixTime = ((DateTimeOffset)dt).ToUnixTimeSeconds();

//1510396991

var dt = DateTimeOffset.FromUnixTimeSeconds(1510396991);

//[11.11.2017 10:43:11 +00: 00]

Ответ 11

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;

Обрезайте до Int64 и/или используйте TotalSeconds по мере необходимости.

Ответ 12

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

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

Ответ 13

Из .net 4.6 вы можете сделать это:

var dateTime = DateTimeOffset.FromUnixTimeSeconds(unixDateTime).DateTime;

Ответ 14

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

Ответ 15

public static class UnixTime
    {
        private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);

        public static DateTime UnixTimeToDateTime(double unixTimeStamp)
        {
            return Epoch.AddSeconds(unixTimeStamp).ToUniversalTime();
        }
    }

вы можете вызвать UnixTime.UnixTimeToDateTime(double datetime))

Ответ 16

Написано простейшее расширение, которое работает для нас. Если кто-то ищет это...

public static class DateTimeExtensions
{
    public static DateTime FromUnixTimeStampToDateTime(this string unixTimeStamp)
    {

        return DateTimeOffset.FromUnixTimeSeconds(long.Parse(unixTimeStamp)).UtcDateTime;
    }
}

Ответ 17

System.DateTimeOffset.Now.ToUnixTimeSeconds()

Ответ 18

DateTime - временная метка Unix, включая летнее время (DST)

    public static double DateTimeToUnixTimestamp(DateTime dateTime)
    {
        double unixTime = (dateTime - new DateTime(1970, 1, 1).ToLocalTime()).TotalSeconds;
        if(dateTime.IsDaylightSavingTime()) {
            unixTime -= 3600;
        }
        return unixTime;
    }

Ответ 19

Для .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);
    }
}