Jak uzyskać znacznik czasu unix w C #

Odpowiedzi:

597

Otrzymasz uniksowy znacznik czasu w języku C #, używając DateTime.UtcNowi odejmując czas epoki 1970-01-01.

na przykład

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

DateTime.UtcNowmożna zastąpić dowolnym DateTimeobiektem, dla którego chcesz uzyskać znacznik czasu unix.

Istnieje również pole, DateTime.UnixEpochktóre jest bardzo słabo udokumentowane przez MSFT, ale może być zamiennikiemnew DateTime(1970, 1, 1)

bizzehdee
źródło
28
Komentowanie w imieniu @wdhough. „Ta odpowiedź ma ograniczenie do limitu Int32, który, moim zdaniem, wynosi 2 147 483 647. Według onlineconversion.com/unix_time.htm jest to czas wtorek, 19 stycznia 2038 03:14:07 GMT. , podwójne, długie itd. ostatecznie też będą miały limit, ale pomyślałem, że warto o tym wspomnieć. Wybrałem tu długi, ponieważ chciałem mieć cały numer. Mam nadzieję, że to pomoże ”
IsmailS
11
Znacznik czasu unix jest tradycyjnie 32-bitową liczbą całkowitą i ma zakres od „1970-01-01 00:00:01” UTC do „2038-01-19 03:14:07” UTC.
the_nuts
89
Dziwne, że konwersja czasu UNIX nie znajduje się w standardowej bibliotece jako część DateTime.
xingyu
7
Lub stosując całkowitą arytmetykę:DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).Ticks / TimeSpan.TicksPerSecond;
Anton Pietrow
2
Odejmowana data / godzina nie musi być UTC?
jjxtra
570

Od wersji .NET 4.6 istnieje DateTimeOffset.ToUnixTimeSeconds().


Jest to metoda instancji, dlatego należy wywoływać ją w instancji DateTimeOffset. Możesz także rzucić dowolną instancję DateTime, choć strzeż się strefy czasowej .

Aby uzyskać bieżący znacznik czasu:

DateTimeOffset.UtcNow.ToUnixTimeSeconds()

Aby uzyskać znacznik czasu z DateTime:

DateTime foo = DateTime.UtcNow;
long unixTime = ((DateTimeOffset)foo).ToUnixTimeSeconds();
Kok
źródło
126
Dobrze.
Najwyższy
35
@MattBorja Na szczęście zwraca Int64- do czasu, gdy się przewróci, nie będziemy już korzystać z ziemskich lat z powodu braku Ziemi.
Bob
24
Dla wszystkich, którzy się zastanawiają, aktualny znacznik czasu można uzyskać za pomocą opcjiDateTimeOffset.Now.ToUnixTimeSeconds()
kR105
8
@bizzehdee, Pun zamierzał?
st0le
5
Możesz pobrać unixtimestamp UTC za pomocą: DateTimeOffset.UtcNow.ToUnixTimeSeconds ()
Yair Levi
39

Możesz także użyć Kleszczy. Piszę dla Windows Mobile, więc nie mam pełnego zestawu metod. TotalSeconds nie jest dla mnie dostępny.

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

lub

TimeSpan epochTicks = new TimeSpan(new DateTime(1970, 1, 1).Ticks);
TimeSpan unixTicks = new TimeSpan(DateTime.UtcNow.Ticks) - epochTicks;
double unixTime = unixTicks.TotalSeconds;
Dave Hindle
źródło
1
Błąd drugiego rozwiązania: Nie można przekonwertować typu źródła „podwójny” na typ docelowy „długi”.
Pixar
@Pixar: Druga próbka jest naprawiona
JBert
5
new DateTime(1970, 1, 1)tworzy czas z nieokreśloną Kindwłaściwością. To, co naprawdę chcesz new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)być naprawdę poprawne
ustalono
Z .NET Core 2.1 Możesz użyć DateTime.UnixEpoch zamiast nowego DateTime (1970, 1, 1) patrz docs.microsoft.com/en-us/dotnet/api/…
Jaa H
27

