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

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

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

person Mark Ingram    schedule 30.10.2008    source источник
comment
В следующем выпуске .NET 4.6 (который будет выпущен позже в этом году) эта поддержка будет реализована. См. DateTimeOffset.FromUnixTimeSeconds и _ 2_. Также существуют методы для миллисекундного unix-времени.   -  person Jeppe Stig Nielsen    schedule 05.05.2015


Ответы (17)


Вот что вам понадобится:

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;
}
person ScottCher    schedule 30.10.2008
comment
AddSeconds, похоже, не очень хорошо работает для значений меньше 0,1 миллисекунды (iirc) - person Luk; 03.11.2008
comment
@Luk да, некоторые методы DateTime / TimeSpan необъяснимо нарушены на доли миллисекунды ... - person Roman Starkov; 16.04.2011
comment
Время в Windows обрабатывается HAL и с точностью до 1–15 мс. Если кому-то интересно, дополнительная информация доступна на Внутренних компонентах Windows на странице 112. - person Jim Schubert; 13.04.2012
comment
Этот ответ рискует сократить секунды ... Двойное число - это плавающее число. Аргумент должен иметь вид int / long / etc. - person ccook; 04.03.2013
comment
Эти методы должны принимать long или int, а не double. Кроме того, для меток времени Java нет необходимости делить на 1000 и округлять. Просто сделай dtDateTime.AddMilliseconds(javaTimeStamp).ToLocalTime(); - person Justin Johnson; 22.02.2014
comment
Вы просто скучали наоборот? Как преобразовать DateTime в метку времени? - person Jonny; 08.12.2014
comment
Для .NET Framework 4.6 и более поздних версий теперь есть static DateTimeOffset.FromUnixMilliseconds и DateTimeOffset.ToUnixMilliseconds. - person rookie1024; 18.05.2016
comment
System.DateTime dtDateTime = новый DateTime.MinValue; должно быть достаточно. - person needfulthing; 22.08.2018
comment
Лучший способ выполнить вычисления без ошибок с плавающей запятой: unixEpoch.AddTicks( TimeSpan.TicksPerSecond * seconds ) - person Soonts; 27.09.2019

последняя версия .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;
person i3arnon    schedule 06.10.2014
comment
com / en-us / dotnet / api / - person yedevtxt; 12.07.2017
comment
Это не переводит время в местное время. Вы получите UTC, если используете DateTimeOffset.FromUnixTimeSeconds (). - person Berend de Boer; 28.08.2017
comment
@BerenddeBoer Вы можете использовать ToLocalTime, если хотите. - person i3arnon; 28.08.2017
comment
Чтобы узнать текущее время, вы можете использовать long unixMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds(); - person Dan Diplo; 04.04.2019
comment
Абсолютно качественный ответ. - person user1514042; 21.07.2020

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;
}
person Dmitry Fedorkov    schedule 29.09.2011
comment
Я получаю разные результаты, если бегу из облака или с локального хоста. В этом есть смысл? - person Rony Tesler; 19.06.2021

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

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

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

TimeSpan span = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0,DateTimeKind.Utc));
double unixTime = span.TotalSeconds;
person gl051    schedule 13.04.2012
comment
но это возвращает двойной, я думаю, нужно забрасывать долго? - person knocte; 06.05.2013

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

Методы .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;
}
person Felix Keil    schedule 23.07.2014
comment
Это правильный ответ. Другие получают неправильный часовой пояс при преобразовании обратно из метки времени. - person IamIC; 20.06.2017
comment
для DateTime- ›Java просто [код] return (long) unixTimeStampInTicks / TimeSpan.TicksPerMilliSecond; [/код] - person Max; 17.02.2018

Вы можете использовать DateTimeOffset.

Например. У меня есть объект DateTime

var dateTime1=DateTime.Now;

Если я хочу преобразовать его в метки времени Unix, я могу добиться следующего

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

Если вы хотите преобразовать unix timeStamp в обычный DateTime, вы можете использовать этот фрагмент кода:

var dateTime2 = DateTimeOffset.FromUnixTimeSeconds(unixTimeSeconds).LocalDateTime;

