Comment puis-je convertir un horodatage Unix en DateTime et vice versa?


755

Il y a cet exemple de code, mais ensuite il commence à parler de problèmes de milliseconde / nanoseconde.

La même question se pose sur MSDN, Secondes depuis l'époque Unix en C # .

Voici ce que j'ai jusqu'à présent:

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
Le prochain .NET 4.6 (qui sera publié plus tard cette année) introduit la prise en charge de cela. Voir DateTimeOffset.FromUnixTimeSecondset DateTimeOffset.ToUnixTimeSecondsméthodes. Il existe également des méthodes pour la milliseconde unix-time.
Jeppe Stig Nielsen

Réponses:


1018

Voici ce dont vous avez besoin:

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

Ou, pour Java (qui est différent car l'horodatage est en millisecondes, pas en secondes):

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
Le temps dans Windows est géré par HAL et n'est presque précis qu'en 1 ms à 15 ms. Plus d'informations sont disponibles dans Windows Internals autour de la page 112, si quelqu'un est intéressé.
Jim Schubert

16
Cette réponse risque de tronquer les secondes ... Un double est un nombre flottant. L'argument doit être int / long / etc.
ccook

44
Ces méthodes doivent accepter un long ou un entier, pas un double. De plus, pour les horodatages Java, il n'est pas nécessaire de diviser par 1000 et d'arrondir. Just dodtDateTime.AddMilliseconds(javaTimeStamp).ToLocalTime();
Justin Johnson

11
Vous venez de manquer le "vice versa"? Comment convertir un DateTime en horodatage?
Jonny

39
Pour le .NET Framework 4.6 et supérieur, il existe maintenant static DateTimeOffset.FromUnixMillisecondset DateTimeOffset.ToUnixMilliseconds.
rookie1024

422

La dernière version de .NET (v4.6) a ajouté la prise en charge intégrée pour les conversions de temps Unix. Cela inclut le temps vers et depuis Unix représenté par des secondes ou des millisecondes.

  • Temps Unix en secondes en UTC DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
  • DateTimeOffset en temps Unix en secondes:

long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
  • Temps Unix en millisecondes en UTC DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
  • DateTimeOffset en Unix en millisecondes:

long unixTimeStampInMilliseconds = dateTimeOffset.ToUnixTimeMilliseconds();

Remarque: Ces méthodes convertissent vers et depuis un UTC DateTimeOffset. Pour obtenir une DateTimereprésentation, utilisez simplement les propriétés DateTimeOffset.UtcDateTimeou DateTimeOffset.LocalDateTime:

DateTime dateTime = dateTimeOffset.UtcDateTime;


Cela ne convertit pas l'heure en heure locale. Vous obtenez UTC si vous utilisez DateTimeOffset.FromUnixTimeSeconds ().
Berend de Boer

4
@BerenddeBoer Vous pouvez utiliser ToLocalTimesi vous le souhaitez.
i3arnon

1
Pour obtenir l'heure actuelle, vous pouvez utiliserlong unixMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Dan Diplo

219

DateTime à l'horodatage UNIX:

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

47

De Wikipédia :

L'UTC ne change pas avec un changement de saison, mais l'heure locale ou l'heure civile peut changer si une juridiction de fuseau horaire observe l'heure d'été (heure d'été). Par exemple, l'heure locale sur la côte est des États-Unis a cinq heures de retard sur UTC pendant l'hiver, mais quatre heures de retard alors que l'heure d'été y est observée.

Voici donc mon code:

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

2
mais cela renvoie un double, je suppose que l'on doit lancer trop longtemps?
knocte

30

Attention, si vous avez besoin d'une précision supérieure aux millisecondes!

Les méthodes .NET (v4.6) (par exemple FromUnixTimeMilliseconds ) ne fournissent pas cette précision.

AddSeconds et AddMilliseconds coupent également les microsecondes dans le double.

Ces versions ont une grande précision:

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
Ceci est la bonne réponse. Les autres obtiennent le fuseau horaire incorrect lors de la conversion de l'horodatage.
IamIC

pour DateTime-> Java, juste [code] return (long) unixTimeStampInTicks / TimeSpan.TicksPerMilliSecond; [/ code]
Max

Donc dans votre UnixTimestampToDateTime, le fourni unixTimeest toujours en quelques secondes, non?
Ngoc Pham

@NgocPham oui c'est le cas
Felix Keil

14

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

