Comment convertir le temps d'époque en C #?


377

Comment convertir le temps de l'époque Unix en temps réel en C #? (Epoque débutant le 1/1/1970)


1
Sauf si je manque quelque chose, l '"époque" est simplement le point d'origine d'un système de chronométrage particulier. Les exemples incluent 1/1/0001, 1/1/1970 et 1/1/2000. Il s'agit davantage d'un attribut d'un schéma plutôt que d'un schéma (par exemple, Julian) lui-même.
Bob Kaufman

8
Le temps écoulé depuis l'époque correspond au nombre de secondes écoulées depuis le 1er janvier 1970 UTC.
Taylor Leese

13
@Taylor C'est l'époque du temps Unix, et c'est probablement vrai, mais ce n'est pas la seule époque valide. Les utilisateurs de temps Unix ne doivent pas se confondre sur ce point.
Joel Coehoorn

Dup, avec d'autres réponses: stackoverflow.com/q/3354893/712526
jpaugh

Réponses:


563

Je suppose que vous voulez dire l' heure Unix , qui est définie comme le nombre de secondes depuis minuit (UTC) le 1er janvier 1970.

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

74
Pour que cela fonctionne correctement, j'ai dû changer .AddSeconds en .AddMilliseconds. Vous aurez besoin de savoir si votre numéro provient de secondes ou de millisecondes afin d'obtenir le résultat correct. Ainsi, par exemple, la date suivante: 1406310305188 (25 juillet 2014). epochconverter.com vous permettra également de vérifier vos résultats de conversion.
jrandomuser

5
Vous devez soit changer le type de paramètre en double (car AddSeconds accepte le double et donc le downcast en double) ou ajouter une clause de non-responsabilité à la description de la méthode selon laquelle seuls 53 des 64 bits de précision de l'argument seront conservés.
tomosius

6
@jrandomuser: Le temps de l'époque Unix est traditionnellement représenté en secondes depuis The Epoch. Depuis, il est devenu courant d'utiliser des millisecondes depuis The Epoch (par exemple, JavaScript), mais la définition classique est de quelques secondes. En bout de ligne, sachez simplement quelle est votre valeur d'entrée (secondes, millisecondes, ticks, peu importe) et utilisez la bonne AddXYZméthode.
TJ Crowder

Essayez d'abord avec AddMilliseconds et si l'année est toujours 1970, faites AddSeconds. De cette façon, cela fonctionnera tout le temps sans avoir à se soucier des millisecondes ou des secondes. De plus, vous pouvez empêcher une excès de débordement. Passer un grand nombre à AddSeconds fera planter le code
Tono Nam

213

La dernière version de .Net (v4.6) vient d'ajouter la prise en charge intégrée des conversions de temps Unix. Cela inclut le temps vers et depuis Unix représenté par des secondes ou des millisecondes.

  • Temps Unix en secondes pour DateTimeOffset:

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

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

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

long unixTimeStampInMilliseconds= dateTimeOffset.ToUnixTimeMilliseconds();

Remarque: Ces méthodes convertissent vers et depuis DateTimeOffset. Pour obtenir une DateTimereprésentation, utilisez simplement la DateTimeOffset.DateTimepropriété:

DateTime dateTime = dateTimeOffset.UtcDateTime;

1
Je reçois 'DateTimeOffset' does not contain a definition for 'FromUnixTimeSeconds'Comment pourrais-je résoudre ce problème?
Happy Bird

@HappyBird Êtes-vous sur .NET 4.6 ou supérieur?
i3arnon

La même chose - 4.7.2 et aucune méthode FromUnixTimeMilliseconds pour DateTimeOffset ...
Mikhail_Sam

J? ai compris. Je n'ai pas besoin de créer de nouvel objet. C'est une méthode statique.
Mikhail_Sam

J'ai trouvé les valeurs par défaut un peu déroutantes à première vue. Bc 1000 est le facteur de conversion de millisecondes en secondes.
BluE

169

Avec tout le mérite de LukeH, j'ai mis en place quelques méthodes d'extension pour une utilisation facile:

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

Notez le commentaire ci-dessous de CodesInChaos selon lequel ce qui précède FromUnixTimerenvoie un DateTimeavec un Kindde Utc, ce qui est bien, mais ce qui précède ToUnixTimeest beaucoup plus suspect car cela ne tient pas compte du type deDateTime donné date. Pour permettre datede » Kindl'être soit Utcou Local, utilisez 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);
}

ToUniversalTimeconvertira un Local(ou Unspecified) DateTimeen Utc.

si vous ne voulez pas créer l'instance epoch DateTime lors du passage de DateTime à epoch, vous pouvez également faire:

