Come ottenere il timestamp unix in C #


Risposte:


597

Ottieni un timestamp unix in C # usando DateTime.UtcNowe sottraendo il tempo dell'epoca del 1970-01-01.

per esempio

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

DateTime.UtcNowpuò essere sostituito con qualsiasi DateTimeoggetto per il quale si desidera ottenere il timestamp unix.

C'è anche un campo, DateTime.UnixEpochche è scarsamente documentato da MSFT, ma può essere un sostitutonew DateTime(1970, 1, 1)


28
Commentando per conto di @wdhough. "Questa risposta ha una limitazione con il limite di Int32 che è, credo, 2.147.483.647. Secondo onlineconversion.com/unix_time.htm questo equivale a un tempo di martedì 19 gennaio 2038 03:14:07 GMT, credo che qualsiasi tipo di numero alternativo , doppio, lungo, ecc. alla fine avrà anche un limite, ma ho pensato che valesse la pena menzionarlo. Ho scelto qui a lungo perché volevo un numero intero. Spero che questo aiuti "
IsmailS,

11
Il timestamp unix è tradizionalmente un numero intero a 32 bit e ha un intervallo da '1970-01-01 00:00:01' UTC a '2038-01-19 03:14:07' UTC.
the_nuts

89
Pazzo che la conversione dell'ora UNIX non sia nella libreria standard come parte di DateTime.
Xingyu,

7
O usando l'aritmetica intera:DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).Ticks / TimeSpan.TicksPerSecond;
Anton Petrov,

2
Il datetime sottratto non deve essere UTC?
jjxtra,

573

A partire da .NET 4.6, c'è DateTimeOffset.ToUnixTimeSeconds().


Questo è un metodo di istanza, quindi dovresti chiamarlo su un'istanza di DateTimeOffset. Puoi anche trasmettere qualsiasi istanza di DateTime, anche se fai attenzione al fuso orario .

Per ottenere il timestamp corrente:

DateTimeOffset.UtcNow.ToUnixTimeSeconds()

Per ottenere il timestamp da un DateTime:

DateTime foo = DateTime.UtcNow;
long unixTime = ((DateTimeOffset)foo).ToUnixTimeSeconds();

126
Buona. È giunto il momento
bizzehdee,

35
@MattBorja Per fortuna, ritorna un Int64- quando si ribalta , non avremmo più usato gli anni terrestri per mancanza di terra.
Bob,

24
Per chiunque si DateTimeOffset.Now.ToUnixTimeSeconds()
stia

8
@bizzehdee, Pun inteso?
st0le

5
È possibile ottenere il unixtimestamp UTC con: DateTimeOffset.UtcNow.ToUnixTimeSeconds ()
Yair Levi

39

Puoi anche usare le zecche. Sto codificando per Windows Mobile, quindi non ho il set completo di metodi. TotalSeconds non è disponibile per me.

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

o

TimeSpan epochTicks = new TimeSpan(new DateTime(1970, 1, 1).Ticks);
TimeSpan unixTicks = new TimeSpan(DateTime.UtcNow.Ticks) - epochTicks;
double unixTime = unixTicks.TotalSeconds;

1
Errore per la seconda soluzione: impossibile convertire il tipo di origine 'double' nel tipo di destinazione 'long'.
Pixar

@Pixar: il secondo campione è stato risolto
JBert,

5
new DateTime(1970, 1, 1)crea un orario con Kindproprietà non specificate . Quello che vuoi davvero new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)essere veramente corretto
detunizzato il

Da .NET Core 2.1 È possibile utilizzare DateTime.UnixEpoch anziché il nuovo DateTime (1970, 1, 1), vedere docs.microsoft.com/en-us/dotnet/api/…
Jaa H

27

Questo è quello che uso:

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

Tieni presente che questo metodo restituirà l'ora come Tempo coordinato universale (UTC).


(TotalSeconds ha doubletipo; lanciarlo a lungo causerà una perdita di precisione.)
franco

Hai ragione, ma non ci dobbiamo preoccupare per diverse migliaia di anni :)
Bartłomiej Mucha,

21

Troncare .TotalSecondsè importante poiché è definito comethe value of the current System.TimeSpan structure expressed in whole fractional seconds.

E che ne dici di un'estensione per DateTime? Il secondo è probabilmente più confuso che vale fino a quando non esistono estensioni di proprietà.

/// <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
Il metodo di estensione è chiaramente il modo per farlo ordinatamente. Questa è una risposta eccellente e matura - e non capisco perché abbia così pochi voti. Abbastanza sicuro che Robba sia corretto - il cast dell'output come (int) tronca automaticamente il risultato. (Ignorando letteralmente la parte decimale del doppio).
Stephanie,

4
(questo DateTime ignorato) è molto, molto fuorviante
Lars Corneliussen,

6

Quando si sottraggono 1970 dall'ora corrente, tenere presente che l'intervallo di tempo avrà spesso un campo non zero millisecondi. Se per qualche motivo sei interessato ai millisecondi, tienilo a mente.

Ecco cosa ho fatto per aggirare questo problema.

 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

Questo è quello che uso.

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

forse renderlo un metodo di estensione di DateTime
bizzehdee il

3

Ho unito gli approcci più eleganti a questo metodo di utilità:

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

Questa soluzione mi ha aiutato nella mia situazione:

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

usando l'helper nel codice:

double ret = DateHelper.DateTimeToUnixTimestamp(DateTime.Now)

0

Esiste un ToUnixTimeMilliseconds per DateTimeOffset nel sistema

Puoi scrivere un metodo simile per DateTime:

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

10000000L - conversione di tick in secondi

62135596800L - conversione da 01.01.01 a 01.01.1978

Non ci sono problemi con Utc e perdite



0

Di seguito è una classe di estensione a 2 vie che supporta:

  • Localizzazione del fuso orario
  • Input \ output in secondi o millisecondi.

Nel caso di OP, l'utilizzo è:

DateTime.Now.ToUnixtime();

o

DateTime.UtcNow.ToUnixtime();

Anche se esiste una risposta diretta, credo che sia meglio usare un approccio generico. Soprattutto perché è molto probabile che un progetto abbia bisogno di una conversione come questa, avrà comunque bisogno di queste estensioni, quindi è meglio usare lo stesso strumento per tutti.

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

Fai attenzione a non confondere i formati di millisecondi e secondi (il caso migliore è un'eccezione, il peggio è la conversione illogica) Ho impostato automaticamente l'input \ output nel formato millisecondi. Se si preferisce utilizzare il formato dei secondi come predefinito, è sufficiente impostare isInMilliseconds = true (in entrambi i metodi) su false.
SingleFlake

0

L'ho usato dopo aver lottato per un po ', si rivolge anche all'offset del fuso orario:

    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

Il semplice codice che sto usando:

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

Questo codice indica unix timestamp, in millisecondi totali dal 1970-01-01 ad oggi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.