229

While writing a web application, it makes sense to store (server side) all datetimes in the DB as UTC timestamps.

I was astonished when I noticed that you couldn't natively do much in terms of Timezone manipulation in JavaScript.

I extended the Date object a little. Does this function make sense? Basically, every time I send anything to the server, it's going to be a timestamp formatted with this function...

Can you see any major problems here? Or maybe a solution from a different angle?

Date.prototype.getUTCTime = function(){ 
  return new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime(); 
}

It just seems a little convoluted to me. And I am not so sure about performance either.

TylerH
  • 20,799
  • 66
  • 75
  • 101
Merc
  • 16,277
  • 18
  • 79
  • 122
  • I know this is kind of an old question, but try not to extend native objects like the Date object. Upvoted because I like the question itself. – trysis Jan 13 '16 at 16:47
  • Date.parse(new Date().toUTCString()) – Sagi Jan 18 '16 at 07:49
  • 65
    This is an old question that came up in my feed today, and it's full of misinformation. **Timestamp is always in UTC.** `new Date().toString()` will show you current time zone time representation, `new Date().toUTCString()` will show you UTC time repr, but `new Date().getTime()` is *always UTC*, because that is what Unix time is defined as: "Unix time (also known as POSIX time or epoch time) is a system for describing instants in time, defined as the number of seconds that have elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970, not counting leap seconds." – Amadan Apr 05 '17 at 01:44

16 Answers16

205
  1. Dates constructed that way use the local timezone, making the constructed date incorrect. To set the timezone of a certain date object is to construct it from a date string that includes the timezone. (I had problems getting that to work in an older Android browser.)

  2. Note that getTime() returns milliseconds, not plain seconds.

For a UTC/Unix timestamp, the following should suffice:

Math.floor((new Date()).getTime() / 1000)

It will factor the current timezone offset into the result. For a string representation, David Ellis' answer works.

To clarify:

new Date(Y, M, D, h, m, s)

That input is treated as local time. If UTC time is passed in, the results will differ. Observe (I'm in GMT +02:00 right now, and it's 07:50):

> var d1 = new Date();
> d1.toUTCString();
"Sun, 18 Mar 2012 05:50:34 GMT" // two hours less than my local time
> Math.floor(d1.getTime()/ 1000)
1332049834 

> var d2 = new Date( d1.getUTCFullYear(), d1.getUTCMonth(), d1.getUTCDate(), d1.getUTCHours(), d1.getUTCMinutes(), d1.getUTCSeconds() );
> d2.toUTCString();
"Sun, 18 Mar 2012 03:50:34 GMT" // four hours less than my local time, and two hours less than the original time - because my GMT+2 input was interpreted as GMT+0!
> Math.floor(d2.getTime()/ 1000)
1332042634

Also note that getUTCDate() cannot be substituted for getUTCDay(). This is because getUTCDate() returns the day of the month; whereas, getUTCDay() returns the day of the week.

Community
  • 1
  • 1
DCoder
  • 12,962
  • 4
  • 40
  • 62
  • 1
    1) I didn't construct a date... I added a prototype function that worked on *this*. 2) Good point, I should do the Math.floor / 1000 -- but still I would need that function in order to have the UTC timestamp of an *existing* date object... right? – Merc Mar 18 '12 at 05:22
  • @Merc: 1) you are calling `new Date()`, that creates a new date from your UTC input but treats it as local date/time. 2) Yes, you should use `Math.floor(this.getTime() / 1000)` in this case. – DCoder Mar 18 '12 at 05:25
  • Answering here as I need to update the code... This is to have the Unix timestamp in UTC for an *existing* date: function (){ return Math.floor( new Date( this.getUTCFullYear(), this.getUTCMonth(), this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds() ).getTime() / 1000); } This means that I can do: var n = new Date(2008,10,10) ... ... n.getUTCTime(); (This will be DIFFERENT to n.getUTCTime() ) – Merc Mar 18 '12 at 05:29
  • 1
    Thanks Bro Its working file Math.floor((new Date()).getTime() / 1000) – Manoj Patel Feb 07 '19 at 09:28
  • I need the UTC Hours and Minutes and this helped me `d1.getUTCHours(), d1.getUTCMinutes()`. – Timo Sep 25 '22 at 06:31