public static long ToUnixTime(this DateTime date)
{
    return (date.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
}

6
ToUnixTimene fonctionne correctement que si la date est en Utc. Ajoutez un chèque ou convertissez-le. (Personnellement, je préfère le chèque)
CodesInChaos

2
Je viens de passer la dernière heure à comprendre pourquoi cela ne fonctionne pas. Vous devez travailler en milliseconds pas secondes !!!
KristianB

7
@KristianB: "Le temps Unix" est traditionnellement quelques secondes, pas des millisecondes, depuis The Epoch, bien que ces jours-ci, je fais attention à vérifier la définition que quelqu'un utilise. Les secondes étaient auparavant assez bonnes et nous ont donné une plage raisonnable de chaque côté de The Epoch en valeurs 32 bits signées. (Et c'est pourquoi juste après 03h14 le 19 janvier 2038 GMT pourrait être un mauvais moment pour certains ...) L'utilisation des millisecondes est une pratique plus moderne grâce à notre capacité à lancer régulièrement des valeurs 64 bits (toutes deux intégrales et double précision IEEE-754) ...
TJ Crowder

5
Merci pour le code. Juste une légère recommandation lors de la création de la base Epoch: assurez-vous de définir explicitement la valeur en millisecondes sur 0. ie var epoch = new DateTime (1970, 1, 1, 0 / * h * /, 0 / * m * /, 0 / * s * /, 0 / * ms * /, DateTimeKind.Utc); Si vous ne le définissez pas explicitement, la valeur en millisecondes semble sortir à 1. Cela a causé des incohérences dans mes tests.
ctrlplusb

1
Vous devez utiliser AddMillisecondset vous devez utiliser Double NOT Float. Sinon, vous vous retrouverez avec un mauvais moment.
Axel

25

Vous voulez réellement ajouter des millisecondes (millisecondes), pas des secondes. L'ajout de secondes vous donnera une exception hors de portée.


Pourquoi donc? epochconverter.com Il dit que vous ajoutez le nombre de secondes depuis 1/1/970 pas ms.
Jamie R Rytlewski

Si vous allez de ms, vous voulez évidemment AddMilliset si vous partez de secondes, vous voulez évidemment AddSeconds.
Chaussure

J'ai eu le même problème que je n'arrivais pas à atteindre lorsque j'utilisais les secondes. Le temps Unix que j'essayais de convertir était en millisecondes. Je pensais que c'était en quelques secondes. Je suppose qu'un certain temps Unix est mesuré en millisecondes.
DoodleKana

Le temps Unix est généralement exprimé en secondes, mais 0,001 est un nombre valide de secondes (= 1 ms). En cas de doute, utilisez simplement la précision maximale possible.
Scott

9

Si vous voulez de meilleures performances, vous pouvez utiliser cette version.

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

À partir d'un benchmark rapide (BenchmarkDotNet) sous net471, j'obtiens ce numéro:

        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 plus rapide contre la version de LukeH (si la performance est importante)

Ceci est similaire au fonctionnement interne de DateTime.


9

Utilisez la méthode DateTimeOffset.ToUnixTimeMilliseconds () Elle renvoie le nombre de millisecondes qui se sont écoulées depuis le 1970-01-01T00: 00: 00.000Z.

Ceci n'est pris en charge qu'avec Framework 4.6 ou supérieur

var EPOCH = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

C'est bien documenté ici DateTimeOffset.ToUnixTimeMilliseconds

L'autre solution consiste à utiliser ce qui suit

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

Pour obtenir l'EPOCH en quelques secondes seulement, vous pouvez utiliser

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

et convertissez le Epochen DateTimeavec la méthode suivante

private DateTime Epoch2UTCNow(int epoch) 
{
    return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(epoch); 
}

DateTime.Ticks - chaque tick est «cent nanosecondes», ce qui en fait une «chose» supplémentaire à retenir. Si vous omettez les deux .Ticks, vous récupérerez une belle instance TimeSpan de la soustraction DateTime.
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);
}

Doit utiliser ToUniversalTime () pour l'objet DateTime.


5

J'utilise les méthodes d'extension suivantes pour la conversion d'époque

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

    }

2

Pour ne pas vous soucier d'utiliser des millisecondes ou des secondes, faites simplement:

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

Si le temps de l'époque est en secondes, il n'y a aucun moyen de passer l'année 1972 en ajoutant des millisecondes.


1

Si vous n'utilisez pas 4.6, cela peut aider Source: 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;
    }    

Merci par exemple de JWT. Au fait, pour l'utiliser, il suffit d'utiliser: using Microsoft.IdentityModel.Tokens; ... EpochTime.GetIntDate(dateTime);
liquide

0

Dans le cas où vous devez convertir une structure temporelle (secondes, microsecondes) contenant UNIX timeen DateTimesans perdre en précision, voici comment:

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


-4

Voici ma solution:

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

7
cela représente-t-il les années bissextiles et les secondes bissextiles, etc.?
Jodrell

1
Pour développer le commentaire précédent, voici une courte vidéo qui explique pourquoi le temps est compliqué et pourquoi vous ne devriez pas essayer de le faire vous-même: youtube.com/watch?v=-5wpm-gesOY
vmrob
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.