JavaScript time is an hour behind after ISO conversion - javascript

I create a new Date in JavaScript, with the correct time, but after I use toISOString() to convert it, it's an hour behind. Why would that be?
https://jsfiddle.net/73nfyxeL/
var createdDateTime = new Date('2015-04-01 11:53:00');
var isoCreatedDateTime = "";
alert(createdDateTime);
isoCreatedDateTime = createdDateTime.toISOString().match(/(\d{4}\-\d{2}\-\d{2})T(\d{2}:\d{2}:\d{2})/);
alert(isoCreatedDateTime[1] + ' ' + isoCreatedDateTime[2]);
createdDateTime.setMinutes(createdDateTime.getMinutes() + 1);
As far as I'm aware this should be immune to changes to the local time (eg. daylight savings), as I'm giving it a pre-set time, and not a timezone. What's going on?

The toISOString method doesn't only format the date, first it is converted to UTC.
The difference between your local time zone and UTC is one hour.

Related

Is there a way to get date in another timezone in milliseconds like Date.now() in JavaScript?

new Date(Date.now()).toLocaleString(
"en-US",
{
timeZone: "Asia/Calcutta"
}
)
Works for my timezone. But when I try to get for another timezone, it doesn't help. I tried using Date.parse() and moment, no luck. Would be helpful if there is some other way. I am trying to work on time setting feature for different timezones. Hence I need a function to return current time in that timezone.
Time returned by Date.now() will be the same for any time zone, because it returns how many ms have passed since 01-01-1970
What you need is to calculate GMT offset for your desired time zone
var offset = new Date().getTimezoneOffset();
console.log(offset);
The time-zone offset is the difference, in minutes, between UTC and local time. Note that this means that the offset is positive if the local timezone is behind UTC and negative if it is ahead. For example, if your time zone is UTC+10 (Australian Eastern Standard Time), -600 will be returned. Daylight savings time prevents this value from being a constant even for a given locale
ECMAScript Dates are simply a time value that is an offset from 1970-01-01T00:00:00Z (the ECMAScript epoch, which is the same as the Java and UNIX epoch).
If a system's clock is accurately set to the current time, then Date.now() and new Date().getTime() for a particular instant will return exactly the same value regardless of the timezone offset of the host system. In practice there will however be minor variations due to clock inaccuracies and lack of syncrhonisation.
The host timezone offset comes from the host system and is only used for calculations involving local values, it's not an attribute of the Date itself.
If you want to get the time value for a particular date and time for a particular timezone offset, you can build a string that should be parsable by the built–in parser and use that. E.g. the Line Islands have an offset of +14:00 and don't observe daylight saving, so to get the time value for Christmas morning use a supported string format1 and the built–in parser:
// Christmas morning in Line Islands
let s = '2019-12-25T00:00:00+14:00';
// Get time value
let ms = Date.parse(s);
let d = new Date(ms);
let optsLocal = {weekday:'short', day:'numeric', month:'short', year:'numeric', hour:'numeric', hour12:false, minute:'numeric'};
let optsHK = Object.assign({},optsLocal,{timeZone:'Asia/Hong_Kong'});
let optsNY = Object.assign({},optsLocal,{timeZone:'America/New_York'});
let optsHW = Object.assign({},optsLocal,{timeZone:'Pacific/Honolulu'});
console.log('Start string: ' + s +
'\nTime value : ' + ms +
'\nLocal date : ' + d.toLocaleString('en-GB', optsLocal) +
'\nHong Kong : ' + d.toLocaleString('en-GB', optsHK) +
'\nNew York USA: ' + d.toLocaleString('en-GB', optsNY) +
'\nHawaii USA : ' + d.toLocaleString('en-GB', optsHW)
);
Where "supported string format" is one of the two formats specified in ECMA-262, also see Why does Date.parse give incorrect results?

Javascript - converting local time to google friendly UTC time