C'est bien, mais je suggère une petite modification: l'utilisation du type "long" doit être remplacée par "Int32" ou "int". "Long" implique qu'il y a une précision importante, mais ce n'est pas le cas. Tout le calcul n'est précis qu'à 1 seconde, donc Int32 serait plus suggestif de ce que vous attendez d'un horodatage Unix
JamesHoux

3
Je pense que cela est dû au DateTime.Ticksfait qu'Int64 (long), ils évitent donc une distribution supplémentaire non contrôlée.
2018 à 20h42

10

Pour compléter la réponse de ScottCher, je me suis récemment retrouvé dans le scénario ennuyeux d'avoir des horodatages UNIX en secondes et en millisecondes mélangés arbitrairement dans un ensemble de données d'entrée. Le code suivant semble bien gérer cela:

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
Soyez prudent lorsque vous n'utilisez pas l'argument DateTimeKind, car le DateTime construit sera à l'heure locale de l'ordinateur (merci pour le code, Chris)!
Sam Grondahl

1
Attention - cela ne fonctionnera pas pour les horodatages Unix pour les dates antérieures au 11 janvier 1978 si elles sont représentées en millisecondes. Un horodatage Unix de 253324800 (secondes) donne la date correcte du 11.01.1978, tandis que la représentation en millisecondes 253324800000 donne une date du 18.07.9997. Cela a peut-être fonctionné pour votre ensemble de données, mais ce n'est pas une solution générale.
Øyvind

8

La conversion de l'heure Unix est nouvelle dans .NET Framework 4.6.

Vous pouvez désormais convertir plus facilement les valeurs de date et d'heure vers ou depuis les types .NET Framework et l'heure Unix. Cela peut être nécessaire, par exemple, lors de la conversion de valeurs de temps entre un client JavaScript et un serveur .NET. Les API suivantes ont été ajoutées à la structure DateTimeOffset :

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

Cela ne vous donne pas l'heure locale, vous obtenez UTC.
Berend de Boer

@BerenddeBoer C'est un défaut raisonnable. Vous pouvez ensuite appliquer un décalage personnalisé comme vous le souhaitez.
Deilan

1
@BerenddeBoer Cela méconnaît ce qu'est le temps Unix. Le temps Unix est en secondes depuis minuit, le 1er janvier 1970, UTC. Peu importe où vous êtes, le nombre de secondes depuis cette époque ne change pas. Le convertir en affichage de l'heure locale lisible par l'homme est séparé de cette représentation universelle, comme il se doit.
Tanktalus

5

J'ai trouvé la bonne réponse simplement en comparant la conversion au 1/1/1970 sans l'ajustement de l'heure 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

Depuis .net 4.6, vous pouvez faire ceci:

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

Bien sûr, on peut créer unixEpochune statique globale, il ne doit donc apparaître qu'une seule fois dans votre projet, et on peut l'utiliser AddSecondssi l'heure UNIX est en secondes.

Pour aller dans l'autre sens:

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

Tronquez en Int64 et / ou utilisez TotalSecondsau besoin.


3

A écrit une extension la plus simple qui fonctionne pour nous. Si quelqu'un le cherche ...

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

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


2

Un tick Unix est de 1 seconde (si je me souviens bien), et un tick .NET est de 100 nanosecondes.

Si vous rencontrez des problèmes avec les nanosecondes, vous voudrez peut-être essayer d'utiliser AddTick (valeur 10000000 *).


3
Unix est une seconde après l'époque - qui est 1/1/70.
ScottCher

1

Je avais besoin de convertir une struct timeval (secondes, microsecondes) contenant UNIX timede DateTimesans perte de précision et n'ont pas trouvé une réponse ici , donc je pensais que je pourrais juste ajouter le mien:

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

Vous pouvez utiliser DateTimeOffset .

Par exemple. J'ai un objet DateTime

var dateTime=new DateTime();

Si je veux le convertir en horodatages Unix, je peux être réalisé comme suit

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

Pour plus d'informations, veuillez visiter ce lien: Méthode 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();
        }
    }

vous pouvez appeler UnixTime.UnixTimeToDateTime (double datetime))


-2

Pour .NET 4.6 et versions ultérieures:

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
Je ne comprends pas. Dans .NET 4.6, la BCL a déjà ces méthodes (voir par exemple mon commentaire à la question ci-dessus, ou certaines des autres nouvelles réponses (2015). Alors, à quoi bon les écrire à nouveau? Vouliez-vous dire que votre réponse était une solution pour les versions antérieures à 4.6?
Jeppe Stig Nielsen
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.