Javascript Date.ToLocaleTimeString() doesn't match computer's time format - javascript

My computer is defined to use 24h format:
However, when I use var date = new Date("10/25/2020 19:32")
and then date.toLocaleTimeString()
I get a 12h format:

When no options are provided, the output of toLocaleString is entirely implementation dependent so may or may not use host settings, however they are almost certain to treat it as equivalent to a language of "default" with no options, i.e.
new Date().toLocaleString('default') === new Date().toLocaleString()
which returns true in every browser I tested. The important part is:
[toLocaleString is] intended to represent the Date in the current time zone in a convenient, human-readable form that corresponds to the conventions of the host environment's current locale.
Note that it should use the conventions of the locale (i.e. place or region), not the host system.
When a language and/or options are provided, the output is governed by ECMA-402 and is primarily based on the language code provided as the first argument (misnamed "locale"). Options also affect the output, however the host settings are not used other than to obtain the language code to use in the case of "default" for the first argument.
The underlying principle of the toLocale methods is that appropriate formatting can be determined from a language and other fairly vague options. Implementation developers then work out what format to use for each language and option combination. Clearly the host system settings can't be used when language or options are provided as that defeats the entire purpose of the function.

Your assumption that the browser will use the settings in the operating system is probably wrong.
You leave it to the browser to choose a locale for you.
My guess is that it is based on window.navigator.languages. This could be "en-US" in your case, hence the 12h format.

Related

toLocaleTimeString() behaviour without arguments in Chrome and Safari

I read in the MDN documentation that:
toLocaleTimeString() without arguments depends on the
implementation,the default locale, and the default time zone
What does this mean exactly?
And I tried the following code in both Chrome(Version 87.0.4280.88) and Safari browser(Version 14.0).
new Date().toLocaleTimeString()
in Chrome it gives output as
16:57:37
whereas in Safari it gives output as
4:57:37 PM
With regards to the above example can someone explain how the implementation is changing from one browser to another, and why is it so?
Edit:
All this was done using MAC, I tried changing preferred language under Setting -> "Language and Region" to English(US) it was English(India) before, as soon as I did that change and restarted chrome the result became.
4:57:37 PM
But for Safari without doing this change it was able to show in 12 hour format, what was the reason for that?
The specification for toLocaleTimeString states:
This function returns a String value. The contents of the String are implementation-defined, but are intended to represent the “time” portion of the Date in the current time zone in a convenient, human-readable form that corresponds to the conventions of the host environment's current locale.
with the definition of implementation-defined being:
An implementation-defined facility is one that defers its definition
to an external source without further qualification. This
specification does not make any recommendations for particular
behaviours, and conforming implementations are free to choose any
behaviour within the constraints put forth by this specification.
Therefore browsers are free to implement this feature as they see fit.

Node 8 vs 11 Timezone is different

