web-dev-qa-db-fra.com

Créer une date avec un fuseau horaire défini sans utiliser de représentation de chaîne

J'ai une page Web avec trois listes déroulantes pour le jour, le mois et l'année. Si j'utilise le constructeur JavaScript Date qui prend des chiffres, j'obtiens un objet Date pour mon fuseau horaire actuel:

new Date(xiYear, xiMonth, xiDate)

Donnez la date correcte, mais elle pense que la date est GMT + 01: 00 en raison de l'heure avancée.

Le problème ici est que je passe ensuite cette Date à une méthode Ajax et que, lorsque la date est désérialisée sur le serveur, elle est convertie au format GMT et perd donc une heure, ce qui ramène la journée d’un jour à le jour, le mois et l'année individuellement dans la méthode Ajax, mais il semble qu'il devrait y avoir une meilleure façon.

La réponse acceptée m’a orientée dans la bonne direction, mais l’utilisation de setUTCHours() en elle-même a changé:

Apr 5th 00:00 GMT+01:00 

à

Apr 4th 23:00 GMT+01:00

J'ai ensuite également dû définir la date, le mois et l'année de l'UTC pour que

Apr 5th 01:00 GMT+01:00

c'est ce que je voulais.

362
Dan

en utilisant .setUTCHours(), il serait possible de définir des dates en heure UTC, ce qui vous permettrait d'utiliser les heures UTC dans tout le système.

Vous ne pouvez cependant pas le définir en utilisant UTC dans le constructeur, sauf si vous spécifiez une chaîne de date.

À l'aide de new Date(Date.UTC(year, month, day, hour, minute, second)), vous pouvez créer un objet Date à partir d'une heure UTC spécifique.

436
jishi
var d = new Date(xiYear, xiMonth, xiDate);
d.setTime( d.getTime() + d.getTimezoneOffset()*60*1000 );

Cette réponse est adaptée spécifiquement à la question initiale et ne donnera pas la réponse que vous attendez nécessairement. En particulier, certaines personnes voudront soustraire le décalage horaire au lieu de l’ajouter. Rappelez-vous cependant que le but de cette solution est de pirater l'objet de date de javascript pour une désérialisation particulière, pour ne pas être correct dans tous les cas.

181
T.W.R. Cole

Je crois que vous avez besoin de la fonction createDateAsUTC (comparez SVP avec convertDateToUTC )

function createDateAsUTC(date) {
    return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()));
}

function convertDateToUTC(date) { 
    return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()); 
}
147
monsterclub

Je ne crois pas que cela soit possible - il n’est pas possible de définir le fuseau horaire d’un objet Date après sa création.

Et d’une certaine manière, cela a un sens - conceptuellement (sinon peut-être pas dans la mise en œuvre); per http://en.wikipedia.org/wiki/Unix_timestamp (l'emphase mienne):

L'heure Unix, ou heure POSIX, est un système permettant de décrire les instants dans le temps, défini comme le nombre de secondes écoulées depuis minuit le temps universel coordonné du jeudi 1er janvier 1970.

Une fois que vous en avez construit un, il représentera un certain moment en temps "réel". Le fuseau horaire n'est pertinent que lorsque vous souhaitez convertir ce point temporel abstrait en une chaîne lisible par l'homme.

Il est donc logique que vous ne puissiez modifier que l’heure réelle que Date représente dans le constructeur. Malheureusement, il semble qu’il n’y ait aucun moyen de passer un fuseau horaire explicite - et le constructeur que vous appelez (sans doute correctement) traduit vos variables de temps "locales" en GMT quand il les stocke de manière canon - il n’ya donc aucun moyen d’utiliser le constructeur int, int, int pour les heures GMT.

Du côté des avantages, il est trivial d’utiliser simplement le constructeur qui prend une chaîne à la place. Vous n'avez même pas besoin de convertir le mois numérique en chaîne (sur Firefox au moins), j'espérais donc une implémentation naïve. Cependant, après l'avoir essayé, il fonctionne correctement dans Firefox, Chrome et Opera, mais échoue dans Konqueror ("Date invalide"), Safari ("Date invalide") et IE ("NaN"). Je suppose que vous auriez juste un tableau de recherche pour convertir le mois en chaîne, comme ceci:

var months = [ '', 'January', 'February', ..., 'December'];

function createGMTDate(xiYear, xiMonth, xiDate) {
   return new Date(months[xiMonth] + ' ' + xiDate + ', ' + xiYear + ' 00:00:00 GMT');
}
25
Andrzej Doyle

