Как получить метку времени Unix в C #

400

Я посмотрел вокруг stackoverflow и даже посмотрел на некоторые из предложенных вопросов, и никто, кажется, не отвечает, как вы получаете метку времени Unix в C #?

bizzehdee
источник

Ответы:

598

Вы получаете метку времени Unix в C #, используя DateTime.UtcNowи вычитая время эпохи 1970-01-01.

например

Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;

DateTime.UtcNowможет быть заменен любым DateTimeобъектом, для которого вы хотите получить метку времени Unix.

Существует также поле, DateTime.UnixEpochкоторое очень плохо документировано MSFT, но может заменитьnew DateTime(1970, 1, 1)

bizzehdee
источник
28
Комментируя от имени @wdhough. «Этот ответ имеет ограничение с пределом Int32, который, я полагаю, составляет 2 147 483 647 человек. Согласно onlineconversion.com/unix_time.htm это соответствует времени вт, 19 января 2038 03:14:07 GMT Я предполагаю, что любой альтернативный тип номера double, long и т. д. в конечном итоге тоже будет иметь предел, но я подумал, что стоит упомянуть. Я выбираю long здесь, так как хотел целое число. Надеюсь, это поможет »
IsmailS
11
Временная метка Unix традиционно представляет собой 32-разрядное целое число и имеет диапазон от «1970-01-01 00:00:01» UTC до «2038-01-19 03:14:07» UTC.
the_nuts
89
Сумасшедший, что преобразование времени UNIX отсутствует в стандартной библиотеке как часть DateTime.
xingyu
7
Или используя целочисленную арифметику:DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).Ticks / TimeSpan.TicksPerSecond;
Антон Петров
2
Вычитаемая дата и время не обязательно должны быть в формате UTC?
jjxtra
573

Начиная с .NET 4.6, есть DateTimeOffset.ToUnixTimeSeconds().


Это метод экземпляра, поэтому вы должны вызывать его для экземпляра DateTimeOffset. Вы также можете разыграть любой экземпляр DateTime, хотя остерегайтесь часового пояса .

Чтобы получить текущую метку времени:

DateTimeOffset.UtcNow.ToUnixTimeSeconds()

Чтобы получить метку времени из DateTime:

DateTime foo = DateTime.UtcNow;
long unixTime = ((DateTimeOffset)foo).ToUnixTimeSeconds();
боб
источник
126
Хорошо. Это о времени
bizzehdee
35
@MattBorja К счастью, это возвращает Int64- к тому времени, когда перевернется, мы больше не будем использовать земные годы из-за отсутствия Земли.
Боб
24
Для всех, кто интересуется, вы можете получить текущую метку времени сDateTimeOffset.Now.ToUnixTimeSeconds()
kR105
8
@bizzehdee, Пун намеревался?
st0le
5
Вы можете получить UTC unixtimestamp с помощью: DateTimeOffset.UtcNow.ToUnixTimeSeconds ()
Яир Леви
39

Вы также можете использовать тики. Я пишу для Windows Mobile, поэтому не имею полного набора методов. TotalSeconds не доступен для меня.

long epochTicks = new DateTime(1970, 1, 1).Ticks;
long unixTime = ((DateTime.UtcNow.Ticks - epochTicks) / TimeSpan.TicksPerSecond);

или

TimeSpan epochTicks = new TimeSpan(new DateTime(1970, 1, 1).Ticks);
TimeSpan unixTicks = new TimeSpan(DateTime.UtcNow.Ticks) - epochTicks;
double unixTime = unixTicks.TotalSeconds;
Дэйв Хиндл
источник
1
Ошибка для второго решения: невозможно преобразовать тип источника «double» в тип цели «long».
Pixar
@Pixar: исправлен второй пример
JBert
5
new DateTime(1970, 1, 1)создает время с неопределенным Kindсвойством. То, что вы действительно хотите, чтобы new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)быть по-настоящему правильным
детонизировано
Из .NET Core 2.1 Вы можете использовать DateTime.UnixEpoch вместо нового DateTime (1970, 1, 1), см. Docs.microsoft.com/en-us/dotnet/api/…
Jaa H
27

Это то, что я использую:

public long UnixTimeNow()
{
    var timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
    return (long)timeSpan.TotalSeconds;
}

Имейте в виду, что этот метод будет возвращать время в формате UTC.

Бартломей Муха
источник
(TotalSeconds имеет doubleтип, литье это долго может привести к потере точности.)
франкский
Вы правы, но нам не нужно беспокоиться об этом в течение нескольких тысяч лет :)
Bartłomiej Mucha
21

Усечение .TotalSecondsважно, так как оно определяется какthe value of the current System.TimeSpan structure expressed in whole fractional seconds.

А как насчет расширения для DateTime? Второе, вероятно, более запутанно, чем стоит расширение свойств.

