Question

Suppose a user of your website enters a date range.

2009-1-1 to 2009-1-3

You need to send this date to a server for some processing, but the server expects all dates and times to be in UTC.

Now suppose the user is in Alaska or Hawaii or Fiji. Since they are in a timezone quite different from UTC, the date range needs to be converted to something like this:

2009-1-1T8:00:00 to 2009-1-4T7:59:59

Using the JavaScript Date object, how would you convert the first "localized" date range into something the server will understand?

Was it helpful?

Solution

The toISOString() method returns a string in simplified extended ISO format (ISO 8601), which is always 24 or 27 characters long (YYYY-MM-DDTHH:mm:ss.sssZ or ±YYYYYY-MM-DDTHH:mm:ss.sssZ, respectively). The timezone is always zero UTC offset, as denoted by the suffix "Z".

Source: MDN web docs

The format you need is created with the .toISOString() method. For older browsers (ie8 and under), which don't natively support this method, the shim can be found here:

This will give you the ability to do what you need:

var isoDate = new Date('yourdatehere').toISOString();

For Timezone work, moment.js and moment.js timezone are really invaluable tools...especially for navigating timezones between client and server javascript.

OTHER TIPS

Simple and stupid

var date = new Date(); 
var now_utc =  Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(),
 date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());

 return new Date(now_utc);

Here's my method:

var now = new Date();
var utc = new Date(now.getTime() + now.getTimezoneOffset() * 60000);

The resulting utc object isn't really a UTC date, but a local date shifted to match the UTC time (see comments). However, in practice it does the job.

Date.prototype.toUTCArray= function(){
    var D= this;
    return [D.getUTCFullYear(), D.getUTCMonth(), D.getUTCDate(), D.getUTCHours(),
    D.getUTCMinutes(), D.getUTCSeconds()];
}

Date.prototype.toISO= function(){
    var tem, A= this.toUTCArray(), i= 0;
    A[1]+= 1;
    while(i++<7){
        tem= A[i];
        if(tem<10) A[i]= '0'+tem;
    }
    return A.splice(0, 3).join('-')+'T'+A.join(':');    
}

Convert to ISO without changing date/time

var now = new Date(); // Fri Feb 20 2015 19:29:31 GMT+0530 (India Standard Time) 
var isoDate = new Date(now.getTime() - now.getTimezoneOffset() * 60000).toISOString();
//OUTPUT : 2015-02-20T19:29:31.238Z

Convert to ISO with change in date/time(date/time will be changed)

isoDate = new Date(now).toISOString();
//OUTPUT : 2015-02-20T13:59:31.238Z 

Fiddle link

Browsers may differ, and you should also remember to not trust any info generated by the client, that being said, the below statement works for me (Google Chrome v24 on Mac OS X 10.8.2)

var utcDate = new Date(new Date().getTime());


edit: "How is this different than just new Date()?" see here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

  • If no arguments are provided, the constructor creates a JavaScript Date object for the current date and time according to system settings.
  • Note: Where Date is called as a constructor with more than one argument, the specifed arguments represent local time. If UTC is desired, use new Date(Date.UTC(...)) with the same arguments. (note: Date.UTC() returns the number of millisecond since 1970-01-01 00:00:00 UTC)

Adding the 60000 * Date.getTimezoneOffset() as previous answers have stated is incorrect. First, you must think of all Dates/Times as already being UTC with a timezone modifier for display purposes.

Again, browsers may differ, however, Date.getTime() returns the number of milliseconds since 1970-01-01 UTC/GMT. If you create a new Date using this number as I do above, it will be UTC/GMT. However, if you display it by calling .toString() it will appear to be in your local timezone because .toString() uses your local timezone, not the timezone of the Date object it is called on.

