186 votes

Comment formater une date au format ISO 8601 avec un décalage de fuseau horaire en JavaScript ?

Objectif : Trouvez le local time y UTC time offset puis construire l'URL dans le format suivant.

Exemple d'URL : /Actions/Sleep?duration=2002-10-10T12:00:0005:00

Le format est basé sur le Recommandation du W3C . La documentation dit :

Par exemple, 2002-10-10T12:00:0005:00 (midi le 10 octobre 2002, heure d'été centrale et heure normale de l'Est aux États-Unis) est égal à 2002-10-10T17:00:00Z, soit cinq heures plus tard que 2002-10-10T12:00:00Z.

Donc, d'après ce que j'ai compris, je dois trouver mon heure locale en new Date() puis utiliser getTimezoneOffset() pour calculer la différence et l'attacher à la fin de la chaîne.

  1. Obtenez l'heure locale avec format

    var local = new Date().format("yyyy-MM-ddThh:mm:ss"); // 2013-07-02T09:00:00
  2. Obtenir l'heure UTC décalée d'une heure

    var offset = local.getTimezoneOffset() / 60; // 7
  3. Construct URL (à temps partiel uniquement)

    var duration = local + "-" + offset + ":00"; // 2013-07-02T09:00:00-7:00

La sortie ci-dessus signifie que mon heure locale est 2013/07/02 9h00 et que la différence avec l'UTC est de 7 heures (l'UTC est en avance de 7 heures sur l'heure locale).

Jusqu'à présent, cela semble fonctionner, mais que faire si getTimezoneOffset() renvoie une valeur négative comme -120 ?

Je me demande à quoi devrait ressembler le format dans un tel cas, car je n'arrive pas à le comprendre à partir de la documentation du W3C.

293voto

Steven Moseley Points 6405

Voici une fonction d'aide simple qui formatera les dates JS pour vous.

function toIsoString(date) {
  var tzo = -date.getTimezoneOffset(),
      dif = tzo >= 0 ? '+' : '-',
      pad = function(num) {
          return (num < 10 ? '0' : '') + num;
      };

  return date.getFullYear() +
      '-' + pad(date.getMonth() + 1) +
      '-' + pad(date.getDate()) +
      'T' + pad(date.getHours()) +
      ':' + pad(date.getMinutes()) +
      ':' + pad(date.getSeconds()) +
      dif + pad(Math.floor(Math.abs(tzo) / 60)) +
      ':' + pad(Math.abs(tzo) % 60);
}

var dt = new Date();
console.log(toIsoString(dt));

82voto

Matt Johnson Points 33433

getTimezoneOffset() renvoie le signe opposé au format requis par la spécification que vous avez référencée.

Ce format est également connu sous le nom de ISO8601 ou, plus précisément, comme RFC3339 .

Dans ce format, l'UTC est représenté par un signe Z tandis que tous les autres formats sont représentés par un décalage par rapport à l'UTC. La signification est la même que celle de JavaScript, mais l'ordre de la soustraction est inversé, de sorte que le résultat porte le signe opposé.

De plus, il n'y a pas de méthode sur l'interface native Date objet appelé format Par conséquent, votre fonction du point 1 échouera, à moins que vous n'utilisiez une bibliothèque pour y parvenir. Référez-vous à cette documentation .

Si vous cherchez une bibliothèque qui peut travailler directement avec ce format, je vous recommande d'essayer moment.js . En fait, il s'agit du format par défaut, vous pouvez donc simplement le faire :

var m = moment();    // get "now" as a moment
var s = m.format();  // the ISO format is the default so no parameters are needed

// sample output:   2013-07-01T17:55:13-07:00

Il s'agit d'une solution bien testée, compatible avec tous les navigateurs, qui présente de nombreuses autres caractéristiques utiles.

46voto

Tom Points 4834

Je pense que cela vaut la peine de considérer que vous pouvez obtenir l'information demandée avec un seul appel API à la bibliothèque standard...

new Date().toLocaleString( 'sv', { timeZoneName: 'short' } );

// produces "2019-10-30 15:33:47 GMT−4"

Vous devrez procéder à une permutation de texte si vous souhaitez ajouter le délimiteur 'T', supprimer le 'GMT-' ou ajouter le ':00' à la fin.

Mais alors vous pouvez facilement jouer avec les autres options si vous voulez, par exemple, utiliser l'heure de 12h ou omettre les secondes, etc.

Notez que j'utilise la Suède comme locale car c'est l'un des pays qui utilise le format ISO 8601. Je pense que la plupart des pays ISO utilisent ce format 'GMT-4' pour le décalage horaire, à l'exception du Canada qui utilise l'abréviation du fuseau horaire, par exemple "EDT" pour Eastern-daylight-time.

Vous pouvez obtenir la même chose avec la nouvelle fonction standard i18n "Intl.DateTimeFormat()". mais vous devez lui demander d'inclure l'heure via les options ou elle ne donnera que la date.

23voto

Jonathan Steele Points 307

Ma réponse est une légère variation pour ceux qui veulent simplement la date du jour dans le fuseau horaire local au format AAAA-MM-JJ.

Laissez-moi être clair :

Mon but : obtenir date du jour en le fuseau horaire de l'utilisateur mais formaté en ISO8601 (AAAA-MM-JJ)

Voici le code :

new Date().toLocaleDateString("sv") // "2020-02-23" // 

Cela fonctionne parce que la locale suédoise utilise le format ISO 8601.

8voto

Jay Points 138

Voici ma fonction pour le fuseau horaire des clients, elle est légère et simple.

  function getCurrentDateTimeMySql() {        
      var tzoffset = (new Date()).getTimezoneOffset() * 60000; //offset in milliseconds
      var localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0, 19).replace('T', ' ');
      var mySqlDT = localISOTime;
      return mySqlDT;
  }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X