Create a Date with a set timezone without using a string representation

Create a Date with a set timezone without using a string representation

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

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.


Solution 1:

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.

Solution 2:

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.

Solution 3:

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

Solution 4:

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 (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');

Solution 5:

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.

two really handy time manipulation libraries.

Solution 6:

Simply Set the Time Zone and Get Back According

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