Як отримати часову позначку 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.