Wie konvertiert man die Epochenzeit in C #?

377

Wie konvertiert man Unix- Epochenzeit in C # in Echtzeit? (Epoche beginnend am 1.1.1970)

hsatterwhite
quelle
1
Wenn mir nichts fehlt, ist die "Epoche" einfach der Ausgangspunkt eines bestimmten Zeitnehmungsschemas. Beispiele sind 1/1/0001, 1/1/1970 und 1/1/2000. Es ist eher ein Attribut eines Schemas als ein Schema (z. B. Julian) selbst.
Bob Kaufman
8
Die Zeit seit der Epoche ist die Anzahl der Sekunden seit dem 1. Januar 1970 UTC.
Taylor Leese
13
@ Taylor Das ist die Epoche für Unix-Zeit, und es ist wahrscheinlich richtig, aber es ist nicht die einzige gültige Epoche. Unix-Zeitbenutzer sollten sich in diesem Punkt nicht verwirren.
Joel Coehoorn
Dup, mit anderen Antworten: stackoverflow.com/q/3354893/712526
jpaugh

Antworten:

563

Ich nehme an, Sie meinen die Unix-Zeit , die als die Anzahl der Sekunden seit Mitternacht (UTC) am 1. Januar 1970 definiert ist.

public static DateTime FromUnixTime(long unixTime)
{
    return epoch.AddSeconds(unixTime);
}
private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
LukeH
quelle
74
Damit dies richtig funktioniert, musste ich .AddSeconds in .AddMilliseconds ändern. Sie müssen wissen, ob Ihre Nummer aus Sekunden oder Millisekunden stammt, um das richtige Ergebnis zu erhalten. So zum Beispiel das folgende Datum: 1406310305188 (25. Juli 2014). Mit epochconverter.com können Sie auch Ihre Conversion-Ergebnisse überprüfen.
jrandomuser
5
Sie sollten entweder den Parametertyp in double ändern (da AddSeconds double akzeptiert und daher auf double heruntergestuft wird) oder der Methodenbeschreibung einen Haftungsausschluss hinzufügen, dass nur 53 von 64 Bit Genauigkeit im Argument erhalten bleiben.
Tomosius
6
@jrandomuser: Die Unix-Epochenzeit wird traditionell als Sekunden seit The Epoch dargestellt. Seitdem ist es üblich, Millisekunden seit The Epoch zu verwenden (zum Beispiel JavaScript), aber die klassische Definition ist Sekunden. Unterm Strich wissen Sie einfach, was Ihr Eingabewert ist (Sekunden, Millisekunden, Ticks, was auch immer) und verwenden Sie die richtige AddXYZMethode.
TJ Crowder
Versuchen Sie es zuerst mit AddMilliseconds. Wenn das Jahr noch 1970 ist, führen Sie AddSeconds aus. Auf diese Weise funktioniert es die ganze Zeit, ohne sich um Millisekunden oder Sekunden sorgen zu müssen. Außerdem können Sie einen Überlauf verhindern. Wenn Sie eine große Zahl an AddSeconds übergeben, stürzt der Code ab
Tono Nam,
213

Die neueste Version von .Net (v4.6) hat gerade die integrierte Unterstützung für Unix- Zeitkonvertierungen hinzugefügt. 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 für DateTimeOffset:

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

long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
  • Unix-Zeit in Millisekunden für DateTimeOffset:

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

long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds();

Hinweis: Diese Methoden konvertieren nach und von DateTimeOffset. Um eine DateTimeDarstellung zu erhalten, verwenden Sie einfach die DateTimeOffset.DateTimeEigenschaft:

DateTime dateTime = dateTimeOffset.UtcDateTime;
i3arnon
quelle
1
Ich bekomme 'DateTimeOffset' does not contain a definition for 'FromUnixTimeSeconds'Wie würde ich das lösen?
Happy Bird
@HappyBird Sind Sie auf .NET 4.6 oder höher?
i3arnon
Das gleiche - 4.7.2 und haben keine FromUnixTimeMilliseconds-Methode für DateTimeOffset ...
Mikhail_Sam
Ich habe es bekommen. Ich muss kein neues Objekt erstellen. Es ist eine statische Methode.
Mikhail_Sam
Ich fand die Standardwerte auf den ersten Blick etwas verwirrend. Bc 1000 ist der Faktor, der von Millis in Sekunden umgerechnet werden muss.
BluE
169

Mit aller Ehre für LukeH habe ich einige Erweiterungsmethoden für die einfache Verwendung zusammengestellt:

public static DateTime FromUnixTime(this long unixTime)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return epoch.AddSeconds(unixTime);
}

public static long ToUnixTime(this DateTime date)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return Convert.ToInt64((date - epoch).TotalSeconds);
}

