Come posso convertire un timestamp Unix in DateTime e viceversa?


755

C'è questo codice di esempio, ma poi inizia a parlare di problemi di millisecondi / nanosecondi.

La stessa domanda è su MSDN, Seconds dall'epoca Unix in C # .

Questo è quello che ho finora:

public Double CreatedEpoch
{
  get
  {
    DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime();
    TimeSpan span = (this.Created.ToLocalTime() - epoch);
    return span.TotalSeconds;
  }
  set
  {
    DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime();
    this.Created = epoch.AddSeconds(value);
  }
}

119
L'imminente .NET 4.6 (che sarà rilasciato entro la fine dell'anno) introduce il supporto per questo. Vedi DateTimeOffset.FromUnixTimeSecondse DateTimeOffset.ToUnixTimeSecondsmetodi. Esistono anche metodi per millisecondi di tempo unix.
Jeppe Stig Nielsen

Risposte:


1018

Ecco cosa ti serve:

public static DateTime UnixTimeStampToDateTime( double unixTimeStamp )
{
    // Unix timestamp is seconds past epoch
    System.DateTime dtDateTime = new DateTime(1970,1,1,0,0,0,0,System.DateTimeKind.Utc);
    dtDateTime = dtDateTime.AddSeconds( unixTimeStamp ).ToLocalTime();
    return dtDateTime;
}

Oppure, per Java (che è diverso perché il timestamp è in millisecondi, non secondi):

public static DateTime JavaTimeStampToDateTime( double javaTimeStamp )
{
    // Java timestamp is milliseconds past epoch
    System.DateTime dtDateTime = new DateTime(1970,1,1,0,0,0,0,System.DateTimeKind.Utc);
    dtDateTime = dtDateTime.AddMilliseconds( javaTimeStamp ).ToLocalTime();
    return dtDateTime;
}

5
Il tempo in Windows è gestito da HAL e solo con precisione da 1ms a 15ms. Ulteriori informazioni sono disponibili in Windows Internals a pagina 112, se qualcuno è interessato.
Jim Schubert,

16
Questa risposta rischia di troncare i secondi ... Un doppio è un numero mobile. L'argomento dovrebbe essere int / long / etc.
cok

44
Questi metodi dovrebbero accettare un long o int, non un double. Inoltre, per i timestamp Java, non è necessario dividere per 1000 e arrotondare. BastadtDateTime.AddMilliseconds(javaTimeStamp).ToLocalTime();
Justin Johnson,

11
Ti sei appena perso il "viceversa"? Come possiamo convertire un DateTime in un timestamp?
Jonny l'

38
Per .NET Framework 4.6 e versioni successive ora static DateTimeOffset.FromUnixMillisecondse DateTimeOffset.ToUnixMilliseconds.
rookie1024,

422

L' ultima versione di .NET (v4.6) ha aggiunto il supporto integrato per le conversioni temporali Unix. Ciò include sia il tempo di andata e ritorno di Unix rappresentato da secondi o millisecondi.

  • Tempo Unix in secondi a UTC DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
  • DateTimeOffset tempo Unix in secondi:

long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
  • Tempo Unix in millisecondi a UTC DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
  • DateTimeOffset al tempo Unix in millisecondi:

long unixTimeStampInMilliseconds = dateTimeOffset.ToUnixTimeMilliseconds();

Nota: questi metodi vengono convertiti da e verso un UTC DateTimeOffset. Per ottenere una DateTimerappresentazione, utilizzare semplicemente le proprietà DateTimeOffset.UtcDateTimeo DateTimeOffset.LocalDateTime:

DateTime dateTime = dateTimeOffset.UtcDateTime;


Questo non converte l'ora in ora locale. Ottieni UTC se usi DateTimeOffset.FromUnixTimeSeconds ().
Berend de Boer,

4
@BerenddeBoer Puoi usarlo ToLocalTimese vuoi.
i3arnon,

1
Per ottenere l'ora corrente è possibile utilizzarelong unixMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Dan Diplo

219

Data / ora da UNIX timestamp:

public static double DateTimeToUnixTimestamp(DateTime dateTime)
{
    return (TimeZoneInfo.ConvertTimeToUtc(dateTime) - 
           new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc)).TotalSeconds;
}

47

Da Wikipedia :

