524

I have a web page with three dropdowns for day, month and year. If I use the JavaScript Date constructor that takes numbers, then I get a Date object for my current timezone:

new Date(xiYear, xiMonth, xiDate)

Give the correct date, but it thinks that date is GMT+01:00 due to daylight savings time.

The problem here is that I then pass this Date to an Ajax method and when the date is deserialised on the server it has been converted to GMT and so lost an hour which moves the day back by one. Now I could just pass the day, month, and year individually into the Ajax method, but it seems that there ought to be a better way.

The accepted answer pointed me in the right direction, however just using setUTCHours() by itself changed:

Apr 5th 00:00 GMT+01:00 

to

Apr 4th 23:00 GMT+01:00

I then also had to set the UTC date, month and year to end up with

Apr 5th 01:00 GMT+01:00

which is what I wanted.

0

28 Answers 28

568

using .setUTCHours() it would be possible to actually set dates in UTC-time, which would allow you to use UTC-times throughout the system.

You cannot set it using UTC in the constructor though, unless you specify a date-string.

Using new Date(Date.UTC(year, month, day, hour, minute, second)) you can create a Date-object from a specific UTC time.

Sign up to request clarification or add additional context in comments.

8 Comments

The "new Date(Date.UTC(...))" syntax allows you to create a date which is equivalent to a UTC date in terms of the point in time that it represents, but it is not the same - it has a different (non UTC) time zone.
Keep in mind that when using "Date" the "month"-value has a range from 0-11 (not 1-12). I kept getting a timezone-offset of 2h (while it should have been 1h) and it took me hours to find out that the reason was a wrong month.
Nothing stops you from taking in a "time zone" as a separate parameter and handle it yourself. A Date object i js is always represented as "local" time, you can just choose to set it from a different timezone, but toString() will still show it as the appropriate local time.
@jishi—Date objects are based on a UTC time value, not local time. However, the default Date.prototype.toString method will display local time values.
@Anthony—"but it is not the same time" is not correct. It represents exactly the same moment in time, the only difference is the timezone offset.
|
297
+50

Simply Set the Time Zone and Get Back According

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

Other Time-zones are as Following

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'
];

7 Comments

Very easy, very elegant. You can find here a list with all the timezones stackoverflow.com/questions/38399465/… . For UTC pick London timezone.
None of those values are "timezones", they are IANA timezone database representative locations for places that have the same historic local timezone and daylight saving changes.
@EPurpl3—that is bad advice. Firstly, a stackoverflow answer is not an authority, IANA representative locations should be sought from the IANA timezone database. Secondly, they are not timezones, they're representative locations for places that share the same historic timezone offset changes. Lastly, London observes daylight saving so 'Europe/London' will differ from UTC from the end of March to the end of October every year that daylight saving is observed.
@RobG Yes, you are right. The list includes Daylight Saving Time hours, which can be useful for some. I needed the hour with DST so it was perfect for me. Here is a full list of hours with and without DST. en.wikipedia.org/wiki/List_of_tz_database_time_zones . Soon if you use London as UTC there wont be a DST anymore because on 27 Oct 2019 Europe will scrap DST for ever so it's going to be only 1 hour for London. My answer was a bit ahead of it's time but soon it will be perfect for everybody, not just for some :). timeanddate.com/news/time/europe-may-scrap-dst.html
Thank you but it doesn't work when you want to save dates as Unix timestamps
|
232
var d = new Date(xiYear, xiMonth, xiDate);
d.setTime( d.getTime() + d.getTimezoneOffset()*60*1000 );

This answer is tailored specifically to the original question, and will not give the answer you necessarily expect. In particular, some people will want to subtract the timezone offset instead of add it. Remember though that the whole point of this solution is to hack javascript's date object for a particular deserialization, not to be correct in all cases.

14 Comments

