toLocaleDateString and toLocaleString methods does not respect the machines timezone - javascript

My computer is with US region settings and date formats and -8h GMT timezone, but i am not exactly in US region. Why when getting the date through new Date i can see that the timezone offset is correct, but when i try and convert it to localedateString i get my really local date string?
var date = new Date();
///here date is (for example) Mon Jan 15 2001 12:00:00 GMT-0800 (Pacific Standard Time)
var localeString = date.toLocateDateString();
///or date.toLocaleString()
/// localeString here comes in my real locale date format 15.01.2001 г or 15.01.2001 г., 12:00:00 when using toLocaleString()

The output of toLocaleString is entirely implementation dependent and is inconsistent across browsers currently in use. It does not necessarily respect system settings (e.g. Chrome does not respect my system settings for the order of the components) and there is no requirement in ECMA-262 for it to do so.
For reliable results, format the output manually in an unambiguous format, e.g. 25 Feb 2017. A library can help, but if you only need one format then a simple function will suffice.

Related

Javascript: new Date() initialized with specific date string returns two different dates in different timezones

I am using new Date() to create a date object for a specific date. But it returns two different dates in different timezones. See below:
When my machine is in Indian Timezone (IST)
console.log(new Date('2020-08-28')); //returns Fri Aug 28 2020 05:30:00 GMT+0530 (India Standard Time)
When my machine is in US timezone (CST)
console.log(new Date('2020-08-28')); //returns Fri Aug 27 2020 19:00:00 GMT-0500 (Central Daylight Time)
How is this happening even when I am telling the JS to create a date for a given string? The string here is '2020-08-28'.
Why is this happening and how to ignore the timezone in this case?
From the ECMAScript specification:
When the UTC offset representation is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as a local time.
The forms themselves are described in the Date Time String Format.
It is important to note that treating date-only forms as UTC is in conflict with the ISO 8601 spec which treats such forms as local time. This is a known issue and was done deliberately in the name of "web reality".
When you instantiate a Date by passing a string, it's supposed to be a full ISO 8601 string which specifies the time zone. As you dont specify it, it takes Greenwich Mean Time (±00:00), then uses your local timezone when displaying it. Use this if you want to display the date as GMT:
console.log(new Date('2020-08-28').toUTCString());

Weird Javascript Timezones with Date()

Javascript hopeless here but I've got a problem I can't seem to understand, and don't know whether it's defined behavior in JS or not...
From what I can understand, new Date() returns the current time in the current timezone as reported by the browser. At the current time of writing this, I am in Milan, Italy (GMT +0200 CEST), so when performing the below:
var date = new Date();
console.log(date);
console.log(date.getTimezoneOffset());
I get, as expected:
Sun Oct 07 2018 15:42:12 GMT+0200 (Central European Summer Time)
-120
However, again from what I understand, throwing milliseconds into the Date Constructor creates a date based off of Epoch Time, 1st January 1970 00:00:00 GMT +0000 - So why if I perform:
var date = new Date(0); // Note The 0
console.log(date);
console.log(date.getTimezoneOffset())
Do I get:
Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time)
-60
Did the browser for some reason change the timezone it thinks I am in? This is causing quite a few problems for me retrieving a unix timestamp from a database, and displaying it in the user's current timezone!
Any help or advice on this would be much appreciated!
Many thanks! :)
The numeric timestamp value inside every Date instance, no matter how it is constructed, represents an offset from a fixed UTC "epoch" time. When you construct a date in your locale, the timezone offset is taken into account when the Date instance timstamp is set. The timezone offset is also taken into account when you access parts of the date via locale-relative APIs like .getTimezoneOffset().
Thus what matters is how you get date/time information out of the Date instance. If you use UTC APIs, you get UTC time information. If you use locale-relative APIs, you get locale-relative values.
let d = new Date();
console.log("locale-relative: " + d);
console.log("UTC: " + d.toUTCString());
Now, as to how you handle the system timestamp values you've got in your database, that depends on how your application works and what the dates mean in that context. If it's important that users see the dates in terms of what your server(s) will do with them, format the dates on the server with locale-relative APIs. That would make sense if your application does some work based on local time. For example some banking applications (in the US) do things at night, but "night" in terms of late evening hours in the continental US.
If, on the other hand, the dates you store should be shown to your users in terms of their locales, then send the client the timestamp and format your dates as strings at the client with locale-relative APIs. That would be appropriate for an application that allows users to set up alarms etc: generally it makes sense for the user to think in terms of their own local time.

javascript create date without daylight savings conversion

when i create date using date constructor new Date('2015','12'), it results in Fri Jan 01 2016 00:00:00 GMT-0500 (Eastern Standard Time). But don't it to assume that what date i am providing is already applied daylight conversion and create date object for december 2015, instead of jan 2016
When creating a date using the Date constructor, the time zone of the host system is almost always used (per ECMA-262). The only exception is when a number (interpreted as a time value, i.e. milliseconds since the ECMAScript epoch) is provided, or an ISO 8601 format string with a time zone. Even then, the internal time value of the Date (i.e. milliseconds since the epoch) is calculated in UTC and the host system time zone offset used for the non–UTC methods like getHours, getMinutes, etc.
Also, the timezone offset of the current systems settings are used for historical dates. So if the host is set for daylight saving, it will be applied to dates at times before daylight saving was implemented. Also, historical changes to daylight saving changeover dates and times (and even value) are not applied. The currents settings are assumed to always apply for past and future dates.
So all of the following will apply the timezone offset of the host system when creating a date for 3 February, 2016:
new Date('2/3/2016'); // US format is assumed by most browsers.
// May also create an invalid Date
new Date(2016, 1, 3); // months are zero indexed so 1 is February
new Date('2016-02-03T00:00:00'); // note missing time zone
However, the following will be treated as UTC (or invalid):
new Date('2016-02-03'); // contrary to ISO 8601, missing time zone for this
// format only is assumed to be UTC
new Date('2016-02-03T00:00:00Z'); // Note has a time zone of GMT
If you want to reliably create a Date for a specific instant in time from a string, you must provide a string with the time zone offset. Then parse it yourself since parsing of date strings is largely implementation dependent and varies across implementations. The best format to use is ISO 8601 extended so something like:
'2016-02-03T00:00:00-0800'
which represents the same instant in time no matter what the settings of the host system are. You just need to reliably parse it.
There are many good libraries for parsing and formatting, or you can write your own small functions for particular parse and output formats.

