IE 11 throwing "'timeZone' is outside of valid range" when setting timezone to "Europe/London"
Asked Answered
L

2

9

I have some js to get the local time displayed in uk's timezone.

var d = new Date(); // local system time (whatever timezone that is)
var dUK = new Date(d.toLocaleString('en-GB', { timeZone: 'Europe/London' })); // UK timezone (covers BST too)

Works fine in all browsers except IE 11(sigh...) which throws the following error:

Option value 'EUROPE/LONDON' for 'timeZone' is outside of valid range. Expected: ['UTC']

Does anybody have any suggestions? See http://jsbin.com/dawaqocuvi/1/edit?html,js,console,output for an example fiddle that supports IE.

Loyal answered 25/1, 2019 at 11:6 Comment(8)
Did you mean en-GB ? Also why would you then send that result to another new Date(Shockheaded
@keith Yeah that should be en-GB good spot. I didn't write this - just inherited the error. I've not checked but d may be getting used further down the line. Anyhow that's not why I've posted the question.Loyal
Ok, well doing new Date( again, really makes no sense. A locale formatted date is actually an invalid parameter to a date constructor anyway. IOW: It might work, it might not.. Just doing the following works for me -> var d = new Date(); var dUK = d.toLocaleString('en-GB', { timeZone: 'Europe/London' }); console.log(dUK);Shockheaded
@Shockheaded I'll probably re-write this block to be fair mate, there's a few issues with it. Anyhow, just tried your code in IE 11 and it's throwing the same error. Found a jsfiddle alternative that works in IE jsbin.com/dawaqocuvi/1/edit?html,js,console,outputLoyal
Ah!, yes IE11 support for locale is not there, only UTC timezone allowed. Should be ok with Edge though. Another option is to use a datetime lib like moment.js, momentjs.com Or better still maybe a polyfill -> npmjs.com/package/date-time-format-timezoneShockheaded
@Shockheaded I thought about using moment.js but figured it was overkill. I'll just bite the bullet and go with that. I wasn't aware that locale is not supported in IE. caniuse.com/#search=locale didn't flag it when I checked earlier. Cheers for the info.Loyal
Sorry, yes the word support is wrong,. Problem is the spec says for support the minimum is UTC, so technically by the spec, it is supported. But having a timezone that only accepts UTC, is not really that useful. It allows you to have locale time based on browser, and UTC time and that's it. Moment.js might be overkill yes, especially if modern browsers have descent support, that's why I like the idea of polyfill, my build system only sends polyfill's for browsers that need it. So using this say in a modern browser adds 0 byte's to my build, were with moment it would be for all.Shockheaded
@Shockheaded All useful info, happy to accept your UTC only comment as an answer mate as I'm sure someone else either has, or will run into this issue.Loyal
S
9

IE11, has limited support of date formatting when using the timezone option, basically the only valid option is UTC. Not very useful.

Two options that I can think off.

  1. Use momentjs, this is a nice datetime lib, but might be overkill
  2. Use a pollyfill

Below is a snippet, that polyfill's the locale timezone, and creates a simple world time clock, with a few zones..

If your running a modern browser, you should be able to remove the script tag at the start and it will continue to work.

Update: Got this working now in IE11, case is important when doing the locale with the polyfill. eg. Europe/Amsterdam is fine, but europe/amsterdam is not, with Chrome it didn't seem to matter.

//var d = new Date(); var dUK = d.toLocaleString('en-GB', { timeZone: 'America/Chicago' }); console.log(dUK);

function updateTimes() {
  var dt = new Date();
  var els = document.querySelectorAll("[data-tz]");
  for (var l = 0; l < els.length; l ++) {
    var d = els[l];
    d.innerText = dt.toLocaleString('en-GB', {timeZone: d.dataset.tz});
  }
}

updateTimes();
setInterval(updateTimes, 1000);
<script src="https://unpkg.com/date-time-format-timezone@latest/build/browserified/date-time-format-timezone-complete-min.js"></script>

<p>Simple world time clocks</p>

<div><span data-tz="Europe/London"></span>
  - London
</div>
<div>
  <span data-tz="Europe/Amsterdam"></span>
  - Amsterdam
</div>
<div>
  <span data-tz="America/Chicago"></span>
  - Chicago
</div>
Shockheaded answered 25/1, 2019 at 12:23 Comment(3)
just an fyi - the timezone script you've referenced is 2.5mb! moment.js is 50kb :)Loyal
@SeanT Yes, I included the complete version. Probably with way more locales than you require.. You can just include locale's you want, eg. for Los Angeles is 1.2K. And of course if you polyfill check, for Chrome it's 0K.. :)Shockheaded
@SeanT Not sure were 2.5mb is coming from either, in Chrome it's saying 262K for me. And moment.js with locales is showing 69.1K.Shockheaded
B
5

Yes, as stated above, IE 11 supports most of the Intl API but does not support the use of a specific timeZone: http://kangax.github.io/compat-table/esintl/#test-DateTimeFormat_accepts_IANA_timezone_names

Here is an example of how to polyfill just the Intl.DateTimeFormat function's timeZone support using webpack's require.ensure:

const fillIntlDateTimeFormatTimezone = () => new Promise((resolve) => {
    try {
        new Intl.DateTimeFormat('en', {
            timeZone: 'America/Los_Angeles',
            timeZoneName: 'long'
        }).format();
        return resolve();
    } catch (error) {
        require.ensure(['date-time-format-timezone'], (require) => {
            require('date-time-format-timezone');
            return resolve();
        }, 'DateTimeFormatTimezone');
    }
});

This should only load the polyfill for browsers that don't support specifying a timeZone property which should only be IE 11 at this point.

Baroscope answered 31/5, 2019 at 18:54 Comment(4)
require.ensure() is specific to webpack and superseded by import().Millstream
import 'date-time-format-timezone' did the trick, thank you for posting.Argil
Be careful with importing the whole date-time-format-timezone because if I remember correctly it is bigger than the whole momentjs libraryJuvenescence
@GiorgioTempesta yes it weighs 2.6 MB minified according to bundlephobia.Kidderminster

© 2022 - 2024 — McMap. All rights reserved.