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

412

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

new Date(xiYear, xiMonth, xiDate)

Donnez la date correcte, mais il pense que la date est GMT + 01: 00 en raison de l'heure d'été.

Le problème ici est que je passe ensuite cela Dateà une méthode Ajax et lorsque la date est désérialisée sur le serveur, elle a été convertie en GMT et a donc perdu une heure, ce qui fait reculer la journée d'une unité. Maintenant, je pourrais simplement passer 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é dans la bonne direction, mais le simple fait d'utiliser setUTCHours()en soi a changé:

Apr 5th 00:00 GMT+01:00 

à

Apr 4th 23:00 GMT+01:00

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

Apr 5th 01:00 GMT+01:00

c'est ce que je voulais.

Dan
la source
9
Si la réponse acceptée vous indiquait la bonne direction mais ne répondait pas à votre question, je dirais que ce ne devrait pas être la réponse acceptée. La réponse doit répondre à la question posée.
TWR Cole

Réponses:

481

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

Cependant, vous ne pouvez 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.

jishi
la source
101
La syntaxe "new Date (Date.UTC (...))" vous permet de créer une date équivalente à une date UTC en termes de temps qu'elle représente, mais ce n'est pas la même - elle a un fuseau horaire différent (non UTC).
Anthony
52
Gardez à l'esprit que lorsque vous utilisez "Date", la valeur "mois" a une plage de 0 à 11 (pas de 1 à 12). J'ai continué à obtenir un décalage horaire de 2h (alors qu'il aurait dû être 1h) et il m'a fallu des heures pour découvrir que la raison était un mauvais mois.
Select0r
4
Cette réponse est excellente. Mais j'utilise une bibliothèque [datepicker ui] qui utilise la nouvelle date à de nombreux endroits. Tout ce que je veux, c'est définir le fuseau horaire UTC et chaque date est selon le nouveau fuseau horaire. Je suis surpris que Javascript n'ait rien pour cela.
Sanjeev Kumar Dangi
6
@ jishi: les objets de date sont basés sur une valeur d'heure UTC et non sur l'heure locale. Toutefois, la méthode Date.prototype.toString par défaut affichera les valeurs d'heure locale.
RobG
5
@ Anthony - " mais ce n'est pas en même temps " n'est pas correct. Il représente exactement le même moment dans le temps, la seule différence est le décalage du fuseau horaire.
RobG
199
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 d'origine et ne donnera pas la réponse que vous attendez nécessairement. En particulier, certaines personnes voudront soustraire le décalage du fuseau horaire au lieu de l'ajouter. Souvenez-vous cependant que le but de cette solution est de pirater l'objet date de javascript pour une désérialisation particulière, pour ne pas être correct dans tous les cas.

TWR Cole
la source
62
@gthmb bien sûr, mais je pense que *60*1000c'est plus clair dans ce cas; en d'autres termes, il est assez évident pourquoi il est là.
TWR Cole
22
Cela fonctionne presque pour moi, sauf que je dois utiliser - (moins) au lieu de + (plus) pour obtenir le bon moment pour mon fuseau horaire.
Wytze
3
Oui, comme d'autres l'ont souligné - je pense qu'il y a une erreur dans cette réponse. Doit être moins pas plus.
UpTheCreek
3
Selon developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…, la valeur renvoyée par getTimezoneOffset est signée en fonction du décalage réel dans votre environnement local au moment où vous appelez la fonction, y compris en tenant compte de l'heure d'été, donc je ne comprends pas pourquoi vous devez le soustraire.
TWR Cole
15
Si vous ajoutez le timezoneOffset à l'objet date, sa valeur telle que formatée dans le fuseau horaire local ressemblera à la valeur correcte en UTC, mais il aura toujours le décalage de fuseau horaire d'origine (et certaines représentations comme "ISOString" le montreront en fait). Ainsi, selon la façon dont vous sérialisez ensuite l'objet date, JS peut appliquer à nouveau le décalage de fuseau horaire , vous donnant la mauvaise réponse. Je crois que cela est responsable de la confusion dans ces commentaires entre +/-. Quoi qu'il en soit, mon downvote est pour ce fait et aussi pour "dans la plupart des cas, vous obtenez ce que vous attendez".
metamatt
173

Je crois que vous avez besoin de la fonction createDateAsUTC (veuillez comparer 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()); 
}
monsterclub
la source
36
Je suis étonné de la clarté et de l'utilité de sa réponse. Je ne savais pas que travailler avec des dates Javascript était un tel cauchemar jusqu'à aujourd'hui: S
will824
Voulez-vous expliquer la différence entre les deux? Le premier se transforme dateen fuseau horaire UTC, mais le second ne semble rien faire d'utile? (retourne la même date que date)
Jonathan Lin
4
Je comprends maintenant: le premier renvoie la date dans le fuseau horaire UTC, avec les valeurs de date littérales de l'heure locale. La seconde renvoie la date dans le fuseau horaire local, mais avec les valeurs de date littérales UTC.
Jonathan Lin
8
Cette approche est une implémentation d'un modèle appelé "décalage d'époque", qui est destiné à déplacer l'époque (qui est basée sur UTC) vers une qui est décalée par le décalage de fuseau horaire actuel. Malheureusement, même si cela est courant, cette approche est défectueuse. L' Dateobjet de JavaScript reflétera toujours l'époque Unix basée sur UTC et le fuseau horaire local . Le problème est apparent lorsque vous appelez toStringl'objet de date résultant et que vous voyez toujours le fuseau horaire local, même si vous vous attendiez à ce qu'il soit en UTC.
Matt Johnson-Pint
2
Cela peut également provoquer des erreurs dans les valeurs d'heure, près des transitions d'heure d'été du fuseau horaire local. En bref, le décalage d'époque (via n'importe quelle implémentation) ne fonctionne pas avec l' Dateobjet JavaScript . Une autre façon de voir cela ici est d' Date.UTCattendre des valeurs basées sur UTC, et vous lui fournissez des valeurs d'heure locale, et vice-versa avec le Dateconstructeur.
Matt Johnson-Pint du
70

Réglez simplement le fuseau horaire et revenez selon

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

Les autres fuseaux horaires sont les suivants

var world_timezones =
[
    'Europe/Andorra',
    'Asia/Dubai',
    'Asia/Kabul',
    'Europe/Tirane',
    'Asia/Yerevan',
    'Antarctica/Casey',
    'Antarctica/Davis',
    'Antarctica/DumontDUrville', 
    'Antarctica/Mawson',
    'Antarctica/Palmer',
    'Antarctica/Rothera',
    'Antarctica/Syowa',
    'Antarctica/Troll',
    'Antarctica/Vostok',
    'America/Argentina/Buenos_Aires',
    'America/Argentina/Cordoba',
    'America/Argentina/Salta',
    'America/Argentina/Jujuy',
    'America/Argentina/Tucuman',
    'America/Argentina/Catamarca',
    'America/Argentina/La_Rioja',
    'America/Argentina/San_Juan',
    'America/Argentina/Mendoza',
    'America/Argentina/San_Luis',
    'America/Argentina/Rio_Gallegos',
    'America/Argentina/Ushuaia',
    'Pacific/Pago_Pago',
    'Europe/Vienna',
    'Australia/Lord_Howe',
    'Antarctica/Macquarie',
    'Australia/Hobart',
    'Australia/Currie',
    'Australia/Melbourne',
    'Australia/Sydney',
    'Australia/Broken_Hill',
    'Australia/Brisbane',
    'Australia/Lindeman',
    'Australia/Adelaide',
    'Australia/Darwin',
    'Australia/Perth',
    'Australia/Eucla',
    'Asia/Baku',
    'America/Barbados',
    'Asia/Dhaka',
    'Europe/Brussels',
    'Europe/Sofia',
    'Atlantic/Bermuda',
    'Asia/Brunei',
    'America/La_Paz',
    'America/Noronha',
    'America/Belem',
    'America/Fortaleza',
    'America/Recife',
    'America/Araguaina',
    'America/Maceio',
    'America/Bahia',
    'America/Sao_Paulo',
    'America/Campo_Grande',
    'America/Cuiaba',
    'America/Santarem',
    'America/Porto_Velho',
    'America/Boa_Vista',
    'America/Manaus',
    'America/Eirunepe',
    'America/Rio_Branco',
    'America/Nassau',
    'Asia/Thimphu',
    'Europe/Minsk',
    'America/Belize',
    'America/St_Johns',
    'America/Halifax',
    'America/Glace_Bay',
    'America/Moncton',
    'America/Goose_Bay',
    'America/Blanc-Sablon',
    'America/Toronto',
    'America/Nipigon',
    'America/Thunder_Bay',
    'America/Iqaluit',
    'America/Pangnirtung',
    'America/Atikokan',
    'America/Winnipeg',
    'America/Rainy_River',
    'America/Resolute',
    'America/Rankin_Inlet',
    'America/Regina',
    'America/Swift_Current',
    'America/Edmonton',
    'America/Cambridge_Bay',
    'America/Yellowknife',
    'America/Inuvik',
    'America/Creston',
    'America/Dawson_Creek',
    'America/Fort_Nelson',
    'America/Vancouver',
    'America/Whitehorse',
    'America/Dawson',
    'Indian/Cocos',
    'Europe/Zurich',
    'Africa/Abidjan',
    'Pacific/Rarotonga',
    'America/Santiago',
    'America/Punta_Arenas',
    'Pacific/Easter',
    'Asia/Shanghai',
    'Asia/Urumqi',
    'America/Bogota',
    'America/Costa_Rica',
    'America/Havana',
    'Atlantic/Cape_Verde',
    'America/Curacao',
    'Indian/Christmas',
    'Asia/Nicosia',
    'Asia/Famagusta',
    'Europe/Prague',
    'Europe/Berlin',
    'Europe/Copenhagen',
    'America/Santo_Domingo',
    'Africa/Algiers',
    'America/Guayaquil',
    'Pacific/Galapagos',
    'Europe/Tallinn',
    'Africa/Cairo',
    'Africa/El_Aaiun',
    'Europe/Madrid',
    'Africa/Ceuta',
    'Atlantic/Canary',
    'Europe/Helsinki',
    'Pacific/Fiji',
    'Atlantic/Stanley',
    'Pacific/Chuuk',
    'Pacific/Pohnpei',
    'Pacific/Kosrae',
    'Atlantic/Faroe',
    'Europe/Paris',
    'Europe/London',
    'Asia/Tbilisi',
    'America/Cayenne',
    'Africa/Accra',
    'Europe/Gibraltar',
    'America/Godthab',
    'America/Danmarkshavn',
    'America/Scoresbysund',
    'America/Thule',
    'Europe/Athens',
    'Atlantic/South_Georgia',
    'America/Guatemala',
    'Pacific/Guam',
    'Africa/Bissau',
    'America/Guyana',
    'Asia/Hong_Kong',
    'America/Tegucigalpa',
    'America/Port-au-Prince',
    'Europe/Budapest',
    'Asia/Jakarta',
    'Asia/Pontianak',
    'Asia/Makassar',
    'Asia/Jayapura',
    'Europe/Dublin',
    'Asia/Jerusalem',
    'Asia/Kolkata',
    'Indian/Chagos',
    'Asia/Baghdad',
    'Asia/Tehran',
    'Atlantic/Reykjavik',
    'Europe/Rome',
    'America/Jamaica',
    'Asia/Amman',
    'Asia/Tokyo',
    'Africa/Nairobi',
    'Asia/Bishkek',
    'Pacific/Tarawa',
    'Pacific/Enderbury',
    'Pacific/Kiritimati',
    'Asia/Pyongyang',
    'Asia/Seoul',
    'Asia/Almaty',
    'Asia/Qyzylorda',
    'Asia/Qostanay', 
    'Asia/Aqtobe',
    'Asia/Aqtau',
    'Asia/Atyrau',
    'Asia/Oral',
    'Asia/Beirut',
    'Asia/Colombo',
    'Africa/Monrovia',
    'Europe/Vilnius',
    'Europe/Luxembourg',
    'Europe/Riga',
    'Africa/Tripoli',
    'Africa/Casablanca',
    'Europe/Monaco',
    'Europe/Chisinau',
    'Pacific/Majuro',
    'Pacific/Kwajalein',
    'Asia/Yangon',
    'Asia/Ulaanbaatar',
    'Asia/Hovd',
    'Asia/Choibalsan',
    'Asia/Macau',
    'America/Martinique',
    'Europe/Malta',
    'Indian/Mauritius',
    'Indian/Maldives',
    'America/Mexico_City',
    'America/Cancun',
    'America/Merida',
    'America/Monterrey',
    'America/Matamoros',
    'America/Mazatlan',
    'America/Chihuahua',
    'America/Ojinaga',
    'America/Hermosillo',
    'America/Tijuana',
    'America/Bahia_Banderas',
    'Asia/Kuala_Lumpur',
    'Asia/Kuching',
    'Africa/Maputo',
    'Africa/Windhoek',
    'Pacific/Noumea',
    'Pacific/Norfolk',
    'Africa/Lagos',
    'America/Managua',
    'Europe/Amsterdam',
    'Europe/Oslo',
    'Asia/Kathmandu',
    'Pacific/Nauru',
    'Pacific/Niue',
    'Pacific/Auckland',
    'Pacific/Chatham',
    'America/Panama',
    'America/Lima',
    'Pacific/Tahiti',
    'Pacific/Marquesas',
    'Pacific/Gambier',
    'Pacific/Port_Moresby',
    'Pacific/Bougainville',
    'Asia/Manila',
    'Asia/Karachi',
    'Europe/Warsaw',
    'America/Miquelon',
    'Pacific/Pitcairn',
    'America/Puerto_Rico',
    'Asia/Gaza',
    'Asia/Hebron',
    'Europe/Lisbon',
    'Atlantic/Madeira',
    'Atlantic/Azores',
    'Pacific/Palau',
    'America/Asuncion',
    'Asia/Qatar',
    'Indian/Reunion',
    'Europe/Bucharest',
    'Europe/Belgrade',
    'Europe/Kaliningrad',
    'Europe/Moscow',
    'Europe/Simferopol',
    'Europe/Kirov',
    'Europe/Astrakhan',
    'Europe/Volgograd',
    'Europe/Saratov',
    'Europe/Ulyanovsk',
    'Europe/Samara',
    'Asia/Yekaterinburg',
    'Asia/Omsk',
    'Asia/Novosibirsk',
    'Asia/Barnaul',
    'Asia/Tomsk',
    'Asia/Novokuznetsk',
    'Asia/Krasnoyarsk',
    'Asia/Irkutsk',
    'Asia/Chita',
    'Asia/Yakutsk',
    'Asia/Khandyga',
    'Asia/Vladivostok',
    'Asia/Ust-Nera',
    'Asia/Magadan',
    'Asia/Sakhalin',
    'Asia/Srednekolymsk',
    'Asia/Kamchatka',
    'Asia/Anadyr',
    'Asia/Riyadh',
    'Pacific/Guadalcanal',
    'Indian/Mahe',
    'Africa/Khartoum',
    'Europe/Stockholm',
    'Asia/Singapore',
    'America/Paramaribo',
    'Africa/Juba',
    'Africa/Sao_Tome',
    'America/El_Salvador',
    'Asia/Damascus',
    'America/Grand_Turk',
    'Africa/Ndjamena',
    'Indian/Kerguelen',
    'Asia/Bangkok',
    'Asia/Dushanbe',
    'Pacific/Fakaofo',
    'Asia/Dili',
    'Asia/Ashgabat',
    'Africa/Tunis',
    'Pacific/Tongatapu',
    'Europe/Istanbul',
    'America/Port_of_Spain',
    'Pacific/Funafuti',
    'Asia/Taipei',
    'Europe/Kiev',
    'Europe/Uzhgorod',
    'Europe/Zaporozhye',
    'Pacific/Wake',
    'America/New_York',
    'America/Detroit',
    'America/Kentucky/Louisville',
    'America/Kentucky/Monticello',
    'America/Indiana/Indianapolis',
    'America/Indiana/Vincennes',
    'America/Indiana/Winamac',
    'America/Indiana/Marengo',
    'America/Indiana/Petersburg',
    'America/Indiana/Vevay',
    'America/Chicago',
    'America/Indiana/Tell_City',
    'America/Indiana/Knox',
    'America/Menominee',
    'America/North_Dakota/Center',
    'America/North_Dakota/New_Salem',
    'America/North_Dakota/Beulah',
    'America/Denver',
    'America/Boise',
    'America/Phoenix',
    'America/Los_Angeles',
    'America/Anchorage',
    'America/Juneau',
    'America/Sitka',
    'America/Metlakatla',
    'America/Yakutat',
    'America/Nome',
    'America/Adak',
    'Pacific/Honolulu',
    'America/Montevideo',
    'Asia/Samarkand',
    'Asia/Tashkent',
    'America/Caracas',
    'Asia/Ho_Chi_Minh',
    'Pacific/Efate',
    'Pacific/Wallis',
    'Pacific/Apia',
    'Africa/Johannesburg'
];
Matee Gojra
la source
8
Cela devrait être bien au sommet
Eugene
Sauf que sachez que cela ne fonctionne pas dans certains navigateurs. Par exemple. IE11.
Paul LeBeau
Erreur dans la console IE: la valeur de l'option «AMERICA / NEW_YORK» pour «timeZone» est en dehors de la plage valide. Attendu: ['UTC'] @OloghoCyrilPaul
Matee Gojra
1
Très facile, très élégant. Vous pouvez trouver ici une liste avec tous les fuseaux horaires stackoverflow.com/questions/38399465/… . Pour UTC, choisissez le fuseau horaire de Londres.
EPurpl3
1
Aucune de ces valeurs n'est un "fuseau horaire", ce sont des emplacements représentatifs de la base de données de fuseau horaire IANA pour les lieux qui ont le même fuseau horaire local et les changements d'heure d'été.
RobG
28

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

Et d'une certaine manière, cela a du sens - conceptuellement (sinon peut-être dans la mise en œuvre); par http://en.wikipedia.org/wiki/Unix_timestamp (accent sur le mien):

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

Une fois que vous en aurez construit un, il représentera un certain point 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 l'heure réelle que la date représente dans le constructeur. Malheureusement, il semble qu'il n'y ait aucun moyen de passer dans un fuseau horaire explicite - et le constructeur que vous appelez (sans doute correctement) traduit vos variables de temps "locales" en GMT lorsqu'il les stocke de manière canonique - il n'y a donc aucun moyen d'utiliser le int, int, intconstructeur pour Horaires GMT.

Sur le plan positif, 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 une chaîne (au moins sur Firefox), alors j'espérais qu'une implémentation naïve fonctionnerait. Cependant, après l'avoir essayé, il fonctionne avec succès dans Firefox, Chrome et Opera mais échoue dans Konqueror ("Date non valide"), Safari ("Date non valide") 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');
}
Andrzej Doyle
la source
6
S'il n'y a aucun moyen de "définir le fuseau horaire sur un objet Date après sa création", voulez-vous dire qu'il existe un moyen de définir le fuseau horaire sur un objet Date lors de sa création? Il ne semble pas qu'une date js soit "une enveloppe mince autour d'un certain nombre de secondes depuis l'époque" - il semble que ce soit le nombre de secondes, plus un fuseau horaire.
Anthony
1
@Anthony, il ne peut utiliser que le fuseau horaire du client. Javascript peut faire du local vers utc et inversement mais il n'y a pas accès à une base de données de fuseau horaire. Il ne peut pas, par exemple, vous indiquer l'heure à Mexico lorsque vous êtes à San Diego.
Samuel Danielson
20