I want to get the date and time from 2 text boxes and format them and send them to the Google directions javascript API to get transit directions.
How do I add the date and time values together and then convert them to standard UTC time?
This is what i have:
var dateOfTravel = document.getElementById('fdate').value;
var timeOfTravel= document.getElementById('ftime').value;
//join the date and time strings
var d1 = new Date(dateOfTravel + ' ' + timeOfTravel);
alert("date and time is " + d1);
alert(d1.getTime());
var UTCDateAndTime = moment(d1).unix();
alert(UTCDateAndTime);
thanks,
Tom
Several options:
JavaScript dates have toISOString, which provides a standard ISO-8601 date/time string always in UTC, e.g. "2015-10-25T11:02:23.019Z". (Yes, the timezone specifier is always Z, that's required by the spec. So it doesn't vary by locale or timezone.)
You can use the various getUTCXyz methods to build your own string.
getTime returns the number of milliseconds since The Epoch (Jan 1 1970 at midnight UTC), which is not timezone-dependent.
getTimezoneOffset tells you how far offset you are from UTC, which you could use to adjust things (though I can't see a good reason for that in this case).
This appears to be working:
var d1 = new Date(dateOfTravel + ' ' + timeOfTravel);
//if the year is less than 1970 then add 100 on. Using 2 digit years and there's a bug with javascript date implimentation
if (d1.getFullYear() < 1970) {
d1.setFullYear(d1.getFullYear() + 100);
}

Convert utc date time to local date time using JavaScript or jQuery

I am storing a UTC date time in a SharePoint list and fetching it's value in c#, converting into milliseconds from 1 Jan 1970 and passing those milliseconds to JavaScript to get date object.
But when I create a date object, its value remains same as UTC date, I want that value to be in users local time zone and reflecting their daylight saving status.
You can use the TimezoneOffset in javascript, check the following code,
var d = new Date()
var n = d.getTimezoneOffset();
In this way you can calculate the time as you want.
Let me know if you need more details :)
When you create a new date in Javascript i assume you create it on the client side / client machine:
var d = new Date(millis);
The notion that the value remains the same in UTC no matter where you construct the Date object is correct, it's only a matter of how you display the date: in UTC or in the user's local timezone:
You can run this code to see the difference:
var local = date.toDateString() + ' ' + date.toTimeString();
var utc = date.toUTCString();
alert(local);
alert(utc);
Note that the value of millis is the milliseconds passed since 1970-01-01 00:00:00 UTC no matter where you are in this world. Calling new Date().getTime() on 2 opposite sides of the globe should return the same number of milliseconds.

Using momentjs to convert date to epoch then back to date

I'm trying to convert a date string to epoch, then epoch back to the date string to verify that I'm providing the correct date string.
var epoch = moment("10/15/2014 9:00").unix(); // do I need to do .local()?
var momentDate = moment(epoch); // I've also tried moment.utc(epoch)
var momentDateStr = momentDate.calendar();
alert("Values are: epoch = " + epoch + ", momentDateStr = " + momentDateStr);
Renders
Values are: epoch = 1413378000, momentDateStr = 01/17/1970
Note: I'm using the following version of the moment js script, //cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment-with-locales.js
There are a few things wrong here:
First, terminology. "Epoch" refers to the starting point of something. The "Unix Epoch" is Midnight, January 1st 1970 UTC. You can't convert an arbitrary "date string to epoch". You probably meant "Unix Time", which is often erroneously called "Epoch Time".
.unix() returns Unix Time in whole seconds, but the default moment constructor accepts a timestamp in milliseconds. You should instead use .valueOf() to return milliseconds. Note that calling .unix()*1000 would also work, but it would result in a loss of precision.
You're parsing a string without providing a format specifier. That isn't a good idea, as values like 1/2/2014 could be interpreted as either February 1st or as January 2nd, depending on the locale of where the code is running. (This is also why you get the deprecation warning in the console.) Instead, provide a format string that matches the expected input, such as:
moment("10/15/2014 9:00", "M/D/YYYY H:mm")
.calendar() has a very specific use. If you are near to the date, it will return a value like "Today 9:00 AM". If that's not what you expected, you should use the .format() function instead. Again, you may want to pass a format specifier.
To answer your questions in comments, No - you don't need to call .local() or .utc().
Putting it all together:
var ts = moment("10/15/2014 9:00", "M/D/YYYY H:mm").valueOf();
var m = moment(ts);
var s = m.format("M/D/YYYY H:mm");
alert("Values are: ts = " + ts + ", s = " + s);
On my machine, in the US Pacific time zone, it results in:
Values are: ts = 1413388800000, s = 10/15/2014 9:00
Since the input value is interpreted in terms of local time, you will get a different value for ts if you are in a different time zone.
Also note that if you really do want to work with whole seconds (possibly losing precision), moment has methods for that as well. You would use .unix() to return the timestamp in whole seconds, and moment.unix(ts) to parse it back to a moment.
var ts = moment("10/15/2014 9:00", "M/D/YYYY H:mm").unix();
var m = moment.unix(ts);
http://momentjs.com/docs/#/displaying/unix-timestamp/
You get the number of unix seconds, not milliseconds!
You you need to multiply it with 1000 or using valueOf() and don't forget to use a formatter, since you are using a non ISO 8601 format. And if you forget to pass the formatter, the date will be parsed in the UTC timezone or as an invalid date.
moment("10/15/2014 9:00", "MM/DD/YYYY HH:mm").valueOf()

How to assume local time zone when parsing ISO 8601 date string?

