Comment obtenir un horodatage UTC en JavaScript?

158

Lors de l'écriture d'une application Web, il est logique de stocker (côté serveur) toutes les heures de données dans la base de données en tant qu'horodatages UTC.

J'ai été étonné de constater que vous ne pouviez pas faire grand-chose en natif en termes de manipulation du fuseau horaire en JavaScript.

J'ai un peu étendu l'objet Date. Cette fonction a-t-elle un sens? En gros, chaque fois que j'envoie quelque chose au serveur, ça va être un horodatage formaté avec cette fonction ...

Pouvez-vous voir des problèmes majeurs ici? Ou peut-être une solution sous un angle différent?

Date.prototype.getUTCTime = function(){ 
  return new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime(); 
}

Cela me semble un peu compliqué. Et je ne suis pas non plus si sûr des performances.

Merc
la source
Je sais que c'est une sorte de vieille question, mais essayez de ne pas étendre les objets natifs comme l'objet Date. Vote positif parce que j'aime la question elle-même.
trysis le
Date.parse (new Date (). ToUTCString ())
Sagi
26
C'est une vieille question qui a été soulevée dans mon fil d'actualité aujourd'hui, et elle est pleine de désinformation. L'horodatage est toujours en UTC. new Date().toString()vous montrera la représentation de l'heure du fuseau horaire actuel, new Date().toUTCString()vous montrera l'heure UTC repr, mais new Date().getTime()est toujours UTC , car c'est ce que l'heure Unix est définie comme: "L'heure Unix (également appelée heure POSIX ou heure d'époque) est un système pour décrire les instants dans le temps, défini comme le nombre de secondes qui se sont écoulées depuis 00:00:00 temps universel coordonné (UTC), jeudi 1er janvier 1970, sans compter les secondes intercalaires. "
Amadan

Réponses:

155
  1. Les dates construites de cette façon utilisent le fuseau horaire local, ce qui rend la date construite incorrecte. Pour définir le fuseau horaire d'un certain objet de date, il faut le construire à partir d'une chaîne de date qui inclut le fuseau horaire. (J'ai eu des problèmes pour faire fonctionner cela dans un ancien navigateur Android.)

  2. Notez que getTime()renvoie des millisecondes, pas des secondes simples.

Pour un horodatage UTC / Unix, ce qui suit devrait suffire:

Math.floor((new Date()).getTime() / 1000)

Il prendra en compte le décalage du fuseau horaire actuel dans le résultat. Pour une représentation sous forme de chaîne, la réponse de David Ellis fonctionne.

Clarifier:

new Date(Y, M, D, h, m, s)

Cette entrée est traitée comme l'heure locale . Si l' heure UTC est passée, les résultats seront différents. Observez (je suis actuellement à GMT +02: 00, et il est 07:50):

> var d1 = new Date();
> d1.toUTCString();
"Sun, 18 Mar 2012 05:50:34 GMT" // two hours less than my local time
> Math.floor(d1.getTime()/ 1000)
1332049834 

> var d2 = new Date( d1.getUTCFullYear(), d1.getUTCMonth(), d1.getUTCDate(), d1.getUTCHours(), d1.getUTCMinutes(), d1.getUTCSeconds() );
> d2.toUTCString();
"Sun, 18 Mar 2012 03:50:34 GMT" // four hours less than my local time, and two hours less than the original time - because my GMT+2 input was interpreted as GMT+0!
> Math.floor(d2.getTime()/ 1000)
1332042634

Notez également que getUTCDate()cela ne peut pas être remplacé getUTCDay(). C'est parce que getUTCDate()renvoie le jour du mois ; tandis que, getUTCDay()renvoie le jour de la semaine .

DCoder
la source
1
1) Je ne construisait pas une date ... J'ai ajouté une fonction prototype qui a travaillé sur ce . 2) Bon point, je devrais faire le Math.floor / 1000 - mais j'aurais quand même besoin de cette fonction pour avoir l'horodatage UTC d'un objet de date existant ... n'est-ce pas?
Merc
@Merc: 1) que vous appelez new Date(), cela crée une nouvelle date à partir de votre entrée UTC mais la traite comme une date / heure locale. 2) Oui, vous devez utiliser Math.floor(this.getTime() / 1000)dans ce cas.
DCoder
Répondre ici car j'ai besoin de mettre à jour le code ... C'est pour avoir l'horodatage Unix en UTC pour une date existante : function () {return Math.floor (new Date (this.getUTCFullYear (), this.getUTCMonth (), this.getUTCDate (), this.getUTCHours (), this.getUTCMinutes (), this.getUTCSeconds ()) .getTime () / 1000); } Cela signifie que je peux faire: var n = new Date (2008,10,10) ... ... n.getUTCTime (); (Ce sera DIFFÉRENT de n.getUTCTime ())
Merc
1
Merci Bro Son fichier de travail Math.floor ((new Date ()). GetTime () / 1000)
Manoj Patel
51