Beachten Sie den Kommentar von CodesInChaos unten, dass das obige FromUnixTimeein DateTimemit einem Kindvon zurückgibt Utc, was in Ordnung ist, aber das Obige ToUnixTimeist viel verdächtiger, da es nicht berücksichtigt, welche Art von DateTimegegeben dateist. Um zuzulassen date, Kinddass entweder Utcoder ist Local, verwenden Sie ToUniversalTime:

public static long ToUnixTime(this DateTime date)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return Convert.ToInt64((date.ToUniversalTime() - epoch).TotalSeconds);
}

ToUniversalTimekonvertiert ein Local(oder Unspecified) DateTimein Utc.

Wenn Sie beim Übergang von DateTime in die Epoche keine DateTime-Instanz für die Epoche erstellen möchten, können Sie außerdem Folgendes tun:

public static long ToUnixTime(this DateTime date)
{
    return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}
Ben Cull
quelle
6
ToUnixTimefunktioniert nur richtig, wenn das Datum in Utc ist. Fügen Sie entweder einen Scheck hinzu oder konvertieren Sie ihn. (Ich persönlich bevorzuge den Scheck)
CodesInChaos
2
Ich habe gerade die letzte Stunde damit verbracht herauszufinden, warum dies nicht funktioniert. Sie müssen in milliseconds nicht Sekunden arbeiten !!!
KristianB
7
@KristianB: "Unix-Zeit" ist seit The Epoch traditionell Sekunden und keine Millisekunden, obwohl ich heutzutage sorgfältig überprüfe, welche Definition jemand verwendet. Sekunden waren früher gut genug und gaben uns einen angemessenen Bereich auf beiden Seiten von The Epoch in vorzeichenbehafteten 32-Bit-Werten. (Und deshalb könnte GMT kurz nach 3:14 Uhr am 19. Januar 2038 für einige eine schlechte Zeit sein ...) Die Verwendung von Millisekunden ist eine modernere Praxis, da wir routinemäßig 64-Bit-Werte (beide ganzzahlig) werfen können und doppelte Genauigkeit IEEE-754) ...
TJ Crowder
5
Danke für den Code. Nur eine kleine Empfehlung beim Erstellen der Epochenbasis: Stellen Sie sicher, dass Sie den Millisekundenwert explizit auf 0 setzen. Dh var epoch = new DateTime (1970, 1, 1, 0 / * h * /, 0 / * m * /, 0 / * s * /, 0 / * ms * /, DateTimeKind.Utc); Wenn Sie es nicht explizit festlegen, scheint der Millisekundenwert 1 zu sein. Dies führte zu einigen Inkonsistenzen in meinen Tests.
Ctrlplusb
1
Sie sollten AddMillisecondsDouble NOT Float verwenden und verwenden. Andernfalls haben Sie eine falsche Zeit.
Axel
25

Sie möchten tatsächlich Millisekunden (Millisekunden) hinzufügen, nicht Sekunden. Wenn Sie Sekunden hinzufügen, erhalten Sie eine Ausnahme außerhalb des Bereichs.

Darya
quelle
Warum ist das so? epochconverter.com Es heißt, Sie addieren die Anzahl der Sekunden seit dem 1.1.970 nicht ms.
Jamie R Rytlewski
Wenn Sie von ms gehen, wollen Sie offensichtlich AddMillisund wenn Sie von Sekunden beginnen, wollen Sie offensichtlich AddSeconds.
Schuh
Ich hatte das gleiche Problem, dass ich bei der Verwendung von Sekunden immer wieder außer Reichweite war. Die Unix-Zeit, die ich zu konvertieren versuchte, war in Millisekunden. Ich dachte, es wäre in Sekunden. Ich denke, einige Unix-Zeit wird in Millisekunden gemessen.
DoodleKana
Die Unix-Zeit wird normalerweise in Sekunden ausgedrückt, aber 0,001 ist eine gültige Anzahl von Sekunden (= 1 ms). Verwenden Sie im Zweifelsfall nur die maximal mögliche Präzision.
Scott
9

Wenn Sie eine bessere Leistung wünschen, können Sie diese Version verwenden.

public const long UnixEpochTicks = 621355968000000000;
public const long TicksPerMillisecond = 10000;
public const long TicksPerSecond = TicksPerMillisecond * 1000;

//[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static DateTime FromUnixTimestamp(this long unixTime)
{
    return new DateTime(UnixEpochTicks + unixTime * TicksPerSecond);
}

Aus einem schnellen Benchmark (BenchmarkDotNet) unter net471 erhalte ich folgende Nummer:

        Method |     Mean |     Error |    StdDev | Scaled |
-------------- |---------:|----------:|----------:|-------:|
         LukeH | 5.897 ns | 0.0897 ns | 0.0795 ns |   1.00 |
      MyCustom | 3.176 ns | 0.0573 ns | 0.0536 ns |   0.54 |

2x schneller gegen LukeHs Version (wenn die Leistung wichtig ist )

Dies ähnelt der internen Funktionsweise von DateTime.

Jiri Sykora
quelle
9