Oto, czego używam:

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

Należy pamiętać, że ta metoda zwróci czas jako skoordynowany czas uniwersalny (UTC).

Bartłomiej Mucha
źródło
(TotalSeconds ma doubletyp; rzutowanie na długi spowoduje utratę precyzji.)
frankish
Masz rację, ale nie musimy się tym martwić przez kilka tysięcy lat :)
Bartłomiej Mucha
21

Obcinanie .TotalSecondsjest ważne, ponieważ jest zdefiniowane jakothe value of the current System.TimeSpan structure expressed in whole fractional seconds.

A może rozszerzenie DateTime? Drugi jest prawdopodobnie bardziej mylący, że jest wart, dopóki nie pojawią się rozszerzenia własności.

/// <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);
}
Ćwiek
źródło
2
Metoda rozszerzenia jest wyraźnie sposobem na zrobienie tego starannie. To doskonała, dojrzała odpowiedź - i nie rozumiem, dlaczego ma tak mało głosów. Jestem prawie pewien, że Robba jest poprawny - rzutowanie wyniku jako (int) automatycznie obcina wynik. (Dosłownie ignorując dziesiętną część liczby podwójnej).
Stephanie
4
(ten czas ignorowany) jest bardzo, bardzo mylący
Lars Corneliussen
6

Kiedy odejmiesz 1970 od bieżącego czasu, pamiętaj, że przedział czasu najczęściej będzie miał niezerowe pole milisekund. Jeśli z jakiegoś powodu jesteś zainteresowany milisekundami, pamiętaj o tym.

Oto, co zrobiłem, aby obejść ten problem.

 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.
Kelly Anderson
źródło
5

Tego używam.

 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;
        }
}
Matthew James Lewis
źródło
być może sprawi, że będzie to metoda rozszerzenia DateTime
bizzehdee
3

Połączyłem najbardziej eleganckie podejścia do tej metody użyteczności:

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
źródło
2

To rozwiązanie pomogło w mojej sytuacji:

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

za pomocą pomocnika w kodzie:

double ret = DateHelper.DateTimeToUnixTimestamp(DateTime.Now)
Aslan Kystaubayev
źródło
0

W systemie istnieje ToUnixTimeMilliseconds dla DateTimeOffset

Możesz napisać podobną metodę dla DateTime:

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

10000000L - konwersja tyknięć na sekundy

62135596800L - konwersja 01.01.01 na 01.01.1978

Nie ma problemu z Utc i przeciekami

Timur Lemeshko
źródło
0

Poniżej znajduje się dwukierunkowa klasa rozszerzenia, która obsługuje:

  • Lokalizacja strefy czasowej
  • Wejście \ wyjście w sekundach lub milisekundach.

W przypadku OP użycie to:

DateTime.Now.ToUnixtime();

lub

DateTime.UtcNow.ToUnixtime();

Chociaż istnieje bezpośrednia odpowiedź, uważam, że zastosowanie podejścia ogólnego jest lepsze. Zwłaszcza, że ​​najprawdopodobniej jest to projekt, który wymaga takiej konwersji, i tak będzie potrzebował tych rozszerzeń, dlatego lepiej jest używać tego samego narzędzia dla wszystkich.

    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
źródło
Uważaj, aby nie pomylić formatów milisekund i sekund (najlepszy przypadek to wyjątek, najgorszy to nielogiczna konwersja) Domyślnie wejście \ wyjście ustawiłem na format milisekund. Jeśli wolisz używać formatu sekund jako domyślnego, po prostu zmień isInMilliseconds = true (w obu metodach) na false.
SingleFlake
0

Użyłem tego po dłuższej walce, dotyczy to również przesunięcia strefy czasowej:

    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;
    }
Bruce Cameron
źródło
-1

Prosty kod, którego używam:

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

Ten kod podaje uniksowy znacznik czasu, łącznie milisekund od 1970-01-01 do chwili obecnej.

Erkin Eren
źródło