@gthmb of course, but I feel that *60*1000 is clearer in this case; in other words, it is fairly self-evident why it is there.
This almost works for me, except I have to use - (minus) instead of + (plus) to get the right time for my time zone.
Yeah, as others have pointed out - I think there is a mistake in this answer. Should be minus not plus.
According to developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… the value returned by getTimezoneOffset is signed according to the actual offset in your locale at the time you call the function, including taking DST into account, so I don't understand why you'd need to subtract it.
If you add the timezoneOffset to the date object, its value as formatted in the local timezone will look like the correct value in UTC, but it will still have the original timezone offset (and some representations like "ISOString" will actually show it). So depending on how you then serialize the date object, JS might apply the timezone offset again, giving you the wrong answer. I believe this is responsible for the confusion in these comments between +/-. Anyway, my downvote is for this fact and also for the "in most cases you get what you expect".
|
213

I believe you need the createDateAsUTC function (please compare with 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()); 
}

10 Comments

I am amazed about his answer clarity and helpfulness. Did not know that working with Javascript dates was such a nightmare until today :S
Mind explaining the difference between the two? The first converts date into UTC timezone, but the second seems to be doing nothing useful? (returns same date as date)
I get it now: The first returns the date in the UTC timezone, with the literal date values of the local time. The second returns the date in the local timezone, but with the UTC literal date values.
This approach is one implementation of a pattern called "epoch shifting", which is intended to move the epoch (that is UTC based) to one that is shifted by the current time zone offset. Unfortunately, even though this is commonly seen, this approach is flawed. JavaScript's Date object will always reflect the UTC-based unix epoch, and the local time zone. The symptom is apparent when you call toString on the resulting date object and still see the local time zone, even though you expected it to be in UTC.
It also can cause errors in the time values, near the daylight saving time transitions of the local time zone. In short, epoch shifting (via any implementation) does not work with the JavaScript Date object. Another way to see this here is that Date.UTC expects UTC-based values, and you're feeding it local time values, and vise-versa with the Date constructor.
|
28

I don't believe this is possible - there is no ability to set the timezone on a Date object after it is created.

And in a way this makes sense - conceptually (if perhaps not in implementation); per http://en.wikipedia.org/wiki/Unix_timestamp (emphasis mine):

Unix time, or POSIX time, is a system for describing instants in time, defined as the number of seconds elapsed since midnight Coordinated Universal Time (UTC) of Thursday, January 1, 1970.

Once you've constructed one it will represent a certain point in "real" time. The time zone is only relevant when you want to convert that abstract time point into a human-readable string.

Thus it makes sense you would only be able to change the actual time the Date represents in the constructor. Sadly it seems that there is no way to pass in an explicit timezone - and the constructor you are calling (arguably correctly) translates your "local" time variables into GMT when it stores them canonically - so there is no way to use the int, int, int constructor for GMT times.

On the plus side, it's trivial to just use the constructor that takes a String instead. You don't even have to convert the numeric month into a String (on Firefox at least), so I was hoping a naive implementation would work. However, after trying it out it works successfully in Firefox, Chrome, and Opera but fails in Konqueror ("Invalid Date") , Safari ("Invalid Date") and IE ("NaN"). I suppose you'd just have a lookup array to convert the month to a string, like so:

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

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

2 Comments

If there's no way to "set the timezone on a Date object after it is created", are you implying that there's a way to set the timezone on a Date object as it is created? It doesn't look like a js date is "thin wrapper around a number of seconds since the Epoch" - it looks like it's that count of seconds, plus a time zone.
@Anthony, It can only use the client's timezone. Javascript can do local to utc and back but there is no access to a timezone database. It cannot, for example, tell you the Time in Mexico City when you're in San Diego.
23

I know this is old but if it helps you could use moment and moment time zone. If you haven't seen them take a look.

http://momentjs.com/timezone/

http://momentjs.com/

two really handy time manipulation libraries.

Comments

20

If you want to deal with the slightly different, but related, problem of creating a Javascript Date object from year, month, day, ..., including timezone – that is, if you want to parse a string into a Date – then you apparently have to do an infuriatingly complicated dance:

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

That is, you create a 'UTC time' using the date without timezone (so you know what locale it's in, namely the UTC 'locale', and it's not defaulted to the local one), and then manually apply the indicated timezone offset.

Wouldn't it have been nice if someone had actually thought about the Javascript date object for more than, oooh, five minutes....

4 Comments