Vous pouvez également le faire en utilisant getTimezoneOffset et getTime,

x = new Date()
var UTCseconds = (x.getTime() + x.getTimezoneOffset()*60*1000)/1000;

console.log("UTCseconds", UTCseconds)

Shiplu Mokaddim
la source
4
Merci, cela ne se trouve nulle part sur Internet!
Theofanis Pantelides
Je teste les codes suivants: var tt = new Date('Thu Jan 01 1970 08:00:00 GMT+0800 (China Standard Time)'); (tt.getTime() - tt.getTimezoneOffset()*60*1000)/1000. Cela semble tt.getTime() - tt.getTimezoneOffset()correct pour GMT+0800.
zangw
1
C'est mieuxvar UTCseconds = (Math.floor(x.getTime()/1000) + x.getTimezoneOffset()*60)
StefansArya
Il semble que cela ne fonctionne pas comme écrit. Il semble que vous deviez passer une chaîne de temps dans new Date()laquelle inclut un fuseau horaire .. ce qui va à l'
encontre de
Ceci est tout simplement faux, la valeur attribuée à UTCseconds n'est pas secondes UTC .. Une valeur de temps de date est UTC, en changeant par quelque moyen que ce procédé , il représente un moment différent dans le temps.
RobG
35

Le moyen le plus simple d'obtenir l'heure UTC dans un format conventionnel est le suivant:

new Date().toISOString()
"2016-06-03T23:15:33.008Z"
Tahsin Turkoz
la source
3
C'est la bonne réponse. Beaucoup d'autres réponses donnent une "chaîne de temps universel" mais ne donnent pas le "temps universel coordonné" actuel. Je ne comprends pas pourquoi tout est si compliqué ici.
gburton
Merci @gburton. J'apprécie de voir le chemin simple vers la vérité. :)
Tahsin Turkoz
1
J'utilise ceci, avec ".split ('T') [0]" pour des comparaisons faciles basées sur les dates AAAA-MM-JJ.
Sean O
Bien d'avoir @SeanO
Tahsin Turkoz
Cela fournit une chaîne d'heure UTC, mais OP demande un horodatage UTC (époque)
Jordi Nebot
13

Je pense en fait que les valeurs de date dans js sont bien meilleures que les objets C # DateTime. Les objets C # DateTime ont une propriété Kind, mais aucun fuseau horaire sous-jacent strict en tant que tel, et les conversions de fuseau horaire sont difficiles à suivre si vous effectuez une conversion entre deux heures non UTC et non locales. Dans js, toutes les valeurs Date ont une valeur UTC sous-jacente qui est transmise et connue indépendamment des conversions offest ou de fuseau horaire que vous effectuez. Ma plus grande plainte à propos de l'objet Date est la quantité de comportement non défini que les implémenteurs de navigateur ont choisi d'inclure, ce qui peut confondre les personnes qui attaquent les dates dans js avec des essais et des erreurs que la lecture des spécifications. L'utilisation de quelque chose comme iso8601.js résout ce comportement variable en définissant une seule implémentation de l'objet Date.

Par défaut, la spécification dit que vous pouvez créer des dates avec un format de date ISO 8601 étendu comme

var someDate = new Date('2010-12-12T12:00Z');

Ainsi, vous pouvez déduire l'heure UTC exacte de cette façon.

Lorsque vous souhaitez renvoyer la valeur Date au serveur que vous appelleriez

someDate.toISOString();

ou si vous préférez travailler avec un horodatage en millisecondes (nombre de millisecondes à partir du 1er janvier 1970 UTC)

someDate.getTime();