Running a simple new Date().toString(). On Node 11, You get something like
'Fri May 10 2019 10:44:44 GMT-0700 (Pacific Daylight Time)'
While on Node 8 you get
'Fri May 10 2019 10:44:44 GMT-0700 (PDT)'
Note the different in timezone abbreviation. Why is that? And how can you force toString() to always return the zone in the abbreviation?
Stolen answer from #ssube who was too lazy to log in and post.
the whole Intl object and default formats were introduced between those two versions, which may have become the new default for Date as well.
After some digging on my own, and reading some of the Intl spec:
The ECMAScript 2015 Internationalization API Specification identifies time zones using the Zone and Link names of the IANA Time Zone Database. Their canonical form is the corresponding Zone name in the casing used in the IANA Time Zone Database.
As to how to revert back to an abbreviated timezone, I am seeing that there are several github repos that suggest using regex, others using an abbreviation Map, or even Ben Nadel who uses some regex to process the short timezone or long timezone, as seen in his blog here
Looks like JavaScript leaves this up to the implementer. Based on the below GitHub Issue for ECMA262, there are known differences between the ways UNIX & Windows handle the timezone value.
Across multiple JS implementations, it seems that Date.prototype.toString writes the timezone (in parens) in a long, locale-dependent form on Windows, but in a short form (2-4 letters) from the tz database on Unix-based OSes. More details in the V8 bug tracker.
The spec is really light on details for Date.prototype.toString:
Return an implementation-dependent String value that represents tv as a date and time in the current time zone using a convenient, human-readable form.
Does anyone have a good memory of why this is the definition? Looks like it goes all the way back to ES1.
Fortunately, it seems that, at this point, implementations have converged on something that's almost always the same, with the exception of the timezone string.
For the timezone string, would it be a good idea to pick one of the two alternatives and standardize it across all platforms? Does anyone have evidence one way or the other whether either of the two is likely to be more web-compatible, or whether we need to preserve the variation?
Additionally, it looks like there is still active discussion in the V8 Issues for Date.prototype.toString() normalization.
Going through the NodeJS there doesn't seem to be an explicit mention of this in their change logs for v10+.
Update
After digging through V8 commits, it looks like there is a new Timezone Names Cache implemented for performance in V8 when using Date.prototype.toString(). Based on the below excerpt from the message for this commit, it seems like this change is why there is a difference between Node v8 & Node v11
To speed up Date.prototype.toString(), this patch adds a cache in the
DateCache for the string short name representing the time zone.
Because time zones in a particular location just have two short names
(for DST and standard time), and the DateCache already understands
whether a time is in DST or not, it is possible to keep the result of
OS::LocalTimezone around and select between the two based on whether
the time is DST or not.
In local microbenchmarks (calling Date.prototype.toString() in a
loop), I observed a 6-10% speedup with this patch. In the browser, the
speedup may be even greater as the system call needs to do some extra
work to break out of the sandbox. I don't think the microbenchmark is
extremely unrealistic; in any real program which calls
Date.prototype.toString() multiple times, the cache should hit almost
all of the time, as time zone changes are rare.
The proximate motivation for this patch was to enable ICU as a backend
for timezone information, which is drafted at
https://codereview.chromium.org/2724373002/ The ICU implementation of
OS::LocalTimezone is even slower than the system call one, but this
patch makes their performance indistinguishable on the microbenchmark.
In the tz database, many timezones actually do have a number of
different historical names. For example, America/Anchorage went
through a number of changes, from AST to AHST to YST to AKST. However,
both ICU and the Linux OS interfaces just report the modern timezone
name in tests for the appropriate timezone name, even for historical
times. I can see why this would be:
- For ICU, CLDR only has two short names in the data file: the one for dst and non-dst
- For Linux, the timezone names do seem to make it into the /etc/localtime file. However, glibc assumes there are only two
relevant names and selects between them, as you can see in its
implementation of localtime_r:
http://bazaar.launchpad.net/~vcs-imports/glibc/master/view/head:/time/tzset.c#L573
So, this cache should be valid until we switch to a more accurate
source of short timezone names.

Date input and toLocaleDateString using different locales

I reside in Canada, where we format our dates dd/mm/yyyy. I'm seeing something unusual when I'm calling toLocaleDateString()
HTML:
<input type="date" value="2016-01-13">
<p id="container">
</p>
JS:
var d = new Date("2016-01-13");
document.getElementById('container').innerText = d.toLocaleDateString();
The value of the date input is what I would expect - 2016-01-13.
The value of the paragraph is the American format - 12-01-2016 (the change in day is due to localizing from GMT to EST)
Chrome language is set to Canadian, as is my system setting (Windows 7). The date input seems to be respecting that, but I thought toLocaleDateString() would pick up Canada as my locale and format the date appropriately.
MSDN describes this function like this:
dateObj.toLocaleDateString( [locales][, options])
locales (Optional). An array of locale strings that contain one or more language or locale tags. If you include more than one locale string, list them in descending order of priority so that the first entry is the preferred locale. If you omit this parameter, the default locale of the JavaScript runtime is used.
Is the JavaScript runtime default locale something the user can change? I'm guessing not given my lack of success.
The different formatting between the date input and toLocaleDateString is quite baffling to me, any thoughts on how I can align the two?
http://jsfiddle.net/DfkU5/283/
Is the JavaScript runtime default locale something the user can change?
That depends entirely on the browser developers, they can do whatever they like. However, they tend to use system settings, but not always. Chrome ignores my settings for toLocalString, showing dates in m/d/y format when my preference is for d/m/y.
Safari, Chrome and Firefox all show a different string for toLocaleDate, which makes it just about useless.
The different formatting between the date input and toLocaleDateString is quite baffling to me, any thoughts on how I can align the two?
By far the best solution is to present dates in an unambiguous format, the easiest being to use the month name. All the following are unambiguous and easy to read:
19-Mar-2016
March 19, 2016
19 March, 2016
To do that you can write your own formatter (maybe 10 lines of code), or perhaps use a library.
In regard to input type date, not all browsers support it and there are lots of issues, so if you're going to use it you must check for support (fairly trivial) and if lacking, provide a fallback that does something sensible. And once you have a good fallback, you might as well implement it everywhere and forget input type date.
Then all the issues associated with it are gone. ;-)
Pass your locale as an arugment to toLocaleDateString()
e.g:
date.toLocaleDateString('en-CA')
or if you want to specify some fallback language, do this
date.toLocaleDateString(['en-CA','en-US'])
Check here