thanks for the great function! the only thing i would change is add support for the colon in the timezone offset. 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}))?/;
They did think about it; unfortunately, the "they" was the Java language designers, as JS just copied Java's Date class over for its initial implementation.
@Xanthir Oooh, you're right, and I'd forgotten how awful the original Java Date object was; but at least Java deprecated it and moved on, something Javascript seems unable to do (it's a bizarre language, Javascript: rather cute, and not nearly as awful as it first appears to be).
This is probably the answer that I was looking for when I was searching my problem. Thanks for sharing!
15
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

for all location offset Wiki List of UTC time offsets

3 Comments

How does this help for New York during Daylight Savings time?
For New York please use offset value -4
The offset for New York varies according to Daylight Savings time. Sometimes it is -4 and sometimes it is -5 en.wikipedia.org/wiki/Eastern_Time_Zone
10
// 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)

2 Comments

Explaining your code and how it solves the problem will raise the quality of your answer, and help learning users.
Actually works, and is very well documented with comments. It is a very cool way to produce a correct new Date(date).toISOString(). And you can even get the offset by code
8

getTimeZoneOffset is minus for UTC + z.

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

2 Comments

A little mistake, != 0 not > 0. I ended up using this
getTimezoneOffset is negative for purpose, see MDN.
8

This may help someone, put UTC at the end of what you pass in to the new constructor

At least in chrome you can say var date = new Date("2014-01-01 11:00:00 UTC")

2 Comments

Returns "Invalid Date" on Safari
Replace ` UTC` with +0000 (noticed that the space between 00 and UTC need to be removed) and this will work on both Firefox and Chrome. Not sure for Safari though.(Reference: stackoverflow.com/a/17545854/1273587)
7

One line solution

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

Instead of 1422524805305, use the timestamp in milliseconds Instead of 330, use your timezone offset in minutes wrt. GMT (eg India +5:30 is 5*60+30 = 330 minutes)

3 Comments

This would be code run on the client, meaning the timezone is going to be different for your differently located users. This solution would require that everyone who needs it lives in the same timezone (yours).
@Kevin Beal in that case just use getTimezoneOffset
@KevinBeal and why i didnt read your comment before using this code ...
5

The easiest way that I have found to get the correct date is using datejs.

http://www.datejs.com/

I get my dates via Ajax in this format as a string: '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);

Console will read:

Mon Jan 11 2016 19:00:00 GMT-0500 (Eastern Standard Time)

Tue Jan 12 2016 00:00:00 GMT-0500 (Eastern Standard Time)

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

The 'addMinutes' comes from datejs, you could probably do this in pure js on your own, but I already had datejs in my project so I found a way to use it to get the correct dates.

I thought that this might help someone...

1 Comment

Tried all the methods and this was the only one to get midnight which was what I was after!
4

This code will return your Date object formatted with the browser timezone.

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

Edit:

To avoid to pollute the Date API, the above function can be transformed into a utility function. The function takes a Date object, and returns a mutated Date object.

function setTimeZone(date) {
    date.setHours(date.getHours() + (new Date().getTimezoneOffset() / 60));
    return date;
}

2 Comments

No to extending native objects
This answer appears to be incorrect at least when the input date is UTC; it may be correct if you change + to - because for me at +420 offset, hours must be subtracted from UTC to show the correct time. In Israel for example at -180 offset, you'd need to subtract a negative number to add hours to the UTC timestamp.
4

Here is a function that you can use to achieve a date object:

const getUTCDate = (date) => {
    const d = new Date(date);
    const utcDate = new Date(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());
    return utcDate;
}

const string = '1930-08-12T00:00:00.000000Z';

const utcDate = getUTCDate(string);

// returns Tue Aug 12 1930 00:00:00 GMT-0800 (Pacific Daylight Time)

Comments

3

any mileage in

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

1 Comment

This seems to do the trick for me (one time zone away from GMT), but since "locale" is not necessarily timezone related, I wouldn't rely on it.
2

I was having a similar problem with a date picker. My research led to a very simple solution, without any extra libraries or hardcoded multipliers.

Key info:

  1. ISO is the Javascript preferred date standard. Assume date utilities will likely return date values in that format.
    • My date picker displays the date in a localized format: mm/dd/yyyy

    • However, it returns the date value in the ISO format: yyyy-mm-dd

      //Select "08/12/2020" in Date Picker date_input 
      
      var input = $('#date_input').val();  //input: 2020-08-12
      
  1. Date.getTimezoneOffset() returns the offset in minutes.

Examples:

If you use the default returned date value without modifying the string format, the Date might not get set to your timezone. This can lead to unexpected results.

var input = $('#date_input').val();  //input: 2020-08-12
var date = new Date(input);          //This get interpreted as an ISO date, already in UTC
//date:                             Tue Aug 11 2020 20:00:00 GMT-0400 (Eastern Daylight Time)
//date.toUTCString():               Wed, 12 Aug 2020 00:00:00 GMT
//date.toLocaleDateString('en-US'):       8/11/2020

Using a different date string format than the ISO standard yyyy-mm-dd applies your timezone to the Date.

var date = new Date("08/12/2020");  //This gets interpreted as local timezone
//date:                             Wed Aug 12 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
//date.toUTCString():               Wed, 12 Aug 2020 04:00:00 GMT
//date.toLocaleDateString('en-US'):       8/12/2020

Solution:

To apply your timezone to the format-agnostic Date without doing string manipulation, use Date.getTimezoneOffset() with Minutes. This works with either original date string format (i.e. UTC dates or localized dates). It provides a consistent result which can then be converted accurately to UTC for storage or interacting with other code.

var input = $('#date_input').val();
var date = new Date(input);
date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
//date:                             Wed Aug 12 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
//date.toUTCString():               Wed, 12 Aug 2020 04:00:00 GMT
//date.toLocaleDateString('en-US'):       8/12/2020
                

Comments

2

When I create a date object:

new Date(year, month, day, hour, minute)

I works fine on localhost. When I deploy to server it breaks, because server is in another timezone.

I can't use getTimezoneOffset(). I need the timezoneOffset of my home - dependent on summertime/wintertime

// add diff minutes between myself (HOME) and server 
timezoneHomeOffset (d, tz = 'Europe/Copenhagen') {
  const utc = new Date(d.getTime())
  const dHome = new Date(d.toLocaleString('en-US', { timeZone: tz }))
  const diff = Math.round((utc - dHome) / 60000) // 60*1000 => minutes
  d.setMinutes(d.getMinutes() + diff)
  return d
}

Comments

2

It's actually not very hard at all to do this, but it certainly isn't intuitive to come up with the solution. There are some really convoluted answers here (though also some nice ones). Here's what I came up with to make sure my server timestamps would match my local timestamps, no matter what timezone my deployed server happened to be in.

(CET = Central European Timezone, which just happens to be my personal timezone; you can get the offset of any given timezone and calculate it and even make it an argument if you like, but for my purpose, I just needed to get my dates to all be the single desired consistent timezone.)

    const convertDateToCET = function(date) {
        date = new Date(date)
        // let startTime = date.getTime();
        const cetOffset = -120; // this is the number you get from running 
        // `(new Date()).getTimezoneOffset()` if you're on a machine in CET
        const offsetFromCET = (date.getTimezoneOffset() - cetOffset);
        const cetMillsecondOffset = ( cetOffset* 60 * 1000);
        date = new Date( date.getTime() - cetMillsecondOffset ) 
        // let endTime = date.getTime()
        // console.log("updated date from",startTime,"to",endTime)
        return date;
    },

Using this, you just make a time the way you would expect, e.g.

    let myDate = new Date("12-4-2021")
    myDate.setHour(14)
    myDate.setMinute(30)
    // now myDate is 2:30pm, December 4th, 2021, in whatever the timezone the machine of code running happens to be in
    myDate = convertDateToCET(myDate)
    // now myDate will show up as 2:30pm, Dec 4th, 2021, mapped into your local timezone
    // so, if you're in the UK, and one hour behind CET, myDate is now 1:30pm, Dec 4th, 2021

The key here is date.getTimezoneOffset(). If you're actually in CET, that number will be -120, and so it cancels out, making no difference (so CET results in CET out). If you're in the UK, one hour behind CET, that output would be -60, which means -60 + 120 = +60 which results in us changing the input time by one hour, and so on.

It probably makes more sense to convert everything and use everything in UTC for a case like this, but given that all of my input time is in CET and I'd originally developed the system based on how things looked locally on my machine, this utility allowed me to convert the existing code by just making a call to this function in a few key places.

Caution: Make sure not to apply this function call multiple times on the same date, as you'll be reapplying the offset multiple times, throwing it off!

2 Comments

I do really like this solution, though I've come across one major problem: Daylight Savings Time. Means my offset changes in the spring and fall.
Haven't thought about this code in over a year, and it was for a project that only had to last for one month at the time--good catch though! Are you sure it wouldn't be handled automatically though? Seems like that gets implicitly handled as needed according to here if I'm not misreading: stackoverflow.com/questions/11887934/…
2

I had a hard time figuring out that:

new Date('2023-06-16')
// Date Mon Jun 20 2022 17:00:00 GMT-0700 (heure d’été du Pacifique nord-américain) 

is different from

new Date('2023-06-16 00:00:00')
// Date Tue Jun 21 2022 00:00:00 GMT-0700 (heure d’été du Pacifique nord-américain)

Comments

1

Best Solution I have seen from this came from

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

Print Time Function

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

Full Code Example

<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 Comment

Your example excludes Daylight Saving Time. CurrentTime: Fri Oct 04 2013 11:13:43 GMT-0700 (Pacific Daylight Time) UtcTime: Fri, 04 Oct 2013 18:13:43 GMT Banff, Canada: 1213 hrs. Michigan: 1413 hrs. Greenwich, England(UTC): 1913 hrs. Tokyo, Japan: 0413 hrs. Berlin, Germany: 2013 hrs.
1
const date = new Date("2020-12-16 17:45:00 UTC");

Works fine.

1 Comment

new Date("2020-12-16 17:45:00 UTC") -> Invalid Date
1

You can use library to help to change time zone

moment-timezone

var moment = require("moment-timezone");
const today = new Date();
var timeGet = moment(today);
timeGet.tz("Asia/Karachi").format("ha z");

this can change your time zone of your region paste your region area and get real gmt+ resolve issue

For more details visit moment timezone official documentation

1 Comment

Could you add a brief explanation and reference link to the answer for moment-timezone?
1

This worked fine for different timezones (IST, PST, Mexico, Central America):

let dateUtc: any = new Date(Date.parse(data.details.dateOfBirth));

dateUtc = new Date(dateUtc.getTime() + Math.abs(dateUtc.getTimezoneOffset()*60000));

console.log(dateUtc);

Comments

1

For instance, Brazil is at GMT -3 hours. If an application is returning 'GMT+0' datetime instead of my country timezone, it displays 3 hours ahead, so we can adjust this offset using a custom function:

function DateGMT( offset ){
   return new Date( new Date().getTime() + (offset * 60 * 60 * 1000) );  
}

Now I can retrieve a Date - 3 hours, using:

var myDate = DateGMT(-3); // Brazil is GMT-3

Comments

0

if you want to check the difference in a time between two dates, you can simply check if second timezone is lesser or greater from your first desired timezone and subtract or add a time.

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

Comments

-1

I used the timezone-js package.

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

Comments

-17

This is BEST solution

Using:

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

Coffee version:

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

3 Comments

Wow, I don't like it either, but I guess people really hate you overriding the prototype of builtins!
@JoshfromQaribou There is nothing wrong with changing the prototype =) this is a myth and a common misconception. These people just think in a formulaic way, and do not apply critical thinking. They were told that this is bad, they blindly believe in it =) The Matrix is ​​everywhere ahah.
@JoshfromQaribou It's bad to change the prototype IF you are writing a library. If you change the prototype as a PART of your project, then there is nothing wrong with that. For example, if in the future browsers add a method with the same name, then you simply override it =), and it also means that the CURRENT packages that you are using, and your code, DO NOT use the newly added property. These are the basics of javascript, but not everyone understands them =), the fact is that I am a genius programmer and there is a huge gap between my experience and the experience of ordinary people =)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.