ISO 8601 est une norme. Vous ne pouvez pas être confus sur ce que signifie une chaîne de date si vous incluez le décalage de date. Ce que cela signifie pour vous en tant que développeur, c'est que vous n'avez jamais à gérer vous-même les conversions d'heure locale . Les valeurs d'heure locale existent uniquement pour le bénéfice de l'utilisateur, et les valeurs de date s'affichent par défaut dans leur heure locale. Toutes les manipulations de l'heure locale vous permettent d'afficher quelque chose de sensible pour l'utilisateur et de convertir des chaînes à partir de l'entrée utilisateur. C'est une bonne pratique de convertir en UTC dès que vous le pouvez, et l'objet js Date rend cela assez trivial.

En revanche, il n'y a pas beaucoup de possibilités de forcer le fuseau horaire ou les paramètres régionaux pour le client (dont je suis conscient), ce qui peut être ennuyeux pour les paramètres spécifiques au site Web, mais je suppose que le raisonnement derrière cela est qu'il s'agit d'un utilisateur configuration à ne pas toucher.

Donc, en bref, la raison pour laquelle il n'y a pas beaucoup de support natif pour la manipulation de fuseau horaire est que vous ne voulez tout simplement pas le faire.

Matt Esch
la source
12

Vous n'avez généralement pas besoin de faire beaucoup de "manipulation du fuseau horaire" côté client. En règle générale, j'essaie de stocker et de travailler avec des dates UTC, sous la forme de ticks" nombre de millisecondes depuis minuit le 1er janvier 1970 ". Cela simplifie vraiment le stockage, le tri, le calcul des décalages, et surtout, vous évite le mal de tête des ajustements "Daylight Saving Time". Voici un petit code JavaScript que j'utilise.

Pour obtenir l'heure UTC actuelle:

function getCurrentTimeUTC()
{
    //RETURN:
    //      = number of milliseconds between current UTC time and midnight of January 1, 1970
    var tmLoc = new Date();
    //The offset is in minutes -- convert it to ms
    return tmLoc.getTime() + tmLoc.getTimezoneOffset() * 60000;
}

Ensuite, ce dont vous avez généralement besoin est de formater la date / l'heure pour l'utilisateur final en fonction de son fuseau horaire et de son format locaux . Ce qui suit prend en charge toutes les complexités des formats de date et d'heure sur l'ordinateur client:

function formatDateTimeFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted date/time
    return new Date(nTicks).toLocaleString();
}

function formatDateFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted date
    return new Date(nTicks).toLocaleDateString();
}

function formatTimeFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted time
    return new Date(nTicks).toLocaleTimeString();
}

Donc l'exemple suivant:

var ticks = getCurrentTimeUTC();  //Or get it from the server

var __s = "ticks=" + ticks + 
    ", DateTime=" + formatDateTimeFromTicks(ticks) +
    ", Date=" + formatDateFromTicks(ticks) +
    ", Time=" + formatTimeFromTicks(ticks);

document.write("<span>" + __s + "</span>");

Renvoie ce qui suit (pour mes paramètres régionaux en anglais américain):

ticks = 1409103400661, DateHeure = 26/08/2014 6:36:40 PM, Date = 26/08/2014, Heure = 18:36:40 PM

ahmd0
la source
1
En ajoutant la getTimezoneOffsetvaleur à votre getCurrentTimeUTCfonction, vous renvoyez en fait un moment différent. Le résultat de getTimeest déjà en UTC.
Matt Johnson-Pint
1
@MattJohnson: C'est incorrect. Le résultat de tmLoc.getTime()est un décalage par rapport à l'heure locale. Il est facile de vérifier si vous avez accès à tout ce qui exécute JavaScript.
ahmd0
2
Désolé, mais ce n'est pas vrai. Voir la référence MDN . Vous pouvez également le voir dans la spécification ECMAScript. Le §15.9.3.3 décritgetTime , qui vous dirige vers la «valeur de temps» définie au §15.9.5 , qui est a PrimitiveValue, telle que définie au §15.9.3.3 explicitement comme UTC.
Matt Johnson-Pint
2
Eh bien, puisque vous obtenez tmLocvia new Date(), alors c'est la même chose. Le fuseau horaire affectera la sortie de la chaîne tmLoc.toString()et les éléments similaires, mais il n'affectera pas tmLoc.getTime() C'est toujours juste un nombre de millisecondes depuis minuit le 01/01/1970 en UTC.
Matt Johnson-Pint
1
@StefansArya://The offset is in minutes -- convert it to ms
ahmd0
5

