Изменения ToLocaleDateString() в IE11

В IE 11 я получаю забавные результаты с помощью ToLocaleDateString(). Возвращаемая строка отлично выглядит в браузере, например. «28.01.2014 11:00:46», но затем, если я скопирую и вставлю это значение в обычный текстовый редактор, оно будет выглядеть так: «?1?/?28?/?2014 ?11?:? 00?:?46? ?AM".

Интересно, что если я вставляю текст в продукт Microsoft, он выглядит нормально... Проблема в том, что если вы попытаетесь использовать значение программно для создания даты, оно будет недействительным. Вы можете проверить это, просто открыв консоль в IE11 и создав новую дату, используя для нее ToLocaleDateString(), а затем попытавшись использовать полученную строку для создания новой даты в javascript или на выбранном вами языке (я м, используя ASP.NET здесь...).

Я делаю что-то не так, или я должен каким-то другим образом взаимодействовать с датой javascript? Как я могу избавиться от этих причудливых символов?

Редактировать: благодаря комментарию ниже я смог выяснить, что представляют собой непоказанные символы, они расположены слева направо. В зависимости от редактора, в который я вставляю значения, и кодировки, на которую настроен редактор, текст будет отображаться по-разному: иногда с «?», иногда без.


person ctb    schedule 28.01.2014    source источник
comment
Какой простой текстовый редактор вы используете и какую кодировку он использует?   -  person Bergi    schedule 28.01.2014
comment
Пожалуйста, сделайте var str=(new Date).toLocaleDateString();for(var i=0;i<str.length;i++)console.log(i,str.charCodeAt(i),str.charAt(i)) и опубликуйте его результаты здесь   -  person Bergi    schedule 28.01.2014
comment
Я использовал TextPad в качестве редактора. Таким образом он отображается в ANSI, DOS, UTF-8 и Unicode. Когда я вставляю его в блокнот, он не появляется. Запуск вашего javascript дает: var str=(new Date).toLocaleDateString();for(var i=0;i‹str.length;i++)console.log(i,str.charCodeAt(i),str.charAt(i )) 0 8206 ? 1 49 1 2 8206 ? 3 47/4 8206 ? 5 50 2 6 56 8 7 8206 ? 8 47 / 9 8206 ? 10 50 2 11 48 0 12 49 1 13 52 4 не определено   -  person ctb    schedule 28.01.2014
comment
Спасибо, хотя было бы лучше, если бы вы отредактировали свой пост и поместили туда результаты в табличном формате :-)   -  person Bergi    schedule 29.01.2014
comment
У меня точно такая же проблема.   -  person Maxx    schedule 29.05.2014
comment
У меня такая же проблема. Чтобы ответить на ctb, вот результаты IE11: undefined 0 8206 ? 1 55 7 2 8206 ? 3 47/4 8206 ? 5 54 6 6 8206 ? 7 47/8 8206 ? 9 50 2 10 48 0 11 49 1 12 52 4   -  person Josh Pollard    schedule 07.07.2014
comment
Это ошибка в IE11 connect.microsoft.com/IE/feedback/details/811107. Вы можете использовать toLocaleDateString().replace(/‎/g, ''), чтобы обойти эту проблему.   -  person Chase    schedule 28.08.2015
comment
Спасибо, это сводило меня с ума   -  person Gordon Thompson    schedule 03.02.2016
comment
Спасибо, Чейз!!!   -  person Shulyk Volodymyr    schedule 10.04.2019
comment
const currentDay = new Date().toLocaleString('en-us', {день недели: 'длинный'}); Я пытался сравнить строку с днем ​​недели, как этот currentDay === Monday, и IE11 всегда возвращал false ... потому что длина строки currentDay равна 7, а в понедельник - только 6. После добавления .replace(/ ‎/g, '') это сработало.   -  person giri-jeedigunta    schedule 30.09.2019


Ответы (5)