Je sais que c'est vieux, mais si cela vous aide, vous pouvez utiliser l'instant et le fuseau horaire. Si vous ne les avez pas vus, jetez un coup d'oeil. 

http://momentjs.com/timezone/

http://momentjs.com/

deux bibliothèques de manipulation du temps très pratique.

17
ChewOnThis_Trident

Si vous souhaitez traiter le problème légèrement différent, mais lié, de la création d'un objet Date en Javascript à partir d'année, mois, jour, ..., y compris le fuseau horaire _ c'est-à-dire, si vous souhaitez analyser une chaîne dans une Date - alors vous devez apparemment faire une danse compliquée exaspérante:

// parseISO8601String : string -> Date
// Parse an ISO-8601 date, including possible timezone,
// into a Javascript Date object.
//
// Test strings: parseISO8601String(x).toISOString()
// "2013-01-31T12:34"              -> "2013-01-31T12:34:00.000Z"
// "2013-01-31T12:34:56"           -> "2013-01-31T12:34:56.000Z"
// "2013-01-31T12:34:56.78"        -> "2013-01-31T12:34:56.780Z"
// "2013-01-31T12:34:56.78+0100"   -> "2013-01-31T11:34:56.780Z"
// "2013-01-31T12:34:56.78+0530"   -> "2013-01-31T07:04:56.780Z"
// "2013-01-31T12:34:56.78-0330"   -> "2013-01-31T16:04:56.780Z"
// "2013-01-31T12:34:56-0330"      -> "2013-01-31T16:04:56.000Z"
// "2013-01-31T12:34:56Z"          -> "2013-01-31T12:34:56.000Z"
function parseISO8601String(dateString) {
    var timebits = /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2})(?::([0-9]*)(\.[0-9]*)?)?(?:([+-])([0-9]{2})([0-9]{2}))?/;
    var m = timebits.exec(dateString);
    var resultDate;
    if (m) {
        var utcdate = Date.UTC(parseInt(m[1]),
                               parseInt(m[2])-1, // months are zero-offset (!)
                               parseInt(m[3]),
                               parseInt(m[4]), parseInt(m[5]), // hh:mm
                               (m[6] && parseInt(m[6]) || 0),  // optional seconds
                               (m[7] && parseFloat(m[7])*1000) || 0); // optional fraction
        // utcdate is milliseconds since the Epoch
        if (m[9] && m[10]) {
            var offsetMinutes = parseInt(m[9]) * 60 + parseInt(m[10]);
            utcdate += (m[8] === '+' ? -1 : +1) * offsetMinutes * 60000;
        }
        resultDate = new Date(utcdate);
    } else {
        resultDate = null;
    }
    return resultDate;
}

En d'autres termes, vous créez une "heure UTC" en utilisant la date sans le fuseau horaire (vous savez donc dans quel environnement local se trouve, à savoir le "environnement local" UTC, et non le paramètre local par défaut), puis vous appliquez manuellement le décalage de fuseau horaire indiqué.

N'aurait-il pas été agréable si quelqu'un avait en fait pensé l'objet de la date Javascript pendant plus de, oooh, cinq minutes ...

16
Norman Gray
d = new Date();
utc = d.getTime() + (d.getTimezoneOffset() * 60000);
nd = new Date(utc + (3600000*offset));

offset value base on which location time zone you would like to set 
For India offset value +5.5,
New York offset value -4,
London offset value +1

pour tout décalage d'emplacement Liste des décalages d'heure UTC par le wiki

13
Vijay Lathiya

Solution en une ligne 

new Date(new Date(1422524805305).getTime() - 330*60*1000)

Au lieu de 1422524805305, utilisez l'horodatage en millisecondes Au lieu de 330, utilisez votre décalage horaire en minutes par rapport à GMT (par exemple Inde +5: 30 soit 5 * 60 + 30 = 330 minutes)

9
Vinay Vemula

Cela peut aider quelqu'un, mettez UTC à la fin de ce que vous transmettez au nouveau constructeur.

Au moins en chrome, vous pouvez dire var date = new Date("2014-01-01 11:00:00 UTC")

8
Drew LeSueur

getTimeZoneOffset est moins pour UTC + z. 

var d = new Date(xiYear, xiMonth, xiDate);
if(d.getTimezoneOffset() > 0){
    d.setTime( d.getTime() + d.getTimezoneOffset()*60*1000 );
}
7
rinjan

Le moyen le plus simple que j'ai trouvé pour obtenir la date correcte est d'utiliser datejs. 

http://www.datejs.com/

Je reçois mes dates via Ajax dans ce format sous forme de chaîne: '2016-01-12T00: 00: 00'