Je pense que c'est une meilleure solution

// UTC milliseconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()

// UTC seconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()/1000|0
Koalex
la source
Une autre mauvaise réponse, getTime renvoie un décalage UTC, l'ajout du décalage du fuseau horaire local le gâche complètement. Les décalages ECMAScript sont + ve pour l'ouest et -ve pour l'est, ils doivent donc être soustraits de UTC pour obtenir local. Mais comme la valeur de l'heure est UTC pour commencer, l'ajouter la déplace essentiellement de UTC dans la direction opposée au décalage local.
RobG
4

Si vous voulez un seule ligne , l' horodatage UTC Unix peut être créé en JavaScript comme:

var currentUnixTimestap = ~~(+new Date() / 1000);

Cela prendra en compte le fuseau horaire du système. C'est essentiellement le temps écoulé en secondes depuis l'époque.

Comment ça fonctionne:

  • Créer un objet Date: new Date().
  • Convertir en horodatage en ajoutant unary +avant la création de l'objet pour le convertir entimestamp integer . : +new Date().
  • Convertissez des millisecondes en secondes: +new Date() / 1000
  • Utilisez des doubles tildes pour arrondir la valeur à un entier. :~~(+new Date())
Kushal Likhi
la source
7
ce n'est tildepas tilda(sic). Malheureusement, cela ne me permettra pas de supprimer une faute de frappe, je dois faire au moins 6 modifications de caractères. Smooth, Stackexchange, smooth
Fred
3
Ne l'utilisez pas . Avec la spécification ecma actuelle, les opérations au niveau du bit (comme le tilde - pas au niveau du bit) gèrent les valeurs entières signées de 32 bits. Cela signifie que cette magie tilde ne fonctionnera pas après le 19 janvier 2038 lorsque la valeur de l'horodatage sera supérieure à la valeur maximale d'un entier signé de 32 bits. jsfiddle.net/phb20ymb
Sharky
3

Je veux préciser que new Date (). GetTime () renvoie en fait une valeur UTC, c'est donc un moyen vraiment utile de stocker et de gérer les dates d'une manière indépendante des heures localisées.

En d'autres termes, ne vous embêtez pas avec toutes les fonctions javascript UTC. Au lieu de cela, utilisez simplement Date.getTime ().

Plus d'informations sur l'explication est ici: Si javascript "(new Date ()). GetTime ()" est exécuté à partir de 2 fuseaux horaires différents.

Stan Lin
la source
3

J'utilise ce qui suit:

Date.prototype.getUTCTime = function(){ 
  return this.getTime()-(this.getTimezoneOffset()*60000); 
};

Une fois définie cette méthode, vous pouvez faire:

var utcTime = new Date().getUTCTime();
jlbofh
la source
La solution la plus propre. THX!
avalanche1
Mais ce n'est pas une solution propre pour envoyer des dates, car les horodatages sont toujours UTC. La meilleure solution pour moi lors de l'envoi de dates, est d'utiliser une représentation sous forme de chaîne comme "jj / MM / aaaa HH: mm: ss", puis de l'analyser côté serveur avec la zone horaire par défaut du serveur pour obtenir un horodatage UTC ou autre. Voir cette réponse
jlbofh
2
analyser une chaîne - vous appelez cela propre? meh
avalanche1
Assurez-vous qu'il existe des méthodes pour générer une date au format chaîne conformément aux spécifications ISO. La méthode est toISOString (). Vous pouvez l'analyser proprement en Java en utilisant quelque chose comme:DateTime dt = new DateTime ("2018-07-15T02:36:00+02:00");
jlbofh
Une autre mauvaise réponse this.getTime()renvoie un décalage UTC, la soustraction du décalage du fuseau horaire local le rend local, pas UTC, donc getUTCTime renvoie un décalage local, pas UTC.
RobG
2

Je suis étonné de voir à quel point cette question est devenue complexe.

Ce sont tous identiques, et leurs valeurs entières toutes === EPOCH time: D

