Wie kann ich einen Unix-Zeitstempel in DateTime konvertieren und umgekehrt?

754

Es gibt diesen Beispielcode, aber dann wird über Millisekunden- / Nanosekundenprobleme gesprochen.

Die gleiche Frage betrifft MSDN, Sekunden seit der Unix-Epoche in C # .

Das habe ich bisher:

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);
  }
}
Mark Ingram
quelle
119
Das kommende .NET 4.6 (das später in diesem Jahr veröffentlicht werden soll) bietet Unterstützung dafür. Siehe DateTimeOffset.FromUnixTimeSecondsund DateTimeOffset.ToUnixTimeSecondsMethoden. Es gibt auch Methoden für die Millisekunden-Unix-Zeit.
Jeppe Stig Nielsen

Antworten:

1017

Folgendes brauchen Sie:

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

Oder für Java (was anders ist, weil der Zeitstempel in Millisekunden und nicht in Sekunden angegeben ist):

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;
}
ScottCher
quelle
5
Die Zeit in Windows wird von HAL verarbeitet und ist innerhalb von 1 ms bis 15 ms nur nahezu genau. Weitere Informationen finden Sie in Windows Internals auf Seite 112, falls jemand interessiert ist.
Jim Schubert
16
Bei dieser Antwort besteht die Gefahr, dass die Sekunden abgeschnitten werden ... Ein Double ist eine schwebende Zahl. Das Argument sollte int / long / etc. Sein.
ccook
44
Diese Methoden sollten ein long oder int akzeptieren, kein double. Für die Java-Zeitstempel besteht keine Notwendigkeit, durch 1000 und rund zu teilen. Tun Sie es einfachdtDateTime.AddMilliseconds(javaTimeStamp).ToLocalTime();
Justin Johnson
11
Haben Sie gerade das "umgekehrt" verpasst? Wie konvertieren wir eine DateTime in einen Zeitstempel?
Jonny
38
Für .NET Framework 4.6 und höher gibt es jetzt static DateTimeOffset.FromUnixMillisecondsund DateTimeOffset.ToUnixMilliseconds.
Rookie1024
422

Die neueste Version von .NET (v4.6) bietet integrierte Unterstützung für Unix- Zeitkonvertierungen . Dies schließt sowohl die Unix-Zeit als auch die Unix-Zeit ein, die entweder durch Sekunden oder Millisekunden dargestellt wird.

  • Unix-Zeit in Sekunden bis UTC DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
  • DateTimeOffset Unix-Zeit in Sekunden:

long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
  • Unix-Zeit in Millisekunden bis UTC DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
  • DateTimeOffset Unix-Zeit in Millisekunden:

long unixTimeStampInMilliseconds = dateTimeOffset.ToUnixTimeMilliseconds();

Hinweis: Diese Methoden werden in und aus einer UTC konvertiert DateTimeOffset. Um eine DateTimeDarstellung zu erhalten, verwenden Sie einfach die Eigenschaften DateTimeOffset.UtcDateTimeoder DateTimeOffset.LocalDateTime:

DateTime dateTime = dateTimeOffset.UtcDateTime;
i3arnon
quelle
Dies konvertiert die Zeit nicht in die Ortszeit. Sie erhalten UTC, wenn Sie DateTimeOffset.FromUnixTimeSeconds () verwenden.
Berend de Boer
4
@BerenddeBoer Sie können verwenden, ToLocalTimewenn Sie möchten.
i3arnon
1
Um die aktuelle Zeit zu erhalten, können Sielong unixMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Dan Diplo
219

Zeitstempel von DateTime zu UNIX:

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

Aus Wikipedia :

Die UTC ändert sich nicht mit dem Wechsel der Jahreszeiten, aber die Ortszeit oder die Zivilzeit können sich ändern, wenn eine Zeitzonen-Gerichtsbarkeit die Sommerzeit (Sommerzeit) einhält. Beispielsweise liegt die Ortszeit an der Ostküste der Vereinigten Staaten im Winter fünf Stunden hinter UTC, aber vier Stunden hinter UTC, während dort Sommerzeit beobachtet wird.

