9

I am trying to get the current UTC date to store in my database. My local time is 9:11 p.m. This equates to 1:11 a.m. UTC. When I look in my database, I notice that 1:11 p.m. is getting written to. I'm confused. In order to get the UTC time in JavaScript, I'm using the following code:

var currentDate = new Date();
var utcDate = Date.UTC(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate(), currentDate.getHours(), currentDate.getMinutes(), currentDate.getSeconds(), currentDate.getMilliseconds());
var result = new Date(utcDate);

What am I doing wrong?

JavaScript Developer
  • 3,968
  • 11
  • 41
  • 46
  • Possible duplicate of [How do you convert a JavaScript date to UTC?](https://stackoverflow.com/questions/948532/how-do-you-convert-a-javascript-date-to-utc) – FZs Jan 28 '19 at 15:15

3 Answers3

3

A lttle searching turned out you can do this:

var now = new Date(),
    utcDate = new Date(
        now.getUTCFullYear(),
        now.getUTCMonth(),
        now.getUTCDate(),
        now.getUTCHours(),
        now.getUTCMinutes(), 
        now.getUTCSeconds()
    );

Even shorter:

var utcDate = new Date(new Date().toUTCString().substr(0, 25));

How do you convert a JavaScript date to UTC?

It is a commonly used way, instead of creating a ISO8601 string, to get date and time of UTC out. Because if you use a string, then you'll not be able to use every single native methods of Date(), and some people might use regex for that, which is slower than native ways.

But if you are storing it in some kind of database like localstorage, a ISO8601 string is recommended because it can also save timezone offsets, but in your case every date is turned into UTC, so timezone really does not matter.

Community
  • 1
  • 1
Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247
  • -1 That isn't a "UTC date", it's a local date object set to a different time that just happens to be the UTC time of some other date object. You can do exactly the same by adjusting the minutes for the timezone offset in far less code. – RobG May 21 '12 at 02:32
  • @RobG - That is the whole point of it. What are you expecting? – Derek 朕會功夫 May 21 '12 at 02:36
  • 1
    @Derek I think he expects an UTC date. If I do this, the result is `Mon May 21 2012 02:51:55 GMT+0300 (FLE Daylight Time)`. That means 23:51 Sunday in UTC, where as UTC time is now `Mon, 21 May 2012 02:53:13` – Esailija May 21 '12 at 02:54
  • @Esailija - I don't understand where is the problem. It returns the correct date, and the correct time in UTC. Also it is [agreed by at least 41 people](http://stackoverflow.com/a/6777470/283863). – Derek 朕會功夫 May 21 '12 at 03:02
  • 1
    @Derek the problem is that it is incorrect. It is representing UTC 23:51 sunday, where as the UTC time was 02:51 monday at the time of running the code. – Esailija May 21 '12 at 03:03
  • @Esailija - I just tested it and there is nothing wrong. Maybe your calculation of UTC time isn't correct? – Derek 朕會功夫 May 21 '12 at 03:06
  • 1
    @Derek what result did you get? The only way it could be correct is that you are on UTC timezone yourself in which case your code does nothing – Esailija May 21 '12 at 03:07
  • @Esailija - My timezone: `Sun May 20 2012 22:12:04 GMT-0500` UTC: `Mon May 21 2012 03:12:04 GMT-0500` (Even RobG agrees this is correct, but he just doesn't agree on the timezone thingy) – Derek 朕會功夫 May 21 '12 at 03:12
  • If the latter is the result of your code, then your time object represents an UTC date of `Mon May 21 2012 08:12:04` which is 5 hours too much in the future. Note the `GMT-0500` at the end, it means Monday 03 **in** `GMT-0500` which is Monday 08 in UTC – Esailija May 21 '12 at 03:14
  • @Esailija - In JavaScript we can't actually change the timezone, that's why we have to "fake" it by setting a UTC time and date inside. No one cares about `GMT-0500` at the end. All we want is the time and date part. You get it now? – Derek 朕會功夫 May 21 '12 at 03:15
  • @Derek nope, if you now turn your date into UTC milliseconds since midnight Jan, 1 1970, it will give monday 08. You don't have to mess with the timezone at all, timezones are for output. – Esailija May 21 '12 at 03:16
  • @Esailija - It is already in UTC time. What should you really do to turn it into milliseconds is this: `+utcDate`. Now, test `new Date(+utcDate);`, it will return `Monday`. – Derek 朕會功夫 May 21 '12 at 03:18
  • @Derek, it's not in UTC time. Turning it into milliseconds gives you monday 08, which is not UTC time but some random time in siberia probably. – Esailija May 21 '12 at 03:19
  • @Esailija - Yes it is. Take a look at RobG's answer. He has the same thing as mine. Although it is in UTC-5, but the time is set to UTC time. – Derek 朕會功夫 May 21 '12 at 03:20
  • @Derek `new Date(+utcDate);` will give the same as `utcDate` was in the first place. It's a date object representing 08 Monday UTC, or 03 GMT-0500. UTC wasn't at 08 when you ran the code, it was at 03. – Esailija May 21 '12 at 03:22
  • @Derek—the problem is that it is a **local date object**, all you've done is adjust the time, its timezone offset is still local and its UTC time will be the local time + the offset. And people **do** care about the offset, that's why it's there and why all times should be in UTC (not local date objects adjusted for UTC). – RobG May 21 '12 at 03:22
  • @RobG - But I don't think there is a way to change the timezone offset in a *Date* object. – Derek 朕會功夫 May 21 '12 at 03:26
  • @Esailija - The OP is saying that the am and pm is flipped. – Derek 朕會功夫 May 21 '12 at 03:41
2

If you want the UTC time of a local date object, use the UTC methods to get it. All javascript date objects are local dates.

var date = new Date(); // date object in local timezone

If you want the UTC time, you can try the implementation dependent toUTCString method:

var UTCstring = date.toUTCString();

but I wouldn't trust that. If you want an ISO8601 string (which most databases want) in UTC time then:

var isoDate = date.getUTCFullYear() + '-' +
              addZ((date.getUTCMonth()) + 1) + '-' +
              addZ(date.getUTCDate()) + 'T' +
              addZ(date.getUTCHours()) + ':' +
              addZ(date.getUTCMinutes()) + ':' +
              addZ(date.getUTCSeconds()) + 'Z';

where the addZ function is:

function addZ(n) {
  return (n<10? '0' : '') + n;
}

Modify to suit.

Edit

To adjust a local date object to display the same time as UTC, just add the timezone offset:

function adjustToUTC(d) {
  d.setMinutes(d.getMinutes() + d.getTimezoneOffset()); 
  return d;
}

alert(adjustToUTC(new Date())); // shows UTC time but will display local offset

Take care with the above. If you are say UTC+5hrs, then it will return a date object 5 hours earlier but still show "UTC+5"

A function to convert a UTC ISO8601 string to a local date object:

function fromUTCISOString(s) {
  var b = s.split(/[-T:\.Z]/i);
  var n= new Date(Date.UTC(b[0],b[1]-1,b[2],b[3],b[4],b[5]));
  return n;
}

alert(fromUTCISOString('2012-05-21T14:32:12Z'));  // local time displayed
Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247
RobG
  • 142,382
  • 31
  • 172
  • 209
  • Of course it is in UTC and the timezone is right. But now you can do nothing about it. `isoDate.getTime()`? Not really. – Derek 朕會功夫 May 21 '12 at 02:45
  • 1
    @Derek—adjusting the time to "fake" a UTC date is bad practice. Far better to use the UTC methods to create local date objects from UTC strings, work with them, then store UTC date strings again. – RobG May 21 '12 at 03:26
  • —But then how do you get the time out of the string? – Derek 朕會功夫 May 21 '12 at 03:28
1
var now = new Date();
var utc = new Date(now.getTime() + now.getTimezoneOffset() * 60000);
Tiago Medici
  • 1,944
  • 22
  • 22