120

The easiest way of getting UTC time in a conventional format is as follows:

> new Date().toISOString()
"2016-06-03T23:15:33.008Z"

if you need EPOC timestamp, pass your date to Date.parse method

> Date.parse(new Date)
1641241000000
> Date.parse('2022-01-03T20:18:05.833Z')
1641241085833

Or you can use + for type casting from Date to Int

> +new Date 
1641921156671

EPOC timestamp in seconds.

> parseInt(Date.parse('2022-01-03T20:18:05.833Z') / 1000)
1641241085
> parseInt(new Date / 1000)
1643302523
Tahsin Turkoz
  • 4,356
  • 1
  • 27
  • 18
74

You could also do it utilizing getTimezoneOffset and getTime,

x = new Date()
var UTCseconds = (x.getTime() + x.getTimezoneOffset()*60*1000)/1000;

console.log("UTCseconds", UTCseconds)
CommonSenseCode
  • 23,522
  • 33
  • 131
  • 186
Shiplu Mokaddim
  • 56,364
  • 17
  • 141
  • 187
  • 7
    Thanks, this is nowhere to be found on the internet! – Theofanis Pantelides Apr 02 '15 at 01:51
  • I test the following codes: `var tt = new Date('Thu Jan 01 1970 08:00:00 GMT+0800 (China Standard Time)'); (tt.getTime() - tt.getTimezoneOffset()*60*1000)/1000`. It seems `tt.getTime() - tt.getTimezoneOffset()` is correct for `GMT+0800`. – zangw Sep 01 '15 at 07:32
  • 2
    This is more better `var UTCseconds = (Math.floor(x.getTime()/1000) + x.getTimezoneOffset()*60)` – StefansArya Jun 27 '17 at 04:13
  • It looks like this doesn't work as written.. It looks like you have to pass in time string into `new Date()` that includes a timezone..which kinda defeats the purpose of trying to do it in js.. – claudekennilol Nov 26 '18 at 18:31
  • 2
    This is simply wrong, the value assigned to *UTCseconds* **is not** UTC seconds.. A Date's time value **is** UTC, changing it by whatever method means it represents a different moment in time. – RobG Apr 07 '20 at 08:07
17

I actually think Date values in js are far better than say the C# DateTime objects. The C# DateTime objects have a Kind property, but no strict underlying time zone as such, and time zone conversions are difficult to track if you are converting between two non UTC and non local times. In js, all Date values have an underlying UTC value which is passed around and known regardless of the offest or time zone conversions that you do. My biggest complaint about the Date object is the amount of undefined behaviour that browser implementers have chosen to include, which can confuse people who attack dates in js with trial and error than reading the spec. Using something like iso8601.js solves this varying behaviour by defining a single implementation of the Date object.

By default, the spec says you can create dates with an extended ISO 8601 date format like

var someDate = new Date('2010-12-12T12:00Z');

So you can infer the exact UTC time this way.

When you want to pass the Date value back to the server you would call

someDate.toISOString();

or if you would rather work with a millisecond timestamp (number of milliseconds from the 1st January 1970 UTC)

someDate.getTime();

ISO 8601 is a standard. You can't be confused about what a date string means if you include the date offset. What this means for you as a developer is that you never have to deal with local time conversions yourself. The local time values exist purely for the benefit of the user, and date values by default display in their local time. All the local time manipulations allow you to display something sensible to the user and to convert strings from user input. It's good practice to convert to UTC as soon as you can, and the js Date object makes this fairly trivial.