L'ora UTC non cambia con un cambio di stagione, ma l'ora locale o civile può cambiare se una giurisdizione del fuso orario osserva l'ora legale (ora legale). Ad esempio, l'ora locale sulla costa orientale degli Stati Uniti è cinque ore indietro rispetto a UTC durante l'inverno, ma quattro ore indietro mentre si osserva l'ora legale.

Quindi questo è il mio codice:

TimeSpan span = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0,DateTimeKind.Utc));
double unixTime = span.TotalSeconds;

2
ma questo restituisce un doppio, immagino che bisogna lanciare a lungo?
Knocte,

30

Fai attenzione, se hai bisogno di una precisione superiore a millisecondi!

I metodi .NET (v4.6) (ad es. FromUnixTimeMilliseconds ) non forniscono questa precisione.

AddSeconds e AddMilliseconds tagliano anche i microsecondi nel doppio.

Queste versioni hanno un'alta precisione:

Unix -> DateTime

public static DateTime UnixTimestampToDateTime(double unixTime)
{
    DateTime unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
    long unixTimeStampInTicks = (long) (unixTime * TimeSpan.TicksPerSecond);
    return new DateTime(unixStart.Ticks + unixTimeStampInTicks, System.DateTimeKind.Utc);
}

DateTime -> Unix

public static double DateTimeToUnixTimestamp(DateTime dateTime)
{
    DateTime unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
    long unixTimeStampInTicks = (dateTime.ToUniversalTime() - unixStart).Ticks;
    return (double) unixTimeStampInTicks / TimeSpan.TicksPerSecond;
}

2
Questa è la risposta corretta Gli altri ottengono il fuso orario errato sulla conversione indietro dal timestamp.
IamIC

per DateTime-> Java, solo [codice] restituisce (lungo) unixTimeStampInTicks / TimeSpan.TicksPerMilliSecond; [/ code]
Max

Quindi nel tuo UnixTimestampToDateTime, il fornito unixTimeè ancora in pochi secondi, giusto?
Ngoc Pham,

@NgocPham sì, lo è
Felix Keil,

14

Vedi IdentityModel.EpochTimeExtensions

public static class EpochTimeExtensions
{
    /// <summary>
    /// Converts the given date value to epoch time.
    /// </summary>
    public static long ToEpochTime(this DateTime dateTime)
    {
        var date = dateTime.ToUniversalTime();
        var ticks = date.Ticks - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).Ticks;
        var ts = ticks / TimeSpan.TicksPerSecond;
        return ts;
    }

    /// <summary>
    /// Converts the given date value to epoch time.
    /// </summary>
    public static long ToEpochTime(this DateTimeOffset dateTime)
    {
        var date = dateTime.ToUniversalTime();
        var ticks = date.Ticks - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).Ticks;
        var ts = ticks / TimeSpan.TicksPerSecond;
        return ts;
    }

    /// <summary>
    /// Converts the given epoch time to a <see cref="DateTime"/> with <see cref="DateTimeKind.Utc"/> kind.
    /// </summary>
    public static DateTime ToDateTimeFromEpoch(this long intDate)
    {
        var timeInTicks = intDate * TimeSpan.TicksPerSecond;
        return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddTicks(timeInTicks);
    }

    /// <summary>
    /// Converts the given epoch time to a UTC <see cref="DateTimeOffset"/>.
    /// </summary>
    public static DateTimeOffset ToDateTimeOffsetFromEpoch(this long intDate)
    {
        var timeInTicks = intDate * TimeSpan.TicksPerSecond;
        return new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).AddTicks(timeInTicks);
    }
}

Questo va bene, ma suggerirei una piccola modifica: l'uso del tipo "long" dovrebbe essere modificato in "Int32" o "int". "Long" implica una notevole precisione, ma non lo è. Tutta la matematica è precisa solo a 1 secondo, quindi Int32 sarebbe più suggestivo di quello che ti aspetteresti da un timestamp di Unix
JamesHoux,

3
Penso che sia dovuto a DateTime.TicksInt64 (lungo), quindi stanno evitando un cast extra non controllato.
Orad,

10

Per integrare la risposta di ScottCher, di recente mi sono trovato nel fastidioso scenario di avere timestamp UNIX di secondi e millisecondi arbitrariamente mescolati insieme in un set di dati di input. Il seguente codice sembra gestirlo bene:

static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
static readonly double MaxUnixSeconds = (DateTime.MaxValue - UnixEpoch).TotalSeconds;