Verwenden Sie die Methode DateTimeOffset.ToUnixTimeMilliseconds (). Sie gibt die Anzahl der Millisekunden zurück, die seit 1970-01-01T00: 00: 00.000Z vergangen sind.

Dies wird nur mit Framework 4.6 oder höher unterstützt

var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

Es ist hier gut dokumentiert DateTimeOffset.ToUnixTimeMilliseconds

Der andere Ausweg besteht darin, Folgendes zu verwenden

long EPOCH = DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1,0,0,0,0).Ticks;

Um die EPOCH mit nur Sekunden zu erhalten, dürfen Sie verwenden

 var Epoch = (int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;

und Konvertieren der Epochzu DateTimedem folgende Verfahren

private DateTime Epoch2UTCNow(int epoch) 
{
    return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(epoch); 
}
Vinod Srivastav
quelle
DateTime.Ticks - Jeder Tick ist "einhundert Nanosekunden", was es zu einem zusätzlichen "Ding" macht, an das man sich erinnert. Wenn Sie beide weglassen .Ticks, erhalten Sie eine schöne TimeSpan-Instanz aus der DateTime-Subtraktion zurück.
user2864740
8
// convert datetime to unix epoch seconds
public static long ToUnixTime(DateTime date)
{
    var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return Convert.ToInt64((date.ToUniversalTime() - epoch).TotalSeconds);
}

Sollte ToUniversalTime () für das DateTime-Objekt verwenden.

Grüne Su
quelle
5

Ich verwende die folgenden Erweiterungsmethoden für die Epochenkonvertierung

public static int GetEpochSeconds(this DateTime date)
    {
        TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);
        return (int)t.TotalSeconds;
    }

public static DateTime FromEpochSeconds(this DateTime date, long EpochSeconds)
    {
        var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        return epoch.AddSeconds(EpochSeconds);

    }
faisal00813
quelle
2

Um sich keine Gedanken über die Verwendung von Millisekunden oder Sekunden zu machen, gehen Sie wie folgt vor:

    public static DateTime _ToDateTime(this long unixEpochTime)
    {
        DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        var date = epoch.AddMilliseconds(unixEpochTime);

        if (date.Year > 1972)
            return date;

        return epoch.AddSeconds(unixEpochTime);
    }

Wenn die Epochenzeit in Sekunden angegeben ist, können Sie das Jahr 1972 nicht mit Millisekunden verlängern.

Tono Nam
quelle
1

Wenn Sie 4.6 nicht verwenden, kann dies hilfreich sein. Quelle: System.IdentityModel.Tokens

    /// <summary>
    /// DateTime as UTV for UnixEpoch
    /// </summary>
    public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

    /// <summary>
    /// Per JWT spec:
    /// Gets the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the desired date/time.
    /// </summary>
    /// <param name="datetime">The DateTime to convert to seconds.</param>
    /// <remarks>if dateTimeUtc less than UnixEpoch, return 0</remarks>
    /// <returns>the number of seconds since Unix Epoch.</returns>
    public static long GetIntDate(DateTime datetime)
    {
        DateTime dateTimeUtc = datetime;
        if (datetime.Kind != DateTimeKind.Utc)
        {
            dateTimeUtc = datetime.ToUniversalTime();
        }

        if (dateTimeUtc.ToUniversalTime() <= UnixEpoch)
        {
            return 0;
        }

        return (long)(dateTimeUtc - UnixEpoch).TotalSeconds;
    }    
Siva Kandaraj
quelle
Danke zum Beispiel von JWT. Übrigens, um es zu benutzen, benutzen Sie einfach: using Microsoft.IdentityModel.Tokens; ... EpochTime.GetIntDate(dateTime);
Flüssigkeit
0

Wenn Sie eine Zeitstruktur (Sekunden, Mikrosekunden) konvertieren müssen, die enthält UNIX time, DateTimeohne an Genauigkeit zu verlieren, gehen Sie wie folgt vor:

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
0

Seit .Net 4.6 und höher verwenden Sie bitte DateTimeOffset.Now.ToUnixTimeSeconds ()

Saikat Chakraborty
quelle
-4

Hier ist meine Lösung:

public long GetTime()
{
    DateTime dtCurTime = DateTime.Now.ToUniversalTime();

    DateTime dtEpochStartTime = Convert.ToDateTime("1/1/1970 0:00:00 AM");

    TimeSpan ts = dtCurTime.Subtract(dtEpochStartTime);

    double epochtime;

    epochtime = ((((((ts.Days * 24) + ts.Hours) * 60) + ts.Minutes) * 60) + ts.Seconds);   

    return Convert.ToInt64(epochtime);
}
Sandeep
quelle
7
Berücksichtigt dies Schaltjahre und Schaltsekunden usw.?
Jodrell
1
Um den vorherigen Kommentar zu erweitern, hier ein kurzes Video, das erklärt, warum die Zeit kompliziert ist und warum Sie es nicht selbst versuchen sollten: youtube.com/watch?v=-5wpm-gesOY
vmrob