Das ist also mein Code:

TimeSpan span = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0,DateTimeKind.Utc));
double unixTime = span.TotalSeconds;
gl051
quelle
2
aber das ergibt ein Doppel, ich denke man muss zu lange werfen?
Knocte
30

Seien Sie vorsichtig, wenn Sie eine Genauigkeit von mehr als Millisekunden benötigen!

.NET (v4.6) -Methoden (z. B. FromUnixTimeMilliseconds ) bieten diese Genauigkeit nicht.

AddSeconds und AddMilliseconds schneiden die Mikrosekunden ebenfalls doppelt ab.

Diese Versionen haben eine hohe Präzision:

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;
}
Felix Keil
quelle
2
Dies ist die richtige Antwort. Bei den anderen wird die Zeitzone beim Zurückkonvertieren vom Zeitstempel falsch angegeben.
IamIC
für DateTime-> Java nur [Code] return (long) unixTimeStampInTicks / TimeSpan.TicksPerMilliSecond; [/ Code]
Max
Also in deinem UnixTimestampToDateTimeist das mitgelieferte unixTimenoch in Sekunden, oder?
Ngoc Pham
@ NgocPham ja es ist
Felix Keil
14

Siehe 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);
    }
}
orad
quelle
Das ist gut, aber ich würde eine kleine Änderung vorschlagen: Die Verwendung des Typs "long" sollte in "Int32" oder "int" geändert werden. "Lang" bedeutet, dass es eine signifikante Präzision gibt, aber keine. Die gesamte Mathematik ist nur auf 1 Sekunde genau, sodass Int32 eher darauf hindeutet, was Sie von einem Unix-Zeitstempel erwarten würden
JamesHoux
3
Ich denke, es liegt daran, DateTime.Ticksdass Int64 (lang) ist, also vermeiden sie eine zusätzliche ungeprüfte Besetzung.
Orad
10

Als Ergänzung zu ScottChers Antwort befand ich mich kürzlich in dem nervigen Szenario, dass UNIX-Zeitstempel sowohl in Sekunden als auch in Millisekunden willkürlich in einem Eingabedatensatz gemischt wurden. Der folgende Code scheint damit gut umzugehen:

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);
}
Chris Thoman
quelle
1
Seien Sie vorsichtig, wenn Sie das DateTimeKind-Argument nicht verwenden, da die erstellte DateTime in der Ortszeit des Computers angezeigt wird (danke für den Code, Chris)!
Sam Grondahl
1
Achtung - dies funktioniert nicht für Unix-Zeitstempel für Daten vor dem 11. Januar 1978, wenn sie in Millisekunden dargestellt werden. Ein Unix-Datenstempel von 253324800 (Sekunden) gibt das korrekte Datum vom 11.01.1978 an, während die Millisekunden-Darstellung 253324800000 ein Datum vom 18.07.9997 angibt. Dies hat möglicherweise für Ihren Datensatz funktioniert, ist jedoch keine allgemeine Lösung.
Øyvind
8

Die Unix-Zeitkonvertierung ist neu in .NET Framework 4.6.

Sie können jetzt einfacher Datums- und Zeitwerte in oder von .NET Framework-Typen und Unix-Zeit konvertieren. Dies kann beispielsweise beim Konvertieren von Zeitwerten zwischen einem JavaScript-Client und einem .NET-Server erforderlich sein. Die folgenden APIs wurden der DateTimeOffset-Struktur hinzugefügt :

