UTC date conversion to Local date does NOT work, Safari - javascript

I have a UTC string "2018-04-25T13:36:00" which I pass into this function:
function convertUTCDateToLocalDate(dateString) {
var newDate = new Date(dateString);
newDate.setMinutes(dateString.getMinutes() - dateString.getTimezoneOffset());
return newDate;
}
var localDate = convertUTCDateToLocalDate(new Date("2018-04-25T13:36:00"));
console.log(localDate);
Chrome, Firefox and Edge returns correctly as (PASS):
Wed Apr 25 2018 06:36:00 GMT-0700 (PDT)
However, Safari returns it as (FAIL):
Tue Apr 24 2018 23:36:00 GMT-0700 (PDT)
Why is Safari being a stickler?

The string "2018-04-25T13:36:00" should be parsed as local, however Safari gets it wrong and parses it as UTC. Since you want to parse it as UTC, one simple (but not recommended) method is to simply add "Z" to the string so all browsers parse it as UTC:
var s = '2018-04-25T13:36:00';
console.log(new Date(s+'Z').toString());
However, general advice is never use the built-in parser as it is notoriously problematic (see Why does Date.parse give incorrect results?), write your own parser for your particular format or use a library. To parse your format as UTC, consider:
var s = '2018-04-25T13:36:00';
// Parse YYYY-MM-DDTHH:mm:ss as UTC
function parseUTC(s) {
var b = s.split(/\D/);
return new Date(Date.UTC(b[0],--b[1],b[2],b[3],b[4],b[5]))
}
var d = parseUTC(s);
console.log(d.toISOString());
console.log(d.toString());

Related

Creating a Date is adding automatically one hour to my input date

let's say I have this date as input :
var _dateA = 2018-11-15T11:13:26.687Z
If I'm doing, whatever,
var _dateB = new Date(_date)
or
var _dateB = moment(_date)
I get this as result ==>
_dateB = Thu Nov 15 2018 12:13:26 GMT+0100 (heure normale d’Europe centrale)
I understood that there's timezone trouble, but how can I get a Date object or Moment object, without having this one hour more?
Wanted result => Thu Nov 15 2018 11:13:26 GMT+0100
Current result => Thu Nov 15 2018 12:13:26 GMT+0100
You need to use Date.toUTCString() that converts date to string, using the UTC time zone
var _dateA = '2018-11-15T11:13:26.687Z';
var _dateB = new Date(_dateA);
console.log(_dateB.toUTCString());
When you "output" a Date object via console.log(), alert(), etc the toString() method is used by default, converting the date object to a local timezone string for display (which is why you are seeing your date in your local time).
Parsing date strings with the Date constructor is not recommended (although, I suspect that most browsers probably handle ISO 8601 dates, like the one in your question, fairly well) - see the dateString parameter note here. So, if you need to construct a date object as well as output a date string, then you could parse the ISO 8601 string with split() using a regex character set for multiple delimiters, then construct a UTC date object with new Date(Date.UTC(...)). You could also do this with moment.js but the below should illustrate what is happening in a bit more detail.
For example:
const text = '2018-11-15T11:13:26.687Z'
const [y, m, d, hh, mm, ss, ms] = text.split(/[-T:.Z]/);
const date = new Date(Date.UTC(y, m - 1, d, hh, mm, ss, ms));
console.log(date.toLocaleString()); // date string in local timezone
console.log(date.toUTCString()); // UTC date string
console.log(JSON.stringify(date)); // ISO 8601 date string in most browsers

How to create a javascript date from 12 hour format

