Як отримати часову позначку unix у C #


398

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


Відповіді:


597

Ви отримуєте часову позначку 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)


28
Коментуючи від імені @wdhough. "Ця відповідь має обмеження обмеженням Int32, яке, я вважаю, 2147 483 647. Згідно з даними onlineconversion.com/unix_time.htm це прирівнюється до часу вт. 19 січня 2038 03:14:07 GMT Я думаю, будь-який альтернативний тип номера , подвійний, довгий і т. д., врешті-решт, буде також обмеження, але я вважав, що це варто згадати. Я вибираю тут довге, як хотів цілу кількість. Сподіваюся, що це допомагає "
— 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

570

Що стосується .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()
— позначку

8
@bizzehdee, призначений Pun?
— st0le

5
Ви можете отримати UTC unixtimestamp за допомогою: DateTimeOffset.UtcNow.ToUnixTimeSeconds ()
— Yair Levi

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
Помилка другого рішення: Неможливо перетворити тип джерела "подвійний" у цільовий тип "довгий".
— 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/…
— H

27

Це те, що я використовую:

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

Майте на увазі, що цей метод поверне час як координований універсальний час (UTC).


( doubleТип " TotalSeconds" ; перенесення його на довгий час призведе до втрати точності.)
— франкіз

Ви маєте рацію, але нам не треба про це хвилюватися протягом декількох тисяч років :)
— 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
Спосіб розширення - це явно спосіб зробити це акуратно. Це відмінна, зріла відповідь - і я не розумію, чому у неї так мало голосів. Досить впевнений, що Робба правильний - передавання результату як (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;
}

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

Для системи DataTimeOffset у системі є ToUnixTimeMilliseconds

Ви можете написати подібний метод для DateTime:

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

10000000L - перетворення кліщів в секунди

62135596800L - перетворення 01.01.01 на 01.01.1978

Немає проблем з Utc та протіканнями



0

Нижче наведено двосторонній клас розширення, який підтримує:

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

У випадку з ОП використання:

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

Будьте обережні, щоб не плутати формати мілісекунд та секунд (найкращий випадок - виняток, найгірший - нелогічне перетворення). Я дефолтом ввів \ вихід у формат мілісекунд. Якщо ви вважаєте за краще використовувати формат секунд за замовчуванням, просто переключіть 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 по теперішній час.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.