/// <summary>
/// Converts a given DateTime into a Unix timestamp
/// </summary>
/// <param name="value">Any DateTime</param>
/// <returns>The given DateTime in Unix timestamp format</returns>
public static int ToUnixTimestamp(this DateTime value)
{
    return (int)Math.Truncate((value.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}

/// <summary>
/// Gets a Unix timestamp representing the current moment
/// </summary>
/// <param name="ignored">Parameter ignored</param>
/// <returns>Now expressed as a Unix timestamp</returns>
public static int UnixTimestamp(this DateTime ignored)
{
    return (int)Math.Truncate((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}
штифтик
источник
2
Метод расширения, безусловно, способ сделать это аккуратно. Это отличный, зрелый ответ - и я не понимаю, почему у него так мало голосов. Уверен, что Robba верен - приведение вывода как (int) автоматически обрезает результат. (Буквально игнорируя десятичную часть двойного).
Стефани
4
(этот DateTime игнорируется) очень, очень вводит в заблуждение
Ларс Корнелиусен
6

Когда вы вычитаете 1970 из текущего времени, имейте в виду, что временной интервал чаще всего будет иметь поле, отличное от нуля миллисекунд. Если по какой-то причине вас интересуют миллисекунды, имейте это в виду.

Вот что я сделал, чтобы обойти эту проблему.

 DateTime now = UtcNow();

 // milliseconds Not included.
 DateTime nowToTheSecond = new DateTime(now.Year,now.Month,now.Day,now.Hour,now.Minute,now.Second); 

 TimeSpan span = (date - new DateTime(1970, 1, 1, 0, 0, 0, 0));

 Assert.That(span.Milliseconds, Is.EqualTo(0)); // passes.
Келли Андерсон
источник
5

Это то, что я использую.

 public class TimeStamp
    {
        public Int32 UnixTimeStampUTC()
        {
            Int32 unixTimeStamp;
            DateTime currentTime = DateTime.Now;
            DateTime zuluTime = currentTime.ToUniversalTime();
            DateTime unixEpoch = new DateTime(1970, 1, 1);
            unixTimeStamp = (Int32)(zuluTime.Subtract(unixEpoch)).TotalSeconds;
            return unixTimeStamp;
        }
}
Мэтью Джеймс Льюис
источник
возможно, сделайте это методом расширения DateTime
bizzehdee
3

Я собрал воедино самые элегантные подходы к этому служебному методу:

public static class Ux {
    public static decimal ToUnixTimestampSecs(this DateTime date) => ToUnixTimestampTicks(date) / (decimal) TimeSpan.TicksPerSecond;
    public static long ToUnixTimestampTicks(this DateTime date) => date.ToUniversalTime().Ticks - UnixEpochTicks;
    private static readonly long UnixEpochTicks = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
}
XDS
источник
2

Это решение помогло в моей ситуации:

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

используя помощник в коде:

double ret = DateHelper.DateTimeToUnixTimestamp(DateTime.Now)
Аслан Кистаубаев
источник
0

Для SystemTimeOffset в системе существует значение ToUnixTimeMilliseconds

Вы можете написать аналогичный метод для DateTime:

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

10000000L - преобразование тиков в секунды

62135596800L - преобразование с 01.01.01 по 01.01.1978

Нет проблем с Utc и утечками

Тимур Лемешко
источник
см. stackoverflow.com/questions/58391011/…
Тимур Лемешко
0

Ниже приведен двухсторонний класс расширения, который поддерживает:

  • Локализация часового пояса
  • Ввод \ вывод в секундах или миллисекундах.

В случае OP, использование:

DateTime.Now.ToUnixtime();

или

DateTime.UtcNow.ToUnixtime();

Хотя прямой ответ существует, я считаю, что лучше использовать общий подход. Тем более, что это, скорее всего, проект, который нуждается в таком преобразовании, в любом случае также потребует этих расширений, поэтому лучше использовать один и тот же инструмент для всех.

    public static class UnixtimeExtensions
    {
        public static readonly DateTime UNIXTIME_ZERO_POINT = new DateTime(1970, 1, 1, 0, 0,0, DateTimeKind.Utc);

        /// <summary>
        /// Converts a Unix timestamp (UTC timezone by definition) into a DateTime object
        /// </summary>
        /// <param name="value">An input of Unix timestamp in seconds or milliseconds format</param>
        /// <param name="localize">should output be localized or remain in UTC timezone?</param>
        /// <param name="isInMilliseconds">Is input in milliseconds or seconds?</param>
        /// <returns></returns>
        public static DateTime FromUnixtime(this long value, bool localize = false, bool isInMilliseconds = true)
        {
            DateTime result;

            if (isInMilliseconds)
            {
                result = UNIXTIME_ZERO_POINT.AddMilliseconds(value);
            }
            else
            {
                result = UNIXTIME_ZERO_POINT.AddSeconds(value);
            }

            if (localize)
                return result.ToLocalTime();
            else
                return result;
        }

        /// <summary>
        /// Converts a DateTime object into a Unix time stamp
        /// </summary>
        /// <param name="value">any DateTime object as input</param>
        /// <param name="isInMilliseconds">Should output be in milliseconds or seconds?</param>
        /// <returns></returns>
        public static long ToUnixtime(this DateTime value, bool isInMilliseconds = true)
        {
            if (isInMilliseconds)
            {
                return (long)value.ToUniversalTime().Subtract(UNIXTIME_ZERO_POINT).TotalMilliseconds;
            }
            else
            {
                return (long)value.ToUniversalTime().Subtract(UNIXTIME_ZERO_POINT).TotalSeconds;
            }
        }
    }
SingleFlake
источник
Будьте осторожны, чтобы не перепутать форматы в миллисекундах и секундах (лучший случай - исключение, худший - нелогичное преобразование). Я по умолчанию установил ввод / вывод в формат миллисекунд. Если вы предпочитаете использовать формат секунд по умолчанию, просто переключите isInMilliseconds = true (в обоих методах) на false.
SingleFlake
0

Я использовал это после некоторой борьбы, это также учитывает смещение часового пояса:

    public double Convert_DatTime_To_UNIXDATETIME(DateTime dt)
    {
        System.DateTime from_date = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
        double unix_time_since = dt.Subtract(from_date).TotalMilliseconds;

        TimeSpan ts_offset = TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow);

        double offset = ts_offset.TotalMilliseconds;

        return unix_time_since - offset;
    }
Брюс Кэмерон
источник
-1

Простой код, который я использую:

public static long CurrentTimestamp()
{
   return (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds * 1000);
}

Этот код дает метку времени Unix, общее количество миллисекунд с 1970-01-01 по настоящее время.

Эркин Эрен
источник