I have also found that if you call .getTimezoneOffset() on a date, it will return your local timezone, not the timezone of the date object you called it on (I can't verify this to be standard however).

In my browser, adding 60000 * Date.getTimezoneOffset() creates a DateTime that is not UTC. However when displayed within my browser (ex: .toString() ), it displays a DateTime in my local timezone that would be correct UTC time if timezone info is ignored.

var myDate = new Date(); // Set this to your date in whichever timezone.
var utcDate = myDate.toUTCString();

Are you trying to convert the date into a string like that?

I'd make a function to do that, and, though it's slightly controversial, add it to the Date prototype. If you're not comfortable with doing that, then you can put it as a standalone function, passing the date as a parameter.

Date.prototype.getISOString = function() {
    var zone = '', temp = -this.getTimezoneOffset() / 60 * 100;
    if (temp >= 0) zone += "+";
    zone += (Math.abs(temp) < 100 ? "00" : (Math.abs(temp) < 1000 ? "0" : "")) + temp;

    // "2009-6-4T14:7:32+10:00"
    return this.getFullYear()   // 2009
         + "-"
         + (this.getMonth() + 1) // 6
         + "-"
         + this.getDate()       // 4
         + "T"
         + this.getHours()      // 14
         + ":"
         + this.getMinutes()    // 7
         + ":"
         + this.getSeconds()    // 32
         + zone.substr(0, 3)    // +10
         + ":"
         + String(temp).substr(-2) // 00
    ;
};

If you needed it in UTC time, just replace all the get* functions with getUTC*, eg: getUTCFullYear, getUTCMonth, getUTCHours... and then just add "+00:00" at the end instead of the user's timezone offset.

date = '2012-07-28'; stringdate = new Date(date).toISOString();

ought to work in most newer browsers. it returns 2012-07-28T00:00:00.000Z on Firefox 6.0

My recommendation when working with dates is to parse the date into individual fields from user input. You can use it as a full string, but you are playing with fire.

JavaScript can treat two equal dates in different formats differently.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse

Never do anything like:

new Date('date as text');

Once you have your date parsed into its individual fields from user input, create a date object. Once the date object is created convert it to UTC by adding the time zone offset. I can't stress how important it is to use the offset from the date object due to DST (that's another discussion however to show why).

var year = getFullYear('date as text');
var month = getMonth('date as text');
var dayOfMonth = getDate('date as text');

var date = new Date(year, month, dayOfMonth);

var offsetInMs = ((date.getTimezoneOffset() * 60)  // Seconds
                 * 1000);                          //  Milliseconds

var utcDate = new Date(date.getTime + offsetInMs);

Now you can pass the date to the server in UTC time. Again I would highly recommend against using any date strings. Either pass it to the server broken down to the lowest granularity you need e.g. year, month, day, minute or as a value like milliseconds from the unix epoch.

If you are dealing with dates a lot, it's worth using moment.js (http://momentjs.com). The method to convert to UTC would be:

moment(yourTime).utc()

You can use format to change your date to any format you want:

moment(yourTime).utc().format("YYYY-MM-DD")