On the downside there is not a lot of scope for forcing the time zone or locale for the client (that I am aware of), which can be annoying for website-specific settings, but I guess the reasoning behind this is that it's a user configuration that shouldn't be touched.

So, in short, the reason there isn't a lot of native support for time zone manipulation is because you simply don't want to be doing it.

Matt Esch
  • 22,661
  • 8
  • 53
  • 51
13

You generally don't need to do much of "Timezone manipulation" on the client side. As a rule I try to store and work with UTC dates, in the form of ticks or "number of milliseconds since midnight of January 1, 1970." This really simplifies storage, sorting, calculation of offsets, and most of all, rids you of the headache of the "Daylight Saving Time" adjustments. Here's a little JavaScript code that I use.

To get the current UTC time:

function getCurrentTimeUTC()
{
    //RETURN:
    //      = number of milliseconds between current UTC time and midnight of January 1, 1970
    var tmLoc = new Date();
    //The offset is in minutes -- convert it to ms
    return tmLoc.getTime() + tmLoc.getTimezoneOffset() * 60000;
}

Then what you'd generally need is to format date/time for the end-user for their local timezone and format. The following takes care of all the complexities of date and time formats on the client computer:

function formatDateTimeFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted date/time
    return new Date(nTicks).toLocaleString();
}

function formatDateFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted date
    return new Date(nTicks).toLocaleDateString();
}

function formatTimeFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted time
    return new Date(nTicks).toLocaleTimeString();
}

So the following example:

var ticks = getCurrentTimeUTC();  //Or get it from the server

var __s = "ticks=" + ticks + 
    ", DateTime=" + formatDateTimeFromTicks(ticks) +
    ", Date=" + formatDateFromTicks(ticks) +
    ", Time=" + formatTimeFromTicks(ticks);

document.write("<span>" + __s + "</span>");

Returns the following (for my U.S. English locale):

ticks=1409103400661, DateTime=8/26/2014 6:36:40 PM, Date=8/26/2014, Time=6:36:40 PM

ahmd0
  • 16,633
  • 33
  • 137
  • 233
  • 1
    By adding the `getTimezoneOffset` value in your `getCurrentTimeUTC` function, you're actually returning a different point in time. The result of `getTime` is *already* in UTC. – Matt Johnson-Pint Mar 21 '15 at 16:56
  • 1
    @MattJohnson: That is incorrect. The result of `tmLoc.getTime()` is an offset against local time. That is easy to check if you have access to anything that runs JavaScript. – ahmd0 Mar 24 '15 at 17:59
  • 2
    Sorry, but that's not true. See [the MDN reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime). You can also see this in the ECMAScript spec. [§15.9.3.3 describes `getTime`](http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.3.3), which points you at the "time value" defined in [§15.9.5](http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.5), which is a `PrimitiveValue`, as set in [§15.9.3.3](http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.3.3) explicitly as UTC. – Matt Johnson-Pint Mar 24 '15 at 21:19
  • As an experiment, you can try two machines (with their clocks set correctly) set in two different time zones. Running simultaneously `new Date().getTime()` should result in near identical values, despite the time zone difference. The difference between them should be on the order of seconds or milliseconds due to clock synchronization, but not on the order of hours that time zone adjustments would account for. – Matt Johnson-Pint Mar 24 '15 at 21:21
  • @MattJohnson: Simply get the value from `tmLoc.getTime()` and calculate it yourself "on the back of the napkin." – ahmd0 Mar 24 '15 at 21:38
  • 2
    Well, since you obtain `tmLoc` via `new Date()`, then its the same thing. The time zone will affect the string output of `tmLoc.toString()` and similar items, but it will not affect `tmLoc.getTime()` That's always just a number of milliseconds since midnight 1970-01-01 in UTC. – Matt Johnson-Pint Mar 24 '15 at 21:59
  • Can I know where do you get `60000`? – StefansArya Jun 27 '17 at 04:05
  • 1
    @StefansArya: `//The offset is in minutes -- convert it to ms` – ahmd0 Jun 27 '17 at 16:50
  • So if it was GMT+2, `getTimezoneOffset()` will return `-60*2= -120 minutes` then convert it to ms.. Ok, got the idea. Thanks! – StefansArya Jun 28 '17 at 06:43