JavaScript date-only format guaranteed to be interpreted as local time in modern browsers

I am looking for a date format (only year, month and day, no time component), that will be guaranteed to be interpreted as local time, in all reasonably modern browsers, when passed to the Date() constructor in JavaScript.
The (3-letter English month abbreviation) (2-digit date) (4-digit year) format seems to work. When I do new Date('Apr 01 2015') on my English system, in Chrome, with my machine being in the Eastern timezone, I get back Wed Apr 01 2015 00:00:00 GMT-0400 (Eastern Daylight Time) which is exactly what I want.
However, I am not sure if this (3-letter English month abbreviation) (2-digit date) (4-digit year) format is guaranteed to be interpreted in the same way regardless of browser and browser/OS locale/language.
Will this format work the same way across different (reasonably modern) browsers and locales? If not, then is there some other format that will work?
Please note that ISO-8601 doesn't answer this question. ISO-8601 date-only strings are interpreted as being in UTC, and not in local time, so new Date('2015-04-01') is interpreted as Tue Mar 31 2015 20:00:00 GMT-0400 (Eastern Daylight Time), i.e. April 1 turns into March 31, which is not what I'm looking for.
I am looking for a date format (only year, month and day, no time component), that will be guaranteed to be interpreted as local time, in all reasonably modern browsers, when passed to the Date() constructor in JavaScript.
There isn't one. There are a number of formats that, in practice, are reliably parsed by all browsers in use however none of them are required by ECMA-262 to be supported by ECMAScript implementations.
There is one format, a version of ISO 8601, that is specified in ES5 and ECMAScript 2015 however dates without a time zone are to be treated as UTC in ES5 and "local" in ECMAScript 2015.
But that was seen by implementers as "breaking the web", so while some browsers implemented that for a while, they have now reverted to ES5 behaviour and treat a missing timezone as UTC.
A small change in format such as changing the separator from "-" to "/" causes a reversion to implementation dependent behaviour and may cause the date to be treated as UTC or local (though most seem to treat 2015/12/17 as local).
So if you want a guarantee, there isn't one. However, if you are prepared to write a 2 line function, you can parse an ISO 8601 like string reliably based on whatever time zone you like. If you want it to be treated as local (i.e. set to 00:00:00 and offset based on system settings), then:
function parseISOLike(s) {
var b = s.split(/\D/);
return new Date(b[0], b[1]-1, b[2])
}
document.write(parseISOLike('2015-12-17'));
will do the job (without checking for valid values) and allow the separator to be any non–digit, so 2015/12/17, 2015-12-17 and 2015.12.17 will all be correctly parsed.
Edit
Parts of the above have been edited thanks to input from Matt Johnson.

new Date() works differently in Chrome and Firefox

I want to convert date string to Date by javascript, use this code:
var date = new Date('2013-02-27T17:00:00');
alert(date);
'2013-02-27T17:00:00' is UTC time in JSON object from server.
But the result of above code is different between Firefox and Chrome:
Firefox returns:
Wed Feb 27 2013 17:00:00 GMT+0700 (SE Asia Standard Time)
Chrome returns:
Thu Feb 28 2013 00:00:00 GMT+0700 (SE Asia Standard Time)
It's different 1 day, the correct result I would expect is the result from Chrome.
Demo code: http://jsfiddle.net/xHtqa/2/
How can I fix this problem to get the same result from both?
The correct format for UTC would be 2013-02-27T17:00:00Z (Z is for Zulu Time). Append Z if not present to get correct UTC datetime string.
Yeah, unfortunately the date-parsing algorithms are implementation-dependent. From the specification of Date.parse (which is used by new Date):
The String may be interpreted as a local time, a UTC time, or a time in some other time zone, depending on the contents of the String. The function first attempts to parse the format of the String according to the rules called out in Date Time String Format (15.9.1.15). If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.
To make the Date constructor not (maybe) use the local timezone, use a datetime string with timezone information, e.g. "2013-02-27T17:00:00Z". However, it is hard to find a format that is reliable parsed by every browser - the ISO format is not recognised by IE<8 (see JavaScript: Which browsers support parsing of ISO-8601 Date String with Date.parse). Better, use a unix timestamp, i.e. milliseconds since unix epoch, or use a regular expression to break the string down in its parts and then feed those into Date.UTC.
I found one thing here. It seems the native Firefox Inspector Console might have a bug:
If I run "new Date()" in the native Inspector, it shows a date with wrong timezone, GMT locale, but running the same command in the Firebug Extension Console, the date shown uses my correct timezone (GMT-3:00).
Noticed that FireFox wasn't returning the same result as Chrome. Looks like the format you use in kendo.toString for date makes a difference.
The last console result is what I needed:
Try using moment.js. It goes very well and in similar fashion with all the browsers. comes with many formatting options. use moment('date').format("") instead of New Date('date')

Categories