How can I create a Date object from a date with this format:
03/23/2016 02:00:00 PM
The Date object can parse strings: new Date('03/23/2016 02:00:00 PM')
For example:
var date = new Date('03/23/2016 02:00:00 PM') // => "Wed Mar 23 2016 14:00:00 GMT-0700 (PDT)"
date.getFullYear() // => 2016
However, I would recommend using a library that someone else has already spent time considering the edge cases, like time zones, etc. (a good one I've used is moment.js).
Keep in mind (from the moment.js docs):
Warning: Browser support for parsing strings is inconsistent. Because there is no specification on which formats should be supported, what works in some browsers will not work in other browsers.
For consistent results parsing anything other than ISO 8601 strings, you should use String + Format.
var date = new Date("3/23/2016 02:00:00 PM");
console.log(date);
You can then access all the methods of the Date object.
Looking at MDN
var date = new Date('03/23/2016 02:00:00 PM')
You can use something like date.js:
First use script, then write date:
<script type="text/javascript" src="http://www.datejs.com/build/date.js"></script>
....
document.write(new Date().toString("dd:MM:yyyy hh:mm:ss tt"));

Javascript new Date

There is a funny thing in JavaScript, not a big deal but I would like to know, why is this happening.
If you do this:
new Date('2014-6-12')
you'll get:
Thu Jun 12 2014 00:00:00 GMT-0600 (Central America Standard Time)
which is totally fine but if you do the same using the day with the format 'dd' instead of 'd' like this:
new Date('2014-06-12')
you'll get a different result:
Wed Jun 11 2014 18:00:00 GMT-0600 (Central America Standard Time)
Because '2014-06-12' appears to be an ISO 8601 date format without a time zone, so it's treated as UTC (per ES5) by most browsers but not all. '2014-6-12' is seen as some other format so is treated as local.
ES6 will change that so that ISO 8601 dates without a timezone should be treated as local (per ISO 8601). Confused?
ECMAScript 2015 was originally interpreted as treating ISO 8601 date only forms as local, but that was changed to treat them as UTC. All subsequent versions of ECMAScript also treat them as UTC (which is inconsistent with ISO 8601).
So do not parse strings with the built-in parser (i.e. new Date(string) or Date.parse(string)), its behaviour is inconsistent across browsers and not necessarily standards compliant. Use a library, or write your own simple parser:
// Expect year-month-day, treat as local date
function parseYMD(s) {
var b = s.split(/\D+/);
return new Date(b[0], --b[1], b[2]);
}
The above is simple but does not test if the date is valid, to do that takes an extra line:
// Expect year-month-day, treat as local date
function parseYMD(s) {
var b = s.split(/\D+/);
var d = new Date(b[0], --b[1], b[2]);
return d && d.getFullYear() == b[0] && d.getDate() == b[2]? d : NaN;
}
Also see Why does Date.parse give incorrect results?

Date is invalid in IE and Firefox but is chrome it works fine

var stdate=document.forms["myForm"]["from"].value;
var endate=document.forms["myForm"]["to"].value;
var fromDate = new Date(stdate);
var toDate = new Date(endate);
alert(fromDate);
Input:
from: 19-Mar-2014 03:13:50 PM
Output: (in IE & Firefox)
invalid Date
in Chrome broswer:
Wed Mar 19 2014 15:13:50 GMT-0400 (Eastern Daylight Time)
What date format should I use so that all browsers support? Or how should I handle it?
In most cases, new Date(datestring) is all you need. But you need to chose the format carefully.
Here's a nice compatibility table: http://dygraphs.com/date-formats.html
The short version is this:
Dates only? use YYYY/mm/DD; never use hyphens in this format
Need time, but local time is OK? use YYYY/mm/DD HH:MM:SS; again, no hyphens
OK to ignore IE<9? Consider using ISO8601 with whole seconds (YYYY-mm-DDTHH:MM:SSZ, or with time-zone)
Need a UTC time in IE8? You'll have to do something clever. Xotic's answer looks good here.
As documented on MSDN (IE) - the Date constructor supports either a timestamp or a Datestring in a Format supported by Date.parse. According to the docs this is either RFC2822 or ISO 8601. some examples: 2011-10-10 or Mon, 25 Dec 1995 13:30:00 GMT should be valid arguments.
I would use an ISO8601
formatted string in UTC as my input, but then manually
split
this string into parts and feed them into my
Date
constructor thus avoiding date parsing issues.
Example
var iso8601 = '2014-03-19T03:13:50.000Z',
parts = iso8601.slice(0, -1).split(/[\-T:]/),
dateObject;
parts[1] -= 1;
dateObject = new Date(Date.UTC.apply(undefined, parts));
console.log(dateObject.toUTCString());
Output
Wed, 19 Mar 2014 03:13:50 GMT
On jsFiddle

Chrome does not return correct hour in javascript

First try is in IE 9 console:
new Date('2013-10-24T07:32:53')
Thu Oct 24 07:32:53 UTC+0200 2013
returns as expected
Next try is in FireFox 24 console:
new Date('2013-10-24T07:32:53')
Date {Thu Oct 24 2013 07:32:53 GMT+0200 (Central Europe Standard Time)}
Then I go into Chrome 30 console:
new Date('2013-10-24T07:32:53')
Thu Oct 24 2013 09:32:53 GMT+0200 (Central Europe Daylight Time)
But the time is 09 here, it should be 07.
Is this a bug in chrome or am I doing something wrong here?
I can't use any other format than this '2013-10-24T07:32:53' that I get by JSON from C#.
I need to get the hour of this timestamp, with the getHours I get the incorect value in Chrome.
Solution:
var inputHour = input.split('T')[1];
inputHour = inputHour.substring(0, 2);
Its no bug. The implementation of date parse function differs across browsers & so does the format of the dateString accepted by it.
However this format seems to work same across ... link:
new Date("October 13, 1975 11:13:00")
If possible, try and use
new Date(year, month, day, hours, minutes, seconds, milliseconds)
for guaranteed results.
Regarding your format try parsing it yourself. Something like :
var str = '2013-10-24T07:32:53'.split("T");
var date = str[0].split("-");
var time = str[1].split(":");
var myDate = new Date(date[0], date[1]-1, date[2], time[0], time[1], time[2], 0);
Note (Thanks to RobG for this) : The Date constructor used above expects month as 0 - 11 & since October is 10 as per date String, the month has to be modified before passing it to the constructor.
Reference.
See this thread:
Why does Date.parse give incorrect results?
It looks like the behavior of the parsing signature of the Date constructor is completely implementation dependent.
Given:
var s = '2013-10-24T07:32:53';
in ES5 compliant browsers you could do:
var d = new Date(s + 'Z');
but for compatibility across all browsers in use, better to use (assuming date is UTC):
function dateFromString(s) {
s = s.split(/\D/);
return new Date(Date.UTC(s[0],--s[1],s[2],s[3],s[4],s[5]));
}

Categories