Как я могу преобразовать временную метку 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);
  }
}

Предстоящий .NET 4.6 (который будет выпущен позже в этом году) представляет поддержку для этого. См. Методы DateTimeOffset.FromUnixTimeSeconds и DateTimeOffset.ToUnixTimeSeconds. Существуют также методы для миллисекундного unix-времени.

Jeppe Stig Nielsen 05.05.2015 12:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
829
1
672 378
19
Перейти к ответу Данный вопрос помечен как решенный

Ответы 19

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

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

Unix - это секунда прошедшей эпохи - 1/1/70.

ScottCher 30.10.2008 17:44
Ответ принят как подходящий

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

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

AddSeconds, похоже, не очень хорошо работает для значений меньше 0,1 миллисекунды (iirc)

Luk 03.11.2008 20:32

@Luk да, несколько методов DateTime / TimeSpan - это необъяснимо субмиллисекундное нарушение ...

Roman Starkov 16.04.2011 00:36

Время в Windows обрабатывается HAL и с точностью до 1–15 мс. Более подробная информация доступна в Внутреннее устройство Windows на странице 112, если кому-то интересно.

Jim Schubert 13.04.2012 18:59

Этот ответ рискует сократить секунды ... Двойное число - это плавающее число. Аргумент должен иметь вид int / long / etc.

ccook 04.03.2013 18:59

Эти методы должны принимать long или int, а не double. Кроме того, для меток времени Java нет необходимости делить на 1000 и округлять. Вобще dtDateTime.AddMilliseconds(javaTimeStamp).ToLocalTime();

Justin Johnson 22.02.2014 01:20

Вы просто пропустили «наоборот»? Как преобразовать DateTime в метку времени?

Jonny 08.12.2014 11:31

Для .NET Framework 4.6 и выше теперь есть static DateTimeOffset.FromUnixMilliseconds и DateTimeOffset.ToUnixMilliseconds.

rookie1024 18.05.2016 05:49

System.DateTime dtDateTime = новый DateTime.MinValue; должно быть достаточно.

needfulthing 22.08.2018 17:34

Лучший способ выполнить вычисления без ошибок с плавающей запятой - это unixEpoch.AddTicks( TimeSpan.TicksPerSecond * seconds ).

Soonts 27.09.2019 02:19

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

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

От Википедия:

UTC does not change with a change of seasons, but local time or civil time may change if a time zone jurisdiction observes daylight saving time (summer time). For example, local time on the east coast of the United States is five hours behind UTC during winter, but four hours behind while daylight saving is observed there.

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

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

но это возвращает двойной, я думаю, нужно забрасывать долго?

knocte 06.05.2013 10:25

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

Будьте осторожны, когда не используете аргумент DateTimeKind, поскольку сконструированный DateTime будет соответствовать местному времени компьютера (спасибо за код, Крис)!

Sam Grondahl 17.09.2013 02:40

Будьте осторожны - это не будет работать для временных меток unix для дат до 11 января 1978 года, если они представлены в миллисекундах. Метка даты unix 253324800 (секунд) дает правильную дату 11.01.1978, тогда как миллисекундное представление 253324800000 дает дату 18.07.9997. Возможно, это сработало для вашего набора данных, но это не общее решение.

Øyvind 17.05.2018 10:24

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

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

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

Это правильный ответ. Другие получают неправильный часовой пояс при преобразовании обратно из метки времени.

IamIC 20.06.2017 13:10

для DateTime-> Java просто [код] return (long) unixTimeStampInTicks / TimeSpan.TicksPerMilliSecond; [/код]

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

последняя версия .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;
docs.microsoft.com/en-us/dotnet/api/…
yedevtxt 12.07.2017 19:35

Это не переводит время в местное время. Вы получите UTC, если используете DateTimeOffset.FromUnixTimeSeconds ().

Berend de Boer 28.08.2017 02:56

@BerenddeBoer Вы можете использовать ToLocalTime, если хотите.

i3arnon 28.08.2017 20:11

Чтобы узнать текущее время, вы можете использовать long unixMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();

Dan Diplo 04.04.2019 12:54

Абсолютно качественный ответ.

user1514042 21.07.2020 18: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);
    }
}

Это хорошо, но я бы предложил небольшое изменение: использование типа long следует изменить на Int32 или int. «Длинный» подразумевает значительную точность, но это не так. Вся математика точна только до 1 секунды, поэтому Int32 будет более намекающим на то, что вы ожидаете от метки времени Unix.

JamesHoux 14.12.2018 05:47

Я думаю, это связано с тем, что DateTime.Ticks является Int64 (длинным), поэтому они избегают лишнего неконтролируемого приведения.

orad 14.12.2018 23:42

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

Я не понимаю. В .NET 4.6 в BCL уже есть эти методы (см., Например, мой комментарий к вопросу выше или некоторые другие новые ответы (2015 г.). Итак, какой смысл писать их снова? Вы имели в виду, что ваш ответ был решение для версий прежний до 4.6?

Jeppe Stig Nielsen 19.02.2016 13:32

Преобразование времени 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()

Это не дает вам местного времени, вы получаете UTC.

Berend de Boer 28.08.2017 02:57

@BerenddeBoer Это разумное значение по умолчанию. После этого вы можете применить произвольное смещение по своему усмотрению.

Deilan 21.11.2017 16:04

@BerenddeBoer Это неправильно понимает, что такое время unix. Время Unix - секунды с полуночи 1 января 1970 г. по всемирному координированному времени. Неважно, где вы находитесь, количество секунд с той эпохи не меняется. Преобразование его в удобочитаемые дисплеи местного времени, как и должно быть, отделены от этого универсального представления.

Tanktalus 11.09.2018 20:18
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))

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

// 1510396991

var dt = DateTimeOffset.FromUnixTimeSeconds(1510396991);

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

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

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

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

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

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

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

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

var dateTime1=DateTime.Now;

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

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

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

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

или же

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

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

DateTimeOffset.ToUnixTimeSeconds - метод,
DateTimeOffset.FromUnixTimeSeconds

если вы буквально хотите Now как время UNIX, вы можете использовать DateTimeOffset.UtcNow.ToUnixTimeSeconds()

Simon_Weaver 17.12.2020 23:06

Другие вопросы по теме