static DateTimeOffset FromUnixTimeSeconds(long seconds)
static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds)
long DateTimeOffset.ToUnixTimeSeconds()
long DateTimeOffset.ToUnixTimeMilliseconds()
Fred
quelle
Dies gibt Ihnen keine Ortszeit, Sie erhalten UTC.
Berend de Boer
@BerenddeBoer Das ist ein vernünftiger Standard. Danach können Sie einen benutzerdefinierten Versatz anwenden, wie Sie möchten.
Deilan
1
@BerenddeBoer Das versteht falsch, was Unix-Zeit ist. Die Unix-Zeit beträgt Sekunden seit Mitternacht, 1. Januar 1970, UTC. Egal wo Sie sind, die Anzahl der Sekunden seit dieser Epoche ändert sich nicht. Die Konvertierung in von Menschen lesbare Ortszeitanzeigen unterscheidet sich von dieser universellen Darstellung, wie es sein sollte.
Tanktalus
5

Ich fand die richtige Antwort, indem ich die Konvertierung mit dem 1.1.1970 ohne die lokale Zeitanpassung verglich.

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;
n8CodeGuru
quelle
4
var dt = DateTime.Now; 
var unixTime = ((DateTimeOffset)dt).ToUnixTimeSeconds();

// 1510396991

var dt = DateTimeOffset.FromUnixTimeSeconds(1510396991);

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

Mesut
quelle
4

Ab .net 4.6 können Sie Folgendes tun:

var dateTime = DateTimeOffset.FromUnixTimeSeconds(unixDateTime).DateTime;
Yang Zhang
quelle
3
DateTime unixEpoch = DateTime.ParseExact("1970-01-01", "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
DateTime convertedTime = unixEpoch.AddMilliseconds(unixTimeInMillisconds);

Natürlich kann man unixEpocheine globale Statik erstellen, so dass sie nur einmal in Ihrem Projekt erscheinen muss, und man kann sie verwenden, AddSecondswenn die UNIX-Zeit in Sekunden ist.

Um den anderen Weg zu gehen:

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

Auf Int64 abschneiden und / oder TotalSecondsnach Bedarf verwenden.

Hot Licks
quelle
3

Geschrieben eine einfachste Erweiterung, die für uns funktioniert. Wenn jemand danach sucht ...

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

        return DateTimeOffset.FromUnixTimeSeconds(long.Parse(unixTimeStamp)).UtcDateTime;
    }
}
Riyaz Hameed
quelle
3
System.DateTimeOffset.Now.ToUnixTimeSeconds()
AMieres
quelle
2

Ein Unix-Tick ist 1 Sekunde (wenn ich mich gut erinnere) und ein .NET-Tick ist 100 Nanosekunden.

Wenn Sie Probleme mit Nanosekunden haben, können Sie AddTick (Wert 10000000 *) verwenden.

Luk
quelle
3
Unix ist Sekunden nach der Epoche - das ist der 1.1.70.
ScottCher
1

Ich brauchte eine konvertieren timeval struct (Sekunden, Mikrosekunden) , die UNIX timeauf DateTimeohne Präzision zu verlieren und haben festgestellt , keine Antwort hier also dachte ich , ich meine nur noch hinzufügen könnte:

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);
}
i3arnon
quelle
1

Sie können DateTimeOffset verwenden .

Zum Beispiel. Ich habe ein DateTime-Objekt

var dateTime=new DateTime();

Wenn ich es in Unix-Zeitstempel konvertieren möchte, kann ich Folgendes erreichen

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

Weitere Informationen finden Sie unter folgendem Link: DateTimeOffset.ToUnixTimeSeconds-Methode

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

Sie können UnixTime.UnixTimeToDateTime (double datetime) aufrufen.

Madan
quelle
-2

Für .NET 4.6 und höher:

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);
    }
}
superlogisch
quelle
4
Ich verstehe nicht. In .NET 4.6 verfügt die BCL bereits über diese Methoden (siehe z. B. meinen Kommentar zur obigen Frage oder einige der anderen neuen Antworten (2015). Worum sollte es also beim erneuten Schreiben gehen? Meinten Sie, dass Ihre Antwort war eine Lösung für Versionen vor 4.6?
Jeppe Stig Nielsen