Goal: Find the local time
and UTC time offset
then construct the URL in following format.
Example URL: /Actions/Sleep?duration=2002-10-10T12:00:00-05:00
The format is based on the W3C recommendation: http://www.w3.org/TR/xmlschema11-2/#dateTime
The documentation says:
For example, 2002-10-10T12:00:00-05:00 (noon on 10 October 2002, Central Daylight Savings Time as well as Eastern Standard Time in the U.S.) is equal to 2002-10-10T17:00:00Z, five hours later than 2002-10-10T12:00:00Z.
So based on my understanding, I need to find my local time by new Date() then use getTimezoneOffset() function to compute the difference then attach it to the end of string.
1.Get local time with format
var local = new Date().format("yyyy-MM-ddThh:mm:ss"); //today (local time)
output
2013-07-02T09:00:00
2.Get UTC time offset by hour
var offset = local.getTimezoneOffset() / 60;
output
7
3.Construct URL (time part only)
var duration = local + "-" + offset + ":00";
output:
2013-07-02T09:00:00-7:00
The above output means my local time is 2013/07/02 9am and difference from UTC is 7 hours (UTC is 7 hours ahead of local time)
So far it seems to work but what if getTimezoneOffset() returns negative value like -120?
I'm wondering how the format should look like in such case because I cannot figure out from W3C document. Thanks in advance.
This question is related to
javascript
timezone
date-formatting
My answer is a slight variation for those who just want today's date in the local timezone in the YYYY-MM-DD format.
Let me be clear:
My Goal: get today's date in the user's timezone but formatted as ISO8601 (YYYY-MM-DD)
Here is the code:
new Date().toLocaleDateString("sv") // "2020-02-23" //
This works because the Sweden locale uses the ISO 8601 format.
This is my function for the clients timezone, it's lite weight and simple
function getCurrentDateTimeMySql() {
var tzoffset = (new Date()).getTimezoneOffset() * 60000; //offset in milliseconds
var localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0, 19).replace('T', ' ');
var mySqlDT = localISOTime;
return mySqlDT;
}
I think it is worth considering that you can get the requested info with just a single API call to the standard library...
new Date().toLocaleString( 'sv', { timeZoneName: 'short' } );
// produces "2019-10-30 15:33:47 GMT-4"
You would have to do text swapping if you want to add the 'T' delimiter, remove the 'GMT-', or append the ':00' to the end.
But then you can easily play with the other options if you want to eg. use 12h time or omit the seconds etc.
Note that I'm using Sweden as locale because it is one of the countries that uses ISO 8601 format. I think most of the ISO countries use this 'GMT-4' format for the timezone offset other then Canada which uses the time zone abbreviation eg. "EDT" for eastern-daylight-time.
You can get the same thing from the newer standard i18n function "Intl.DateTimeFormat()" but you have to tell it to include the time via the options or it will just give date.
Here are the functions I used for this end:
function localToGMTStingTime(localTime = null) {
var date = localTime ? new Date(localTime) : new Date();
return new Date(date.getTime() + (date.getTimezoneOffset() * 60000)).toISOString();
};
function GMTToLocalStingTime(GMTTime = null) {
var date = GMTTime ? new Date(GMTTime) : new Date();;
return new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toISOString();
};
function setDate(){
var now = new Date();
now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
var timeToSet = now.toISOString().slice(0,16);
/*
If you have an element called "eventDate" like the following:
<input type="datetime-local" name="eventdate" id="eventdate" />
and you would like to set the current and minimum time then use the following:
*/
var elem = document.getElementById("eventDate");
elem.value = timeToSet;
elem.min = timeToSet;
}
No moment.js needed: Here's a full round trip answer, from an input type of "datetime-local" which outputs an ISOLocal string to UTCseconds at GMT and back:
<input type="datetime-local" value="2020-02-16T19:30">
isoLocal="2020-02-16T19:30"
utcSeconds=new Date(isoLocal).getTime()/1000
//here you have 1581899400 for utcSeconds
let isoLocal=new Date(utcSeconds*1000-new Date().getTimezoneOffset()*60000).toISOString().substring(0,16)
2020-02-16T19:30
You can achieve this with a few simple extension methods. The following Date extension method returns just the timezone component in ISO format, then you can define another for the date/time part and combine them for a complete date-time-offset string.
Date.prototype.getISOTimezoneOffset = function () {
const offset = this.getTimezoneOffset();
return (offset < 0 ? "+" : "-") + Math.floor(Math.abs(offset / 60)).leftPad(2) + ":" + (Math.abs(offset % 60)).leftPad(2);
}
Date.prototype.toISOLocaleString = function () {
return this.getFullYear() + "-" + (this.getMonth() + 1).leftPad(2) + "-" +
this.getDate().leftPad(2) + "T" + this.getHours().leftPad(2) + ":" +
this.getMinutes().leftPad(2) + ":" + this.getSeconds().leftPad(2) + "." +
this.getMilliseconds().leftPad(3);
}
Number.prototype.leftPad = function (size) {
var s = String(this);
while (s.length < (size || 2)) {
s = "0" + s;
}
return s;
}
Example usage:
var date = new Date();
console.log(date.toISOLocaleString() + date.getISOTimezoneOffset());
// Prints "2020-08-05T16:15:46.525+10:00"
I know it's 2020 and most people are probably using Moment.js by now, but a simple copy & pastable solution is still sometimes handy to have.
(The reason I split the date/time and offset methods is because I'm using an old Datejs library which already provides a flexible toString
method with custom format specifiers, but just doesn't include the timezone offset. Hence, I added toISOLocaleString
for anyone without said library.)
Just my two sends here
I was facing this issue with datetimes so what I did is this:
const moment = require('moment-timezone')
const date = moment.tz('America/Bogota').format()
Then save date to db to be able to compare it from some query.
To install moment-timezone
npm i moment-timezone
Check this:
function dateToLocalISO(date) {
const off = date.getTimezoneOffset()
const absoff = Math.abs(off)
return (new Date(date.getTime() - off*60*1000).toISOString().substr(0,23) +
(off > 0 ? '-' : '+') +
(absoff / 60).toFixed(0).padStart(2,'0') + ':' +
(absoff % 60).toString().padStart(2,'0'))
}
// Test it:
d = new Date()
dateToLocalISO(d)
// ==> '2019-06-21T16:07:22.181-03:00'
// Is similar to:
moment = require('moment')
moment(d).format('YYYY-MM-DDTHH:mm:ss.SSSZ')
// ==> '2019-06-21T16:07:22.181-03:00'
getTimezoneOffset()
returns the opposite sign of the format required by the spec that you referenced.
This format is also known as ISO8601, or more precisely as RFC3339.
In this format, UTC is represented with a Z
while all other formats are represented by an offset from UTC. The meaning is the same as JavaScript's, but the order of subtraction is inverted, so the result carries the opposite sign.
Also, there is no method on the native Date
object called format
, so your function in #1 will fail unless you are using a library to achieve this. Refer to this documentation.
If you are seeking a library that can work with this format directly, I recommend trying moment.js. In fact, this is the default format, so you can simply do this:
var m = moment(); // get "now" as a moment
var s = m.format(); // the ISO format is the default so no parameters are needed
// sample output: 2013-07-01T17:55:13-07:00
This is a well-tested, cross-browser solution, and has many other useful features.
Source: Stackoverflow.com