13

If you want a one liner, The UTC Unix Timestamp can be created in JavaScript as:

var currentUnixTimestap = ~~(+new Date() / 1000);

This will take in account the timezone of the system. It is basically time elapsed in Seconds since epoch.

How it works:

  • Create date object : new Date().
  • Convert to timestamp by adding unary + before object creation to convert it to timestamp integer. : +new Date().
  • Convert milliseconds to seconds: +new Date() / 1000
  • Use double tildes to round off the value to integer. : ~~(+new Date())
Community
  • 1
  • 1
Kushal Likhi
  • 572
  • 3
  • 7
  • 12
    **Do not use this**. With the current ecma spec, bitwise operations (like the tilde - bitwise not) handle signed integer values of 32 bits. That means this tilde magic **will not work** after 19 jan 2038 when timestamp value will be over the max value of a 32 bit signed integer. https://jsfiddle.net/phb20ymb/ – Sharky Nov 17 '16 at 09:52
  • 2
    @Sharky I use this because it's still not 2038 yet! – jeffbRTC Apr 09 '21 at 19:43
  • I promise to come to downvote this answer 20.1.2038. – Mikko Ohtamaa Dec 01 '22 at 21:50
  • hello from 2023, echo anybody –  Jan 19 '23 at 22:32
7

I think this is a better solution

// UTC milliseconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()

// UTC seconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()/1000|0
koalex
  • 91
  • 1
  • 4
  • 2
    Another wrong answer, *getTime* returns a UTC offset, adding the local timezone offset completely messes it up. The ECMAScript offsets are +ve for west and -ve for east, so they should be subtracted from UTC to get local. But since the time value is UTC to start with, adding it essentially shifts it away from UTC in the opposite direction to the local offset. – RobG Apr 07 '20 at 08:15
7

Since new Date().toUTCString()returns a string like "Wed, 11 Oct 2017 09:24:41 GMT" you can slice the last 3 characters and pass the sliced string to new Date():

new Date()
// Wed Oct 11 2017 11:34:33 GMT+0200 (CEST)

new Date(new Date().toUTCString().slice(0, -3))
// Wed Oct 11 2017 09:34:33 GMT+0200 (CEST)
Maurice Wipf
  • 647
  • 2
  • 7
  • 13
6

I use the following:

Date.prototype.getUTCTime = function(){ 
  return this.getTime()-(this.getTimezoneOffset()*60000); 
};

Once defined this method you can do:

var utcTime = new Date().getUTCTime();
jlbofh
  • 433
  • 5
  • 7
  • Cleanest solution. THX! – avalanche1 Nov 29 '16 at 10:29
  • But that's not a clean solution to send dates, because TimeStamps are always UTC. Best solution for me when sending dates, is to use a string representation like "dd/MM/yyyy HH:mm:ss" and then parse it on server side with server's default TimeZone to get an UTC timestamp or whatever. See this [answer](https://stackoverflow.com/questions/3001260/how-to-detect-client-timezone/51271279#51271279) – jlbofh Jul 10 '18 at 17:59
  • 2
    parsing a string - you're calling that clean? meh – avalanche1 Jul 13 '18 at 22:53
  • Be sure, there are methods to generate a date in string format according to ISO specifications. The method is toISOString(). You can parse it cleanly in Java using something like: `DateTime dt = new DateTime ("2018-07-15T02:36:00+02:00");` – jlbofh Jul 15 '18 at 00:42
  • 1
    Another wrong answer, `this.getTime()` returns a UTC offset, subtracting the local timezone offset makes it local, not UTC so *getUTCTime* returns a local offset, not UTC. – RobG Apr 07 '20 at 08:12
  • I agree... 4 years before ;)... correct method name will be 'getLocalTimestamp'... useless method. – jlbofh Apr 08 '20 at 09:13