Проблема в том, что если вы попытаетесь использовать значение программно для создания даты, оно будет недействительным.

...

Я делаю что-то не так, или я должен каким-то другим образом взаимодействовать с датой javascript?

Да, вы делаете это неправильно. Вы не должны использовать функцию, предназначенную для форматирования чего-либо для отображения человеком, зависящего от локали, и ожидать, что вывод будет обрабатываться машиной. Любой вывод toLocaleString, toLocaleDateString или toLocaleTimeString предназначен только для удобочитаемого отображения. (Как пояснил Берги в комментариях, toString также предназначен для отображения человеком, но ECMA §15.9.4.2 говорит об этом надо туда-обратно)

Вероятно, вы получаете маркеры LTR, потому что ваш язык отображения — RTL. Кроме того, учтите, что локаль всегда будет влиять на вывод. Возможно, ваша локаль использует форматирование дд/мм/гггг вместо форматирования мм/дд/гггг. Или, возможно, ваш язык требует азиатских или арабских символов. Все это необходимо учитывать при определении формата отображения, но они никогда не подходят для машинного синтаксического анализа.

Также учтите, что спецификация ECMAScript не определяет каких-либо конкретных правил форматирования для вывода этих методов, и разные браузеры будут давать разные результаты.

Если целью является нечто иное, чем отображение пользователю, вместо этого вы должны использовать одну из этих функций:

  • toISOString даст вам отметку времени в формате ISO8601/RFC3339.
  • toGMTString или toUTCString даст вам отметку времени в формате RFC822/RFC1123.
  • getTime даст вам целочисленную временную метку Unix с точностью до миллисекунды

Все вышеперечисленное вернет значение на основе UTC. Если вам нужно местное время, вы можете либо создать свою собственную строку с различными функциями доступа (getFullYear, getMonth и т. д.), либо использовать библиотеку, такую ​​как момент.js:

Это использует moment.js для возврата местного времени в формате ISO8601 + смещение от даты:

moment(theDate).format()   // ex:  "2014-08-14T13:32:21-07:00"
person Matt Johnson-Pint    schedule 14.08.2014
comment
Я думаю, что понял. Итак, если вы создаете элемент управления, который запрашивает дату рождения, и вам нужно приспосабливаться к другим иностранным локали (RTL, дд/мм/гг и т. д.), как вы получите что-то безопасное для анализа (например, метку времени UTC) вернуться на сервер, по-прежнему представляя выбранную дату пользователю в локализованном формате? - person ctb; 15.08.2014
comment
Именно поэтому во многих элементах управления вводом даты вы выбираете из календаря, а не анализируете ввод. Хотя есть некоторые способы. Moment.js имеет парсинг входных данных для различных локалей, а входные данные даты/времени/даты/времени HTML5 также имеют некоторые из них. Объект Date также может выполнять некоторый синтаксический анализ, и он должен работать с любой текущей локалью. Но нет единственного способа сделать это, который бы принимал все, что может ввести пользователь. В большинстве случаев вы хотели бы дать вашему пользователю некоторый намек на ожидаемый формат ввода. - person Matt Johnson-Pint; 15.08.2014
comment
Опять же, если бы это была простая дата (например, дата рождения), я бы, вероятно, не хотел преобразовывать ее в UTC. Есть разница между целой датой и датой + временем. Объект javascript Date на самом деле является объектом даты и времени. - person Matt Johnson-Pint; 15.08.2014
comment
Хотя вывод toString предназначен для удобочитаемого отображения, он предназначен не только для этого. Взгляните на §15.9.4.2: С Date объектом x , ожидается, что x.valueOf() === Date.parse(x.toString()) - конечно, это не делает его форматом обмена между реализациями, но его нужно как-то анализировать. - person Bergi; 15.08.2014
comment
@ Берги - Спасибо. И в том же разделе сказано, что toLocaleString не требуется для этого. Отредактировал мой ответ. :) - person Matt Johnson-Pint; 15.08.2014

