Cum pot converti un timestamp Unix în DateTime și viceversa? (Programare, C#, Datetime, Unix, Epoch, Conversie De Date)

Mark Ingram a intrebat.

Există acest cod de exemplu, dar apoi începe să vorbească despre probleme de milisecunde / nanosecunde.

Aceeași întrebare este pe MSDN, Secunde de la epoca Unix în C#.

Asta este ceea ce am obținut până acum:

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

Comentarii

19 răspunsuri
ScottCher

Iată de ce ai nevoie:

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

Sau, pentru Java (care este diferit, deoarece marca de timp este în milisecunde, nu în secunde):

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

user6269864

Comentarii

  • Timpul în Windows este gestionat de HAL și numai aproape de precizie în intervalul 1ms până la 15ms. Mai multe informații sunt disponibile în Elementele interne ale Windows în jurul paginii 112, dacă cineva este interesat. –  > Por Jim Schubert.
  • 19

  • Acest răspuns riscă să truncheze secundele… Un dublu este un număr variabil. Argumentul ar trebui să fie int/long/etc. –  > Por ccook.
  • 44

  • Aceste metode ar trebui să accepte un long sau un int, nu un double. De asemenea, în cazul ștampilelor de timp Java, nu este necesar să se împartă la 1000 și să se rotunjească. Trebuie doar să faceți dtDateTime.AddMilliseconds(javaTimeStamp).ToLocalTime(); –  > Por Justin Johnson.
  • Ți-a scăpat „viceversa”? Cum convertim un DateTime într-un timestamp? –  > Por Jonny.
  • 45

  • Pentru .NET Framework 4.6 și versiunile superioare există acum static DateTimeOffset.FromUnixMilliseconds și DateTimeOffset.ToUnixMilliseconds. –  > Por începător1024.
i3arnon

The cea mai recentă versiune de .NET (v4.6) a adăugat suport încorporat pentru conversiile de timp Unix. Aceasta include atât la și de la timpul Unix reprezentat fie prin secunde, fie prin milisecunde.

  • Conversia Timp Unix în secunde în UTC DateTimeOffset:
DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
  • DateTimeOffset la timpul Unix în secunde:
long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
  • Timp Unix în milisecunde în conversia UTC DateTimeOffset:
DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
  • DateTimeOffset în timpul Unix în milisecunde:
long unixTimeStampInMilliseconds = dateTimeOffset.ToUnixTimeMilliseconds();

Notă: Aceste metode convertesc în și din UTC DateTimeOffset. Pentru a obține un DateTime este suficient să utilizați metoda DateTimeOffset.UtcDateTime sau DateTimeOffset.LocalDateTime proprietăți:

DateTime dateTime = dateTimeOffset.UtcDateTime;

Comentarii

  • docs.microsoft.com/en-us/dotnet/api/… –  > Por yedevtxt.
  • Aceasta nu convertește ora în ora locală. Veți obține UTC dacă utilizați DateTimeOffset.FromUnixTimeSeconds(). –  > Por Berend de Boer.
  • @BerenddeBoer Puteți utiliza ToLocalTime dacă doriți. –  > Por i3arnon.
  • Pentru a obține ora curentă puteți utiliza long unixMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds(); –  > Por Dan Diplo.
  • Un răspuns de o calitate absolută. –  > Por user1514042.
Dmitri Fedorkov

DateTime în loc de 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;
}

gl051

De la Wikipedia:

UTC nu se schimbă odată cu schimbarea anotimpurilor, dar ora locală sau ora civilă se poate schimba dacă o jurisdicție a unui fus orar respectă ora de vară (ora de vară). De exemplu, ora locală de pe coasta de est a Statelor Unite este cu cinci ore în urma UTC în timpul iernii, dar cu patru ore în urmă atunci când acolo se observă ora de vară.

Acesta este codul meu:

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

Comentarii

  • dar acest lucru returnează un dublu, cred că trebuie să se transforme în long? –  > Por knocte.
Felix Keil

Aveți grijă, dacă aveți nevoie de o precizie mai mare de milisecunde!

Metodele .NET (v4.6) (de ex. FromUnixTimeMilliseconds) nu oferă această precizie.

AddSeconds și AddMilliseconds taie, de asemenea, microsecundele din dublul.

Aceste versiuni au o precizie ridicată:

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

Comentarii

  • Acesta este răspunsul corect. Celelalte au fusul orar incorect la conversia înapoi din timestamp. –  > Por IamIC.
  • pentru DateTime->Java, doar [code] return (long) unixTimeStampInTicks / TimeSpan.TicksPerMilliSecond; [/code] – [/code] –  > Por Max.
orad

A se vedea 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);
    }
}

Comentarii

  • Acest lucru este bun, dar aș sugera o mică modificare: Utilizarea tipului „long” ar trebui să fie schimbată în „Int32” sau „int”. „Long” presupune că există o precizie semnificativă, dar nu este așa. Toate calculele matematice sunt precise doar până la 1 secundă, așa că Int32 ar fi mai sugestiv pentru ceea ce vă așteptați de la un timestamp Unix –  > Por JamesHoux.
  • Cred că se datorează DateTime.Ticks fiind Int64 (long), astfel încât evită un cast suplimentar neverificat. –  > Por orad.
Ramil Aliyev

Puteți utiliza DateTimeOffset.