Je sais que c'est vieux mais si cela vous aide, vous pouvez utiliser le moment et le fuseau horaire. Si vous ne les avez pas vus, jetez un œil.

http://momentjs.com/timezone/

http://momentjs.com/

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

ChewOnThis_Trident
la source
16

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

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

C'est-à-dire que vous créez une `` heure UTC '' en utilisant la date sans fuseau horaire (afin que vous sachiez dans quel lieu il se trouve, à savoir le `` lieu '' UTC, et il n'est pas défini par défaut sur l'heure locale), puis appliquez manuellement le décalage de fuseau horaire indiqué.

Cela n'aurait-il pas été bien si quelqu'un avait réellement pensé à l'objet date Javascript pendant plus de, oooh, cinq minutes ...

Norman Gray
la source
1
merci pour la grande fonction! la seule chose que je changerais est d'ajouter la prise en charge des deux points dans le décalage du fuseau horaire. 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}))? /;
robnardo
2
Ils y ont pensé; malheureusement, "ils" étaient les concepteurs du langage Java, car JS venait de copier la classe Date de Java pour son implémentation initiale.
Xanthir
@ Xanthir Oooh, vous avez raison, et j'avais oublié à quel point l'objet Java Date était horrible; mais au moins Java l'a déprécié et est passé à autre chose, ce que Javascript semble incapable de faire (c'est un langage bizarre, Javascript: plutôt mignon, et pas aussi horrible qu'il n'y paraît).
Norman Gray
13
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 tous les décalages d'emplacement Liste Wiki des décalages horaires UTC