I have a ISO date string as below
var startTimeISOString = "2013-03-10T02:00:00Z";
when I convert it to date object in javascript using below code, it returns
var startTimeDate = new Date(startTimeISOString);
output is
Date {Sun Mar 10 2013 07:30:00 GMT+0530 (India Standard Time)}
It sure converts the ISOString to date but it converts to local time since new Date() is client dependent. How to just convert iso date time string to date and time but not to local date-time..?
Thanks
According to MDN:
Differences in assumed time zone
Given a date string of "March 7, 2014", parse() assumes a local time
zone, but given an ISO format such as "2014-03-07" it will assume a
time zone of UTC. Therefore Date objects produced using those strings
will represent different moments in time unless the system is set with
a local time zone of UTC. This means that two date strings that appear
equivalent may result in two different values depending on the format
of the string that is being converted (this behavior is changed in
ECMAScript ed 6 so that both will be treated as local).
I have done like this and am now getting the exact time which is inside the ISO date string instead of the local time
var startTimeISOString = "2013-03-10T02:00:00Z";
var startTime = new Date(startTimeISOString );
startTime = new Date( startTime.getTime() + ( startTime.getTimezoneOffset() * 60000 ) );
This will give the same date time inside iso date string , the output here is
o/p
Date {Sun Mar 10 2013 02:00:00 GMT+0530 (India Standard Time)}
To sum up the conversation from tracevipin's post:
All Date objects are based on a time value that is milliseconds since 1970-01-01T00:00:00Z so they are UTC at their core. This is different to UNIX, which uses a value that is represents seconds since the same epoch.
The Date.prototype.toString method returns an implementation dependent string that represents the time based on the system settings and timezone offset of the client (aka local time).
If a UTC ISO8601 time string is required, the Date.prototype.toISOString method can be used. It's quite easy to write a "shim" for this methods if required.
Lastly, do not trust Date.parse to parse a string. Support for an ISO8601 format UTC string is specified in ES5, however it's not consistently implemented across browsers in use. It is much better to parse the string manually (it's not hard, there are examples on SO of how to do it) if wide browser support is required (e.g. typical web application).
Simple ISO8601 UTC time stamp parser:
function dateObjectFromUTC(s) {
s = s.split(/\D/);
return new Date(Date.UTC(+s[0], --s[1], +s[2], +s[3], +s[4], +s[5], 0));
}
and here's a shim for toISOString:
if (typeof Date.prototype.toISOString != 'function') {
Date.prototype.toISOString = (function() {
function z(n){return (n<10? '0' : '') + n;}
function p(n){
n = n < 10? z(n) : n;
return n < 100? z(n) : n;
}
return function() {
return this.getUTCFullYear() + '-' +
z(this.getUTCMonth() + 1) + '-' +
z(this.getUTCDate()) + 'T' +
z(this.getUTCHours()) + ':' +
z(this.getUTCMinutes()) + ':' +
z(this.getUTCSeconds()) + '.' +
p(this.getUTCMilliseconds()) + 'Z';
}
}());
}
This happens because date is printed using toString method which by default returns the date and time in local timezone. The method toUTCString will give you the string you need.
Date actually keeps the date as unix time in milliseconds and provides methods to manipulate it.
In vanilla javascript there isn't a way to create a date that assumes the local time of the ISO formatted string you give it. Here's what happens when you pass an ISO 8601 formatted string to javascript. I'm going to use a non UTC time as it illustrates the problem better than using an ISO formatted string:
var startTime = new Date("2013-03-10T02:00:00+06:00"). Note this could also be 2013-03-10T02:00:00Z or any other ISO-formatted string.
read the time, apply the offset and calculate milliseconds since 1970-01-01T00:00:00Z
You now have only milliseconds - you have lost all timezone info. In this case 1362859200000
All functions, apart from the ones that give you a UTC representation of that number, will use the timezone of the computer running the code to interpret that number as a time.
To do what the original poster wants, you need to.
parse the ISO string, interpret the offset ('Z' or '+06:00') as the timezone offset
store the timezone offset
calculate and store the ms since epoch, using the offset timezone offset
hold that offset
whenever attempting to make a calculation or print the date, apply the timezone offset.
This isn't trivial, and requires a complete interpretation of the 8601 spec. Way too much code to put here.
This is exactly what moment.js is designed to do. I strongly recommend using it. Using moment.js:
moment("2013-03-10T02:00:00Z").format()
"2013-03-10T02:00:00Z"
this will result in printing the ISO time of the original string, preserving the offset.
you can try moment js library https://momentjs.com
For my case, I had 2022-10-17T01:00:00 on my database. SO I need to format it to the 01:00:00 AM.
So here was my solution.
var date = "2022-10-17T01:00:00"
var timeFormat = moment(date ).format('HH:mm A');
output: 01:00:00 AM
it will return ISOdate
var getDate = () => {
var dt = new Date();
var off = dt.getTimezoneOffset() * 60000
var newdt = new Date(dt - off).toISOString()
return newdt.slice(0, 19)
}
Output

Categories