console.log((new Date()).getTime() / 1000, new Date().valueOf() / 1000, (new Date() - new Date().getTimezoneOffset() * 60 * 1000) / 1000);

Ne me croyez pas, consultez: http://www.epochconverter.com/

fliptopbox
la source
2

Depuis new Date().toUTCString()renvoie une chaîne comme "Wed, 11 Oct 2017 09:24:41 GMT"vous pouvez découper les 3 derniers caractères et passer la chaîne découpée à new Date():

new Date()
// Wed Oct 11 2017 11:34:33 GMT+0200 (CEST)

new Date(new Date().toUTCString().slice(0, -3))
// Wed Oct 11 2017 09:34:33 GMT+0200 (CEST)
Maurice Wipf
la source
1

EDIT: Le code ci-dessous ne fonctionne PAS. J'ai toujours supposé que la nouvelle Date (). GetTime () renvoyait le nombre de secondes depuis le 1er janvier 1970 DANS LE FUSEAU HORAIRE ACTUEL. Ce n'est pas le cas: getTime () renvoie le nombre de secondes en UTC. Ainsi, le code ci-dessous fait un surajustement brut. Merci tout le monde!]

Tout d'abord, merci pour vos idées fantastiques. Je suppose que ma question n'avait pas le bon titre ... elle aurait dû être "Obtenir l'horodatage UTC Unix pour une date existante".

Donc, si j'ai un objet date:

var d = new Date(2009,01,31)

J'étais à la recherche d'une fonction qui me disait "L'horodatage UTC Unix".

Cette fonction semble être la vraie astuce:

Date.prototype.getUTCUnixTime =  function (){
  return Math.floor( new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime() / 1000); 
}

Notez que cela fonctionne sur "ceci" Cela signifie que je peux faire:

var n = new Date(2008,10,10)
...
...

n.getUTCUnixTime();

Et obtenez le nombre de secondes depuis le 1er janvier 1970 à l'heure Unix. Droite?

C'est un peu fou, pour moi, que Javascript stocke tout à l'heure UTC, mais pour obtenir ce numéro, je dois créer un nouvel objet Date en passant les getters UTC individuels, puis enfin appeler getTime () pour cela ...

Merc.

Merc
la source
1
avez-vous vu la mise à jour de @ DCoder concernant sa réponse? Votre méthode getUTCUnixTimeobtient le mauvais moment, et JavaScript ne fournir un moyen simple d'obtenir l'horodatage unix à partir d' un Dateobjet - en utilisant la getTimeméthode. Voir toutes les autres réponses.
Anurag
1
Ugh tu as raison, viens de les voir. (Frapper la tête contre le mur)
Merc
1

Je pense que c'est ce à quoi vous vous attendez ...

var currTimestamp = Date.now(), //1482905176396
    utcDateString = (new Date(currTimestamp)).toUTCString(); //"Wed, 28 Dec 2016 06:06:50 GMT"

Maintenant,

new Date(utcDateString).getTime(); //This will give you UTC Timestamp in JavaScript
Kapilrc
la source
0

Une fois que vous faites cela

new Date(dateString).getTime() / 1000

C'est déjà l'horodatage UTC

   const getUnixTimeUtc = (dateString = new Date()) => Math.round(new Date(dateString).getTime() / 1000)

J'ai testé sur https://www.unixtimestamp.com/index.php

le plus difficile
la source
0

Utilisation de day.js

Dans le navigateur:

dayjs.extend(dayjs_plugin_utc)
console.log(dayjs.utc().unix())
<script src="https://cdn.jsdelivr.net/npm/dayjs@latest/dayjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@latest/plugin/utc.js"></script>

Dans node.js:

import dayjs from 'dayjs'
dayjs.extend(require('dayjs/plugin/utc'))
console.log(dayjs.utc().unix())

Vous obtenez un horodatage UTC unix sans millisecondes.

Ilitch
la source
-2

Cela renverra l'horodatage en UTC:

var utc = new Date(new Date().toUTCString()).getTime();

Yash Pandya
la source
2
Cela ne renvoie pas l'heure en UTC: new Date(new Date().toUTCString())donne Wed Oct 04 2017 07:20:14 GMT + 0200 (GMT + 02: 00)
Bas van Dijk