Vijay Lathiya
la source
Comment cela aide-t-il New York pendant l'heure d'été?
frederj
Pour New York, veuillez utiliser la valeur de décalage -4
Vijay Lathiya
1
Le décalage pour New York varie en fonction de l'heure d'été. Parfois c'est -4 et parfois c'est -5 fr.wikipedia.org/wiki/Eastern_Time_Zone
frederj
8

getTimeZoneOffset est négatif pour UTC + z.

var d = new Date(xiYear, xiMonth, xiDate);
if(d.getTimezoneOffset() > 0){
    d.setTime( d.getTime() + d.getTimezoneOffset()*60*1000 );
}
rinjan
la source
1
Une petite erreur,! = 0 pas> 0. J'ai fini par utiliser cela
Cristi Băluță
8

Cela peut aider quelqu'un, mettre UTC à la fin de ce que vous passez au nouveau constructeur

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

Drew LeSueur
la source
1
Retourne "Date invalide" sur Safari
pmrotule
1
Remplacez `UTC` par +0000(remarquez que l'espace entre 00 et UTC doit être supprimé) et cela fonctionnera à la fois sur Firefox et Chrome. Pas sûr pour Safari cependant. (Référence: stackoverflow.com/a/17545854/1273587 )
cytsunny
8

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 le décalage de votre fuseau horaire en minutes wrt. GMT (par exemple, l'Inde +5: 30 est 5 * 60 + 30 = 330 minutes)

Vinay Vemula
la source
4
Ce serait du code exécuté sur le client, ce qui signifie que le fuseau horaire sera différent pour vos utilisateurs situés différemment. Cette solution exigerait que tous ceux qui en ont besoin vivent dans le même fuseau horaire (le vôtre).
Kevin Beal
@Kevin Beal dans ce cas, utilisez simplement getTimezoneOffset
maximus
6
// 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)
Tuan Nguyen
la source
Expliquer votre code et comment il résout le problème améliorera la qualité de votre réponse et aidera les utilisateurs à apprendre.
Nic3500
5

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 affichera:

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

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

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

Les 'addMinutes' viennent de datejs, vous pourriez probablement le faire vous-même en pur js, mais j'avais déjà des datejs dans mon projet, j'ai donc trouvé un moyen de l'utiliser pour obtenir les dates correctes.

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

Barry Franklin
la source
J'ai essayé toutes les méthodes et c'était la seule à avoir minuit, c'était ce que je cherchais!
SharpC
3

tout kilométrage en

var d = new Date(xiYear, xiMonth, xiDate).toLocaleString();
meouw
la source
Cela semble faire l'affaire pour moi (un fuseau horaire loin de GMT), mais comme "locale" n'est pas nécessairement lié au fuseau horaire, je ne m'y fierais pas.
Wytze
3

Ce code renverra votre objet Date formaté avec le fuseau horaire du navigateur .

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

Éditer:

Pour éviter de polluer l'API Date, la fonction ci-dessus peut être transformée en fonction utilitaire. La fonction prend un objet Date et retourne un objet Date muté.

function setTimeZone(date) {
    date.setHours(date.getHours() + (new Date().getTimezoneOffset() / 60));
    return date;
}
Marco Dal Zovo
la source
6
Non à l'extension des objets natifs
Paul Rumkin
1

La meilleure solution que j'ai vue de cela est venue de

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

Fonction de temps 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>
Jeffrey L. Roberts
la source
Votre exemple exclut l'heure d'été. Heure actuelle: ven 04 oct 2013 11 h 13 min 43 s GMT-0700 (heure avancée du Pacifique) Heure exacte: ven 04 oct 2013 18 h 13 min 43 s GMT Banff, Canada: 12 h 13. Michigan: 1413 heures. Greenwich, Angleterre (UTC): 1913 heures. Tokyo, Japon: 0413 heures. Berlin, Allemagne: 2013 hrs.
Jeson Martajaya
0

si vous voulez vérifier la différence de temps entre deux dates, vous pouvez simplement vérifier si le deuxième fuseau horaire est inférieur ou supérieur au premier fuseau horaire souhaité et soustraire ou ajouter une heure.

  const currTimezone = new Date().getTimezoneOffset(); // your timezone
  const newDateTimezone = date.getTimezoneOffset(); // date with unknown timezone

  if (currTimezone !== newDateTimezone) {
    // and below you are checking if difference should be - or +. It depends on if unknown timezone is lesser or greater than yours
    const newTimezone = (currTimezone - newDateTimezone) * (currTimezone > newDateTimezone ? 1 : -1);
    date.setTime(date.getTime() + (newTimezone * 60 * 1000));
  }
Piosek
la source
0

GMT -03: 00 Exemple

new Date(new Date()-3600*1000*3).toISOString();  // 2020-02-27T15:03:26.261Z

Ou même

now  = new Date().getTime()-3600*1000*3; // 1582818380528
data = new Date(now).toISOString();      // 2020-02-27T15:03:26.261Z
Rafael Xavier
la source
-1

Cela a fonctionné pour moi. Je ne sais pas si c'est une bonne idée.

var myDate = new Date();
console.log('myDate:', myDate);   // myDate: "2018-04-04T01:09:38.112Z"

var offset = '+5';  // e.g. if the timeZone is -5

var MyDateWithOffset = new Date( myDate.toGMTString() + offset );   

console.log('MyDateWithOffset:', MyDateWithOffset); // myDateWithOffset: "2018-04-03T20:09:38.000Z"

ofmoreno06
la source
-1

J'ai utilisé le package timezone-js.

var timezoneJS  = require('timezone-js');
var tzdata = require('tzdata');

createDate(dateObj) {
    if ( dateObj == null ) {
        return null;
    }
    var nativeTimezoneOffset = new Date().getTimezoneOffset();
    var offset = this.getTimeZoneOffset();

    // use the native Date object if the timezone matches
    if ( offset == -1 * nativeTimezoneOffset ) {
        return dateObj;
    }

    this.loadTimeZones();

    // FIXME: it would be better if timezoneJS.Date was an instanceof of Date
    //        tried jquery $.extend
    //        added hack to Fiterpickr to look for Dater.getTime instead of "d instanceof Date"
    return new timezoneJS.Date(dateObj,this.getTimeZoneName());
},
Stephen Ince
la source
-11

C'est la MEILLEURE solution

En utilisant:

// TO ALL dates
Date.timezoneOffset(-240) // +4 UTC

// Override offset only for THIS date
new Date().timezoneOffset(-180) // +3 UTC

Code:

Date.prototype.timezoneOffset = new Date().getTimezoneOffset();

Date.setTimezoneOffset = function(timezoneOffset) {
  return this.prototype.timezoneOffset = timezoneOffset;
};

Date.getTimezoneOffset = function() {
  return this.prototype.timezoneOffset;
};

Date.prototype.setTimezoneOffset = function(timezoneOffset) {
  return this.timezoneOffset = timezoneOffset;
};

Date.prototype.getTimezoneOffset = function() {
  return this.timezoneOffset;
};

Date.prototype.toString = function() {
  var offsetDate, offsetTime;
  offsetTime = this.timezoneOffset * 60 * 1000;
  offsetDate = new Date(this.getTime() - offsetTime);
  return offsetDate.toUTCString();
};

['Milliseconds', 'Seconds', 'Minutes', 'Hours', 'Date', 'Month', 'FullYear', 'Year', 'Day'].forEach((function(_this) {
  return function(key) {
    Date.prototype["get" + key] = function() {
      var offsetDate, offsetTime;
      offsetTime = this.timezoneOffset * 60 * 1000;
      offsetDate = new Date(this.getTime() - offsetTime);
      return offsetDate["getUTC" + key]();
    };
    return Date.prototype["set" + key] = function(value) {
      var offsetDate, offsetTime, time;
      offsetTime = this.timezoneOffset * 60 * 1000;
      offsetDate = new Date(this.getTime() - offsetTime);
      offsetDate["setUTC" + key](value);
      time = offsetDate.getTime() + offsetTime;
      this.setTime(time);
      return time;
    };
  };
})(this));

Version café:

Date.prototype.timezoneOffset = new Date().getTimezoneOffset()


Date.setTimezoneOffset = (timezoneOffset)->
    return @prototype.timezoneOffset = timezoneOffset


Date.getTimezoneOffset = ->
    return @prototype.timezoneOffset


Date.prototype.setTimezoneOffset = (timezoneOffset)->
    return @timezoneOffset = timezoneOffset


Date.prototype.getTimezoneOffset = ->
    return @timezoneOffset


Date.prototype.toString = ->
    offsetTime = @timezoneOffset * 60 * 1000
    offsetDate = new Date(@getTime() - offsetTime)
    return offsetDate.toUTCString()


[
    'Milliseconds', 'Seconds', 'Minutes', 'Hours',
    'Date', 'Month', 'FullYear', 'Year', 'Day'
]
.forEach (key)=>
    Date.prototype["get#{key}"] = ->
        offsetTime = @timezoneOffset * 60 * 1000
        offsetDate = new Date(@getTime() - offsetTime)
        return offsetDate["getUTC#{key}"]()

    Date.prototype["set#{key}"] = (value)->
        offsetTime = @timezoneOffset * 60 * 1000
        offsetDate = new Date(@getTime() - offsetTime)
        offsetDate["setUTC#{key}"](value)
        time = offsetDate.getTime() + offsetTime
        @setTime(time)
        return time
Maxmaxmaximus
la source
2
Wow, je n'aime pas ça non plus, mais je suppose que les gens vous détestent vraiment en remplaçant le prototype des builtins!
Josh de Qaribou le