There is offset options in moment as well but there is an additional complementary library for dealing with timezone (http://momentjs.com/timezone/). The time conversion would be as simple as this:

moment.tz(yourUTCTime, "America/New_York")

Another solution to convert to UTC and keep it as a date object: (It works by removing the ' GMT' part from the end of the formatted string, then putting it back into the Date constructor)

var now = new Date();
var now_utc = new Date(now.toUTCString().slice(0, -4));

I needed to do this to interface with a datetime picker library. But in general it's a bad idea to work with dates this way.

Users generally want to work with datetimes in their local time, so you either update the server side code to parse datetime strings with offsets correctly, then convert to UTC (best option) or you convert to a UTC string client-side before sending to the server (like in Will Stern's answer)

I just discovered that the 1.2.3 version of Steven Levithan's date.format.js does just what I want. It allows you to supply a format string for a JavaScript date and will convert from local time to UTC. Here's the code I'm using now:

// JavaScript dates don't like hyphens!    
var rectifiedDateText = dateText.replace(/-/g, "/");
var d = new Date(rectifiedDateText);

// Using a predefined mask from date.format.js.
var convertedDate = dateFormat(d, 'isoUtcDateTime'); 

I've found the jQuery Globalization Plugin date parsing to work best. Other methods had cross-browser issues and stuff like date.js had not been updated in quite a while.

You also don't need a datePicker on the page. You can just call something similar to the example given in the docs:

$.parseDate('yy-mm-dd', '2007-01-26');

This function works beautifully for me.

function ParseDateForSave(dateValue) {
    // create a new date object
    var newDate = new Date(parseInt(dateValue.substr(6)));

    // return the UTC version of the date
    return newDate.toISOString();
}

Using moment.js UTC method;

const moment = require('moment');
const utc = moment.utc(new Date(string));

This is what I have done in the past:

var utcDateString = new Date(new Date().toUTCString()).toISOString();

Looking at your question its clear that you just want to send the date range to your backend for further post processing.

I am assuming you are conforming to the standard data guidelines which expect the data to be in a particular format. For example, I use ODATA which is a RESTfull API which expects date time objects to be in the format:-

YYYY-MM-DDT00:00:00.

That can be easily achieved via the snippet posted below(Please change the format as per your requirement).

var mydate;//assuming this is my date object which I want to expose var UTCDateStr = mydate.getUTCFullYear() + "-" + mydate.getUTCMonth() + "-" + mydate.getUTCDate() + "T00:00:00";

If on the other hand, you are in my situation wherein you have received a date from your backend, and the browser converts that to your local date. You on the other hand are interested in the UTC date then you can perform the following:-

var mydate;//assuming this is my date object which I want to expose var UTCDate = new Date(mydate);/*create a copy of your date object. Only needed if you for some reason need the original local date*/ UTCDate.setTime(UTCDate.getTime() + UTCDate.getTimezoneOffset() * 60 * 1000);

The code snippet above basically adds/subtracts the time added/subtracted by the browser based on the timezone.

For example if I am in EST(GMT-5) and my Service returns a date time object = Wed Aug 17 2016 00:00:00 GMT-0500 my browser automatically subtracts the timezone offset(5hrs) to get my local time. So if I try to fetch the time I get Wed Aug 16 2016 19:00:00 GMT-0500. This causes a lot of problems. There are a lot of libraries out there which will definitely make this easier but I wanted to share the pure JS approach.

For more info please have a look at: http://praveenlobo.com/blog/how-to-convert-javascript-local-date-to-utc-and-utc-to-local-date/ where in I got my inspiration.

Hope this helps!

var userdate = new Date("2009-1-1T8:00:00Z");
var timezone = userdate.getTimezoneOffset();
var serverdate = new Date(userdate.setMinutes(userdate.getMinutes()+parseInt(timezone)));

This will give you the proper UTC Date and Time.
It's because the getTimezoneOffset() will give you the timezone difference in minutes. I recommend you that not to use toISOString() because the output will be in the string Hence in future you will not able to manipulate the date

This method will give you : 2017-08-04T11:15:00.000+04:30 and you can ignore zone variable to simply get 2017-08-04T11:15:00.000.

function getLocalIsoDateTime(dtString) {
    if(dtString == "")
        return "";
    var offset = new Date().getTimezoneOffset();
    var localISOTime = (new Date(new Date(dtString) - offset * 60000 /*offset in milliseconds*/)).toISOString().slice(0,-1);
    //Next two lines can be removed if zone isn't needed.
    var absO = Math.abs(offset);
    var zone = (offset < 0 ? "+" : "-") + ("00" + Math.floor(absO / 60)).slice(-2) + ":" + ("00" + (absO % 60)).slice(-2);
    return localISOTime + zone;
}

If you need Date Object

Passing only date string Date assumes time to be 00:00 shifted by time zone:

new Date('2019-03-11')
Sun Mar 10 2019 18:00:00 GMT-0600 (Central Standard Time)

If you add current hours and minutes you get proper date:

new Date('2019-03-11 ' + new Date().getHours() + ':' + new Date().getMinutes())
Mon Mar 11 2019 04:36:00 GMT-0600 (Central Standard Time)

Using moment package, you can easily convert a date string of UTC to a new Date object:

const moment = require('moment');
let b = new Date(moment.utc('2014-02-20 00:00:00.000000'));
let utc = b.toUTCString();
b.getTime();

This specially helps when your server do not support timezone and you want to store UTC date always in server and get it back as a new Date object. Above code worked for my requirement of similar issue that this thread is for. Sharing here so that it can help others. I do not see exactly above solution in any answer. Thanks.

I know this question is old, but was looking at this same issue, and one option would be to send date.valueOf() to the server instead. the valueOf() function of the javascript Date sends the number of milliseconds since midnight January 1, 1970 UTC.

valueOf()

So this is the way I had to do it because i still wanted a JavaScript date object to manipulate as a date and unfortunantly alot of these answers require you to go to a string.

//First i had a string called stringDateVar that i needed to convert to Date
var newDate = new Date(stringDateVar)

//output: 2019-01-07T04:00:00.000Z
//I needed it 2019-01-07T00:00:00.000Z because i had other logic that was dependent on that 

var correctDate = new Date(newDate.setUTCHours(0))

//This will output 2019-01-07T00:00:00.000Z on everything which allows scalability 

Even simpler

myvar.setTime(myvar.getTime() + myvar.getTimezoneOffset() * 60000);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top