Я исправил это с помощью следующего replace(/[^ -~]/g,'') как в

(new Date("7/15/2014").toLocaleString().replace(/[^ -~]/g,'')
person vldmrrr    schedule 17.11.2014
comment
Ваш ответ для меня самый простой и точный. Спасибо. - person Austin Lovell; 16.05.2015

function FixLocaleDateString(localeDate) {
    var newStr = "";
    for (var i = 0; i < localeDate.length; i++) {
        var code = localeDate.charCodeAt(i);
        if (code >= 47 && code <= 57) {
            newStr += localeDate.charAt(i);
        }
    }
    return newStr;
}

Возвращает только цифры и символ /. Кажется, это работает:

new Date(FixLocaleDateString(new Date("7/15/2014").toLocaleString()));

Возвращает правильную дату. Без вызова FixLocaleDateString() результатом будет недопустимая дата.

person Evan Machusak    schedule 21.07.2014
comment
Похоже, это сработает, поэтому я отмечу это как ответ. Это просто похоже на взлом. Разве неправильно пытаться получить объект Date из вывода ToLocaleDateString()? Что, если средство выбора даты заполняет ввод с помощью ToLocaleDateString()? Как вы должны получить дату на стороне сервера? Если вы просто возьмете значение из ввода, оно будет иметь эти символы слева направо, которые вас запутают. - person ctb; 14.08.2014
comment
В зависимости от используемой вами серверной технологии левый/правый символы обрабатываются правильно (т. е. игнорируются). Я использую это с веб-службой MVC 5, передавая входные данные в виде строк, которые затем использую для синтаксического анализа с помощью DateTime.Parse, который может обрабатывать строки в любой кодировке, включая строки, содержащие символы пробела, такие как метки порядка байтов Unicode и тому подобное. Не ошибитесь. Это взлом. Это обходной путь для ошибки в реализации JavaScript в IE. Браузеры Webkit не страдают от этой проблемы, поэтому FixLocaleDateString для них не нужен. - person Evan Machusak; 28.08.2014

Для полноты ответа форма:

В моей системе метод toLocaleDateString объекта Date IE 11 приводит к "7/6/2014" при запуске в консоли, которая представлена ​​​​в виде следующих байтов:

00000000  22 e2 80 8e 37 e2 80 8e  2f e2 80 8e 36 e2 80 8e  |"â.Z7â.Z/â.Z6â.Z|
00000010  2f e2 80 8e 32 30 31 34  22                       |/â.Z2014"|

Непечатаемые элементы – это 0xe2 0x80 0x8e, в которых используется кодовая точка Unicode в кодировке UTF-8 U+200E. Это, как говорится в комментариях выше, ОТМЕТКА СЛЕВА НАПРАВО.

У этого JSFiddle, похоже, нет проблем с использованием значения, возвращаемого из toLocaleDateString(), для возврата к дате. По крайней мере, в моем IE 11.0.9600.17239 с версией обновления 11.0.11 (KB2976627). Так может только консоль добавляет лишних персонажей?

person Community    schedule 07.07.2014
comment
Это объясняет, кто такие персонажи, но не в этом загадка. Я думаю, что более важный вопрос заключался в том, как вернуться к фактической дате, если вы начинаете с вывода ToLocaleDateString() - person ctb; 14.08.2014
comment
Я обновил ответ, включив ссылку JSFiddle, которая, похоже, не испытывает проблемы. - person opello; 15.08.2014

var startDateConverted = new Date(start).toLocaleString().replace(/[^A-Za-z 0-9 \.,\?""!@#\$%\^&\*\(\)-_=\+;:<>\/\\\|\}\{\[\]`~]*/g, '')

если вы также хотите удалить время, используйте .split(' ').slice(0, -1).join(' ');

person nikunjM    schedule 15.01.2018
comment
Хотя вы можете просто заменить маркеры LTR ‎ на ''. ;-) - person RobG; 02.04.2020