4

I want to make clear that new Date().getTime() does in fact return a UTC value, so it is a really helpful way to store and manage dates in a way that is agnostic to localized times.

In other words, don't bother with all the UTC javascript functions. Instead, just use Date.getTime().

More info on the explanation is here: If javascript "(new Date()).getTime()" is run from 2 different Timezones.

Community
  • 1
  • 1
Stan Lin
  • 928
  • 7
  • 6
3

I think this what you are expecting...

var currTimestamp = Date.now(), //1482905176396
    utcDateString = (new Date(currTimestamp)).toUTCString(); //"Wed, 28 Dec 2016 06:06:50 GMT"

Now,

new Date(utcDateString).getTime(); //This will give you UTC Timestamp in JavaScript
Kapilrc
  • 1,362
  • 15
  • 11
2

I am amazed at how complex this question has become.

These are all identical, and their integer values all === EPOCH time :D

console.log((new Date()).getTime() / 1000, new Date().valueOf() / 1000, (new Date() - new Date().getTimezoneOffset() * 60 * 1000) / 1000);

Do not believe me, checkout: http://www.epochconverter.com/

hichris123
  • 10,145
  • 15
  • 56
  • 70
fliptopbox
  • 123
  • 2
1

EDIT: The code below does NOT work. I was always assuming that new Date().getTime() returned the number of seconds since the 1st of January 1970 IN THE CURRENT TIMEZONE. This is not the case: getTime() returns the number of seconds in UTC. So, the code below does gross over-adjusting. Thank you everybody!]

First of all, thank you for your fantastic insights. I guess my question had the wrong title... it should have been "Get the UTC Unix Timestamp for an existing date".

So, if I have a date object:

var d = new Date(2009,01,31)

I was after a function that would tell me "The UTC Unix Timestamp".

This function seems to be the real trick:

Date.prototype.getUTCUnixTime =  function (){
  return Math.floor( new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime() / 1000); 
}

Note that it works on "this" This means that I can do:

var n = new Date(2008,10,10)
...
...

n.getUTCUnixTime();

And get the number of seconds since the 1st of Jan 1970 in Unix time. Right?

It's a little insane, to me, that Javascript stores everything in UTC times, but then in order to get that number I have to create a new Date object passing the individual UTC getters and then finally call getTime() for that...

Merc.

Merc
  • 16,277
  • 18
  • 79
  • 122
  • 1
    did you see @DCoder's update to his answer? Your method `getUTCUnixTime` gets the wrong time, and JavaScript *does* provide a straightforward way to get the unix timestamp from a `Date` object - using the `getTime` method. See all other answers. – Anurag Mar 19 '12 at 03:16
  • 1
    Ugh you are right, just saw them. (Banging head against wall) – Merc Mar 19 '12 at 08:16
0

Once you do this

new Date(dateString).getTime() / 1000

It is already UTC time stamp

   const getUnixTimeUtc = (dateString = new Date()) => Math.round(new Date(dateString).getTime() / 1000)

I tested on https://www.unixtimestamp.com/index.php

fiddlest
  • 1,262
  • 2
  • 17
  • 42
0

Just do:

const time = new Date().getTime();

MDN states that:

Date.prototype.getTime() Returns the numeric value of the specified date as the number of milliseconds since January 1, 1970, 00:00:00 UTC. (Negative values are returned for prior times.)

Gnopor
  • 587
  • 9
  • 16
-3

This will return the timestamp in UTC:

var utc = new Date(new Date().toUTCString()).getTime();
  • 2
    This does not return the time in UTC: `new Date(new Date().toUTCString())` gives Wed Oct 04 2017 07:20:14 GMT+0200 (GMT+02:00) – Bas van Dijk Oct 04 '17 at 05:20