or

var dateTime2 = DateTimeOffset.FromUnixTimeSeconds(unixTimeSeconds).UtcDateTime;

Для получения дополнительной информации перейдите по этой ссылке:

Метод DateTimeOffset.ToUnixTimeSeconds,
DateTimeOffset.FromUnixTimeSeconds

person Ramil Aliyev    schedule 23.04.2020
comment
если вы буквально хотите Now как время UNIX, вы можете использовать DateTimeOffset.UtcNow.ToUnixTimeSeconds() - person Simon_Weaver; 17.12.2020

См. 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);
    }
}
person orad    schedule 28.04.2015
comment
Это хорошо, но я бы предложил небольшое изменение: использование типа long следует изменить на Int32 или int. Длинный подразумевает, что есть значительная точность, но это не так. Вся математика точна только до 1 секунды, поэтому Int32 будет более намекающим на то, что вы ожидаете от временной метки Unix. - person JamesHoux; 14.12.2018
comment
Я думаю, это связано с тем, что DateTime.Ticks является Int64 (длинным), поэтому они избегают лишнего неконтролируемого приведения. - person orad; 14.12.2018

Чтобы дополнить ответ Скотта Чера, я недавно столкнулся с раздражающим сценарием, когда временные метки 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);
}
person Chris Thoman    schedule 07.10.2012
comment
Будьте осторожны, когда не используете аргумент DateTimeKind, поскольку сконструированный DateTime будет в локальном времени компьютера (спасибо за код, Крис)! - person Sam Grondahl; 17.09.2013
comment
Будьте осторожны - это не будет работать для временных меток unix для дат до 11 января 1978 года, если они представлены в миллисекундах. Метка даты unix 253324800 (секунд) дает правильную дату 11.01.1978, тогда как миллисекундное представление 253324800000 дает дату 18.07.9997. Возможно, это сработало для вашего набора данных, но это не общее решение. - person Øyvind; 17.05.2018

Преобразование времени Unix - это новая возможность в .NET Framework 4.6.

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

static DateTimeOffset FromUnixTimeSeconds(long seconds)
static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds)
long DateTimeOffset.ToUnixTimeSeconds()
long DateTimeOffset.ToUnixTimeMilliseconds()
person Fred    schedule 23.07.2015
comment
Это не дает вам местного времени, вы получаете UTC. - person Berend de Boer; 28.08.2017
comment
@BerenddeBoer Это разумное значение по умолчанию. После этого вы можете применить произвольное смещение по своему усмотрению. - person Deilan; 21.11.2017
comment
@BerenddeBoer Это неправильно понимает, что такое время unix. Время Unix - секунды с полуночи 1 января 1970 г. по всемирному координированному времени. Неважно, где вы находитесь, количество секунд с той эпохи не меняется. Преобразование его в удобочитаемые дисплеи местного времени, как и должно быть, отделены от этого универсального представления. - person Tanktalus; 11.09.2018

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

Написано простейшее расширение, которое у нас работает. Если кто его ищет ...

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

        return DateTimeOffset.FromUnixTimeSeconds(long.Parse(unixTimeStamp)).UtcDateTime;
    }
}
person Riyaz Hameed    schedule 04.09.2019

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

var dateTime = DateTimeOffset.FromUnixTimeSeconds(unixDateTime).DateTime;
person Yang Zhang    schedule 16.02.2019

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 по мере необходимости.

person Hot Licks    schedule 12.08.2014

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

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

person Luk    schedule 30.10.2008
comment
Unix - это секунда прошедшей эпохи - 1/1/70. - person ScottCher; 30.10.2008

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

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

person madan    schedule 18.06.2018

Для .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);
    }
}
person superlogical    schedule 28.05.2015
comment
Я не понимаю. В .NET 4.6 в BCL уже есть эти методы (см., Например, мой комментарий к вопросу выше или некоторые другие новые ответы (2015 г.). Итак, какой смысл писать их снова? Вы имели в виду, что ваш ответ был решение для версий до до 4.6? - person Jeppe Stig Nielsen; 19.02.2016