public static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
{
   return unixTimeStamp > MaxUnixSeconds
      ? UnixEpoch.AddMilliseconds(unixTimeStamp)
      : UnixEpoch.AddSeconds(unixTimeStamp);
}

1
Fai attenzione quando non usi l'argomento DateTimeKind, poiché il DateTime costruito sarà nell'ora locale del computer (grazie per il codice, Chris)!
Sam Grondahl,

1
Attenzione: questo non funzionerà con i timestamp unix per le date precedenti all'11 gennaio 1978 se sono rappresentati in millisecondi. Un datestamp unix di 253324800 (secondi) indica la data corretta dell'11.01.1978, mentre la rappresentazione in millisecondi 253324800000 indica una data del 18.07.9997. Questo potrebbe aver funzionato per il tuo set di dati, ma non è una soluzione generale.
Øyvind

8

La conversione del tempo Unix è una novità di .NET Framework 4.6.

Ora puoi convertire più facilmente i valori di data e ora in o da tipi di .NET Framework e ora Unix. Ciò può essere necessario, ad esempio, durante la conversione di valori temporali tra un client JavaScript e un server .NET. Le seguenti API sono state aggiunte alla struttura DateTimeOffset :

static DateTimeOffset FromUnixTimeSeconds(long seconds)
static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds)
long DateTimeOffset.ToUnixTimeSeconds()
long DateTimeOffset.ToUnixTimeMilliseconds()

Questo non ti dà l'ora locale, ottieni UTC.
Berend de Boer,

@BerenddeBoer È un valore predefinito ragionevole. È possibile applicare un offset personalizzato dopo quello desiderato.
Deilan,

1
@BerenddeBoer Questo fraintende il tempo di Unix. Il tempo di Unix è secondi dalla mezzanotte, 1 gennaio 1970, UTC. Non importa dove ti trovi, il numero di secondi trascorsi da quell'epoca non cambia. La conversione in visualizzazioni dell'ora locale leggibili dall'uomo è separata da questa rappresentazione universale, come dovrebbe essere.
Tanktalus,

5

Ho trovato la risposta giusta solo confrontando la conversione in 1/1/1970 senza la regolazione dell'ora locale;

DateTime date = new DateTime(2011, 4, 1, 12, 0, 0, 0);
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);
TimeSpan span = (date - epoch);
double unixTime =span.TotalSeconds;

4
var dt = DateTime.Now; 
var unixTime = ((DateTimeOffset)dt).ToUnixTimeSeconds();

// 1510396991

var dt = DateTimeOffset.FromUnixTimeSeconds(1510396991);

// [11.11.2017 10:43:11 +00: 00]


4

Da .net 4.6, puoi farlo:

var dateTime = DateTimeOffset.FromUnixTimeSeconds(unixDateTime).DateTime;

3
DateTime unixEpoch = DateTime.ParseExact("1970-01-01", "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
DateTime convertedTime = unixEpoch.AddMilliseconds(unixTimeInMillisconds);

Naturalmente, si può rendere unixEpochstatico globale, quindi deve apparire una sola volta nel progetto e si può usareAddSeconds se il tempo UNIX è in secondi.

Per andare dall'altra parte:

double unixTimeInMilliseconds = timeToConvert.Subtract(unixEpoch).TotalMilliseconds;

Troncare su Int64 e / o utilizzare TotalSecondssecondo necessità.


3

Scritto un'estensione più semplice che funziona per noi. Se qualcuno lo cerca ...

public static class DateTimeExtensions
{
    public static DateTime FromUnixTimeStampToDateTime(this string unixTimeStamp)
    {

        return DateTimeOffset.FromUnixTimeSeconds(long.Parse(unixTimeStamp)).UtcDateTime;
    }
}


2

Un tick Unix è di 1 secondo (se ricordo bene) e un tick .NET è di 100 nanosecondi.

Se hai riscontrato problemi con i nanosecondi, potresti provare a utilizzare AddTick (valore 10000000 *).


3
Unix è epoche passate - ovvero 1/1/70.
ScottCher,

1

Avevo bisogno di convertire una struct timeval (secondi, microsecondi) contenente UNIX timeal DateTimesenza perdere precisione e non ho trovato una risposta qui così ho pensato che appena potrebbe aggiungere la mia:

DateTime _epochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private DateTime UnixTimeToDateTime(Timeval unixTime)
{
    return _epochTime.AddTicks(
        unixTime.Seconds * TimeSpan.TicksPerSecond +
        unixTime.Microseconds * TimeSpan.TicksPerMillisecond/1000);
}

1

È possibile utilizzare DateTimeOffset .

Per esempio. Ho un oggetto DateTime

var dateTime=new DateTime();

Se voglio convertirlo in timestamp Unix, posso ottenere come segue

var unixTimeSeconds= new DateTimeOffset(dateTime).ToUnixTimeSeconds()

Per ulteriori informazioni, visitare questo collegamento: Metodo DateTimeOffset.ToUnixTimeSeconds


0
public static class UnixTime
    {
        private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);

        public static DateTime UnixTimeToDateTime(double unixTimeStamp)
        {
            return Epoch.AddSeconds(unixTimeStamp).ToUniversalTime();
        }
    }