var yourDateString = '2016-01-12T00:00:00';
var yourDate = new Date(yourDateString);
console.log(yourDate);
if (yourDate.getTimezoneOffset() > 0){
    yourDate = new Date(yourDateString).addMinutes(yourDate.getTimezoneOffset());
}
console.log(yourDate);

La console va lire:

Lundi 11 janvier 2016 19:00:00 GMT-0500 (heure normale de l'Est)

Mar 12 janv. 2016 00:00:00 GMT-0500 (heure normale de l'Est)

https://jsfiddle.net/vp1ena7b/3/

Les 'addMinutes' viennent de datejs, vous pouvez probablement le faire vous-même, mais j'ai déjà eu datejs dans mon projet, j'ai donc trouvé un moyen de l'utiliser pour obtenir les bonnes dates. 

Je pensais que cela pourrait aider quelqu'un ... 

5
Barry Franklin
// My clock 2018-07-25, 00:26:00 (GMT+7)
let date = new Date(); // 2018-07-24:17:26:00 (Look like GMT+0)
const myTimeZone = 7; // my timeZone 
// my timeZone = 7h = 7 * 60 * 60 * 1000 (millisecond);
// 2018-07-24:17:26:00 = x (milliseconds)
// finally, time in milliseconds (GMT+7) = x + myTimezone 
date.setTime( date.getTime() + myTimeZone * 60 * 60 * 1000 );
// date.toISOString() = 2018-07-25, 00:26:00 (GMT+7)
4
Tuan Nguyen

tout kilométrage dans 

var d = new Date(xiYear, xiMonth, xiDate).toLocaleString();
2
meouw

Ce code renverra votre objet Date au format du fuseau horaire du navigateur.

Date.prototype.timezone = function () {
    this.setHours(this.getHours() + (new Date().getTimezoneOffset() / 60));
    return this;
}
2
Marco Dal Zovo

La meilleure solution que j'ai vue de cela vient de 

http://www.codingforums.com/archive/index.php/t-19663.html

Fonction heure d'impression

<script language="javascript" type="text/javascript">
//borrowed from echoecho
//http://www.echoecho.com/ubb/viewthread.php?tid=2362&pid=10482&#pid10482
workDate = new Date()
UTCDate = new Date()
UTCDate.setTime(workDate.getTime()+workDate.getTimezoneOffset()*60000)

function printTime(offset) {
    offset++;
    tempDate = new Date()
    tempDate.setTime(UTCDate.getTime()+3600000*(offset))
    timeValue = ((tempDate.getHours()<10) ? ("0"+tempDate.getHours()) : (""+tempDate.getHours()))
    timeValue += ((tempDate.getMinutes()<10) ? ("0"+tempDate.getMinutes()) : tempDate.getMinutes())
    timeValue += " hrs."
    return timeValue
    }
    var now = new Date()
    var seed = now.getTime() % 0xfffffff
    var same = Rand(12)
</script>

Banff, Canada:
<script language="JavaScript">document.write(printTime("-7"))</script>

Exemple de code complet

<html>

<head>
<script language="javascript" type="text/javascript">
//borrowed from echoecho
//http://www.echoecho.com/ubb/viewthread.php?tid=2362&pid=10482&#pid10482
workDate = new Date()
UTCDate = new Date()
UTCDate.setTime(workDate.getTime()+workDate.getTimezoneOffset()*60000)

function printTime(offset) {
offset++;
tempDate = new Date()
tempDate.setTime(UTCDate.getTime()+3600000*(offset))
timeValue = ((tempDate.getHours()<10) ? ("0"+tempDate.getHours()) : (""+tempDate.getHours()))
timeValue += ((tempDate.getMinutes()<10) ? ("0"+tempDate.getMinutes()) : tempDate.getMinutes())
timeValue += " hrs."
return timeValue
}
var now = new Date()
var seed = now.getTime() % 0xfffffff
var same = Rand(12)
</script>

</head>

<body>
Banff, Canada:
<script language="JavaScript">document.write(printTime("-7"))</script>
<br>
Michigan:
<script language="JavaScript">document.write(printTime("-5"))</script>
<br>
Greenwich, England(UTC):
<script language="JavaScript">document.write(printTime("-0"))</script>
<br>
Tokyo, Japan:
<script language="JavaScript">document.write(printTime("+9"))</script>
<br>
Berlin, Germany:
<script language="JavaScript">document.write(printTime("+1"))</script>

</body>
</html>
1

Il suffit de définir le fuseau horaire et de revenir en fonction

new Date().toLocaleString("en-US", {timeZone: "America/New_York"})
1
Matee Gojra