How does toLocaleDateString() work in Chrome?

I understood the javascript method toLocaleDateString() used computer settings.
Let's take the W3Schools example :
when i change date and hour formats of my computer, the result is different in Firefox or IE (as expected), but Chrome still shows the same date format, why?
From the MDN:
"The exact format depends on the platform, locale and user's settings."
And,
"You shouldn't use this method in contexts where you rely on a particular format or locale."
Basically, "Why" is because that's how Chrome does it. If you need a specific format, you're going to have to specify it yourself.
From the EMCAScript 5 standard:
15.9.5.6 Date.prototype.toLocaleDateString ( )
This function returns a String value. The contents of the String are implementation-dependent, but are intended to represent the “date” portion of the Date in the current time zone in a convenient, human-readable form that corresponds to the conventions of the host environment’s current locale.
Chrome can represent the date as a locale date string in whatever manner it likes. The standard only supplies guidelines; it does not mandate a particular format. And, in fact, the result will vary not only between browsers but also within Chrome itself depending on your locale settings.
It looks like Chrome does not use the Windows regional settings, but its own settings instead. These are available via Settings > Advanced Settings > Language. However the date format is not explicitly defined, it is inferred from the language + country choice, for instance:
English (US) sets date format to mm/dd/yyyy
English (UK) sets date format to dd/mm/yyyy
(For anyone trying to change these, don't forget - like I did - to restart Chrome for the settings to take effect)
Back to the original question, it looks like it was legit to use toLocaleDateString() as long as the idea is to present the information in a format the human user understands. But this would be an ideal world, where every user has his/her browser properly configured. Instead, Chrome is set by default to English(US) as long as people leave it be in English, and it takes some googling (which most users won't do) to change these settings.
This makes it risky to use toLocaleDateString() even when not "relying on a particular format or locale". It looks like the only "serious" option for any cross-browser web application is to manage its own date format preferences (per user, of course...)

How to find browser date time format [duplicate]

I have set a deadline in UTC, as shown below, and I'm wondering what exactly the toLocaleString() method will do to it on user's local machines. For instance, will it account for daylight savings if they are in a timezone that recognizes it? Or will I need to insert additional code that checks where the user is, and then fixes the displayed time?
http://javascript.about.com/library/bldst.htm
var deadline = new Date('5/1/2013 ' + "16:15" + ' UTC');
alert(deadline.toLocaleString());
In general, the answer is yes. JavaScript will represent the UTC value at the appropriate local time based on the time zone settings of the computer it is running on. This includes adjustment for DST. However, as others have pointed out, the details are implementation specific.
If you want a consistent output, I would use a library to format your dates instead of relying on the default implementation. The best library (IMHO) for this is moment.js. The live examples on their main page will give you an idea of what it can do.
UPDATE
If you are passing UTC values that you want converted to the correct local time, and that time falls into a period where the time zone rules are different than the current one - then the results will be invalid. This is crazy, but true - and by design in the ECMA spec. Read - JavaScript Time Zone is wrong for past Daylight Saving Time transition rules
We don't know what exactly the toLocaleString method does (§15.9.5.5):
This function returns a String value. The contents of the String are
implementation-dependent, but are intended to represent the Date in
the current time zone in a convenient, human-readable form that
corresponds to the conventions of the host environment’s current
locale.
But yes, most implementations will consider DST if it is active in the current local timezone. For your example I'm getting "Mittwoch, 1. Mai 2013 18:15:00" - CEST.
Will I need to insert additional code that checks where the user is, and then fixes the displayed time?
I think you can trust toLocaleString - the browser should respect the user's settings. If you want to do it manually, check out timezone.js.
As you use "UTC" the date itself will be UTC format, but the toLocaleString() takes client's locale into account, which means it'll return the date in string updated with all and every changes typical to client's regional and locale settings (DST, date/time format, etc).As JS documentation describes this: "The toLocaleString() method converts a Date object to a string, using locale settings.".If you want to avoid this, use the toUTCString() method instead.I'd also recommend reading the accepted solution for the question Javascript dates: what is the best way to deal with Daylight Savings Time? to avoid (at least, to try to avoid :) future issues related to JS, browsers and locales.Hope this helps!

Categories