puoi chiamare UnixTime.UnixTimeToDateTime (double datetime))


-2

Per .NET 4.6 e versioni successive:

public static class UnixDateTime
{
    public static DateTimeOffset FromUnixTimeSeconds(long seconds)
    {
        if (seconds < -62135596800L || seconds > 253402300799L)
            throw new ArgumentOutOfRangeException("seconds", seconds, "");

        return new DateTimeOffset(seconds * 10000000L + 621355968000000000L, TimeSpan.Zero);
    }

    public static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds)
    {
        if (milliseconds < -62135596800000L || milliseconds > 253402300799999L)
            throw new ArgumentOutOfRangeException("milliseconds", milliseconds, "");

        return new DateTimeOffset(milliseconds * 10000L + 621355968000000000L, TimeSpan.Zero);
    }

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

    public static long ToUnixTimeMilliseconds(this DateTimeOffset utcDateTime)
    {
        return utcDateTime.Ticks / 10000L - 62135596800000L;
    }

    [Test]
    public void UnixSeconds()
    {
        DateTime utcNow = DateTime.UtcNow;
        DateTimeOffset utcNowOffset = new DateTimeOffset(utcNow);

        long unixTimestampInSeconds = utcNowOffset.ToUnixTimeSeconds();

        DateTimeOffset utcNowOffsetTest = UnixDateTime.FromUnixTimeSeconds(unixTimestampInSeconds);

        Assert.AreEqual(utcNowOffset.Year, utcNowOffsetTest.Year);
        Assert.AreEqual(utcNowOffset.Month, utcNowOffsetTest.Month);
        Assert.AreEqual(utcNowOffset.Date, utcNowOffsetTest.Date);
        Assert.AreEqual(utcNowOffset.Hour, utcNowOffsetTest.Hour);
        Assert.AreEqual(utcNowOffset.Minute, utcNowOffsetTest.Minute);
        Assert.AreEqual(utcNowOffset.Second, utcNowOffsetTest.Second);
    }

    [Test]
    public void UnixMilliseconds()
    {
        DateTime utcNow = DateTime.UtcNow;
        DateTimeOffset utcNowOffset = new DateTimeOffset(utcNow);

        long unixTimestampInMilliseconds = utcNowOffset.ToUnixTimeMilliseconds();

        DateTimeOffset utcNowOffsetTest = UnixDateTime.FromUnixTimeMilliseconds(unixTimestampInMilliseconds);

        Assert.AreEqual(utcNowOffset.Year, utcNowOffsetTest.Year);
        Assert.AreEqual(utcNowOffset.Month, utcNowOffsetTest.Month);
        Assert.AreEqual(utcNowOffset.Date, utcNowOffsetTest.Date);
        Assert.AreEqual(utcNowOffset.Hour, utcNowOffsetTest.Hour);
        Assert.AreEqual(utcNowOffset.Minute, utcNowOffsetTest.Minute);
        Assert.AreEqual(utcNowOffset.Second, utcNowOffsetTest.Second);
        Assert.AreEqual(utcNowOffset.Millisecond, utcNowOffsetTest.Millisecond);
    }
}

4
Non capisco. In .NET 4.6, il BCL ha già questi metodi (vedi ad esempio il mio commento alla domanda sopra, o alcune delle altre nuove risposte (2015). Quindi quale dovrebbe essere lo scopo di scriverle di nuovo? Intendevi che la tua risposta era una soluzione per versioni precedenti alla 4.6?
Jeppe Stig Nielsen,
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.