De exemplu. Am un obiect DateTime

var dateTime1=DateTime.Now;

Dacă vreau să îl convertesc în timbre de timp Unix, pot fi realizat după cum urmează

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

Dacă doriți să convertiți unix timeStamp în DateTime normal, puteți utiliza această bucată de cod:

var dateTime2 = DateTimeOffset.FromUnixTimeSeconds(unixTimeSeconds).LocalDateTime;

sau

var dateTime2 = DateTimeOffset.FromUnixTimeSeconds(unixTimeSeconds).UtcDateTime;

Pentru mai multe informații, vă rugăm să vizitați acest link :

Metoda DateTimeOffset.ToUnixTimeSeconds,
DateTimeOffset.FromUnixTimeSeconds

Comentarii

  • dacă doriți literalmente Now ca timp UNIX puteți folosi DateTimeOffset.UtcNow.ToUnixTimeSeconds() –  > Por Simon_Weaver.
Chris Thoman

Pentru a completa răspunsul lui ScottCher, m-am aflat recent în scenariul enervant de a avea atât secunde cât și milisecunde UNIX timestamps amestecate în mod arbitrar într-un set de date de intrare. Următorul cod pare să gestioneze bine acest lucru:

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

Comentarii

  • Aveți grijă când nu folosiți argumentul DateTimeKind, deoarece DateTime construit va fi în ora locală a computerului (mulțumesc pentru cod, Chris)! –  > Por Sam Grondahl.
  • Atenție – acest lucru nu va funcționa pentru timestamp-urile unix pentru datele anterioare datei de 11 ianuarie 1978, dacă acestea sunt reprezentate în milisecunde. O dată unix de 253324800 (secunde) dă data corectă de 11.01.1978, în timp ce reprezentarea în milisecunde 253324800000 dă o dată de 18.07.9997. Este posibil ca acest lucru să fi funcționat pentru setul dvs. de date, dar nu este o soluție generală. –  > Por Øyvind.
Fred

Conversia timpului Unix este o noutate în .NET Framework 4.6.

Acum puteți converti mai ușor valorile de dată și oră în sau din tipurile .NET Framework și ora Unix. Acest lucru poate fi necesar, de exemplu, atunci când se convertesc valorile temporale între un client JavaScript și un server .NET. Următoarele API-uri au fost adăugate la DateTimeOffset:

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

Comentarii

  • Aceasta nu vă oferă ora locală, ci UTC. –  > Por Berend de Boer.
  • @BerenddeBoer Aceasta este o valoare implicită rezonabilă. Puteți aplica un decalaj personalizat după aceea, după cum doriți. –  > Por Deilan.
  • @BerenddeBoer Asta înțelege greșit ce este timpul unix. Timpul Unix este reprezentat de secundele de la miezul nopții, 1 ianuarie 1970, UTC. Nu contează unde vă aflați, numărul de secunde de la acea epocă nu se schimbă. Conversia în afișaje de timp local lizibil pentru oameni este separată de această reprezentare universală, așa cum ar trebui să fie. –  > Por Tanktalus.
n8CodeGuru

Am găsit răspunsul corect doar comparând conversia la 1/1/1970 fără ajustarea orei 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;

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

// 1510396991

var dt = DateTimeOffset.FromUnixTimeSeconds(1510396991);

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

Riyaz Hameed

Ați scris o extensie mai simplă care funcționează pentru noi. Dacă cineva o caută…

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

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

Yang Zhang

Din .net 4.6, puteți face acest lucru:

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

AMieres
System.DateTimeOffset.Now.ToUnixTimeSeconds()

Licăriri fierbinți
DateTime unixEpoch = DateTime.ParseExact("1970-01-01", "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
DateTime convertedTime = unixEpoch.AddMilliseconds(unixTimeInMillisconds);

Bineînțeles, se poate face unixEpoch o statică globală, astfel încât să apară doar o singură dată în proiect, și se poate folosi AddSeconds în cazul în care timpul UNIX este în secunde.

Pentru a merge în sens invers:

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

Trunchiați în Int64 și/sau folosiți TotalSeconds după cum este necesar.

Luk

Un tick Unix este de 1 secundă (dacă îmi amintesc bine), iar un tick .NET este de 100 de nanosecunde.

Dacă ați întâmpinat probleme cu nanosecundele, ați putea încerca să utilizați AddTick(10000000 * valoare).

Comentarii

  • În Unix sunt secundele de după epoca – care este 1/1/70. –  > Por ScottCher.
i3arnon

Am avut nevoie să convertesc un structura timeval (secunde, microsecunde) conținând UNIX time în DateTime fără a pierde precizia și nu am găsit un răspuns aici, așa că m-am gândit să îl adaug pe al meu:

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

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

puteți apela UnixTime.UnixTimeToDateTime(double datetime))

superlogic

Pentru .NET 4.6 și versiunile ulterioare:

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

Comentarii

  • Nu înțeleg. În .NET 4.6, BCL are deja aceste metode (a se vedea, de exemplu, comentariul meu la întrebarea de mai sus, sau unele dintre celelalte răspunsuri noi (2015). Așadar, care ar trebui să fie rostul de a le scrie din nou? Ați vrut să spuneți că răspunsul dvs. este o soluție pentru versiunile anterioare anterioare versiunii 4.6? –  > Por Jeppe Stig Nielsen.