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)


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();

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;

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).


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

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.

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

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

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)

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



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

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

-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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.