Непоследовательное поведение toLocaleString() в другом браузере

Я работаю над проектом, в котором мне приходится иметь дело с датой и временем. Серверной технологией является ASP.Net, а на стороне клиента я использую jQuery и jQuery Week Calendar(плагин jQuery).

Итак, вот описанная проблема, я получаю Data Time с сервера что-то вроде этого 2012-11-13T04:45:00.00 в формате GMT.

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

Для этого я использую метод JavaScript toLocaleString(), Это хорошо работает только в Chrome, в другом браузере работает противоречиво.

Вот его результаты в разных браузерах:

Google Chrome (работает нормально):

Вызов:

new Date ("2012-11-13T04:45:00.00").toLocaleString();

Выход:

Tue Nov 13 2012 10:15:00 GMT+0530 (India Standard Time)

Mozilla Firefox:

Вызов:

new Date ("2012-11-13T04:45:00.00").toLocaleString();

Выход:

Tuesday, November 13, 2012 4:45:00 AM

Сафари:

Вызов:

new Date ("2012-11-13T04:45:00.00").toLocaleString();

Выход:

Invalid Date

Internet Explorer:

Вызов:

new Date ("2012-11-13T04:45:00.00").toLocaleString();

Выход:

Tuesday, November 13, 2012 4:45:00 AM

На данный момент это браузеры, где я тестировал.

Вот вопрос:

Мне нужен способ конвертировать время данных (в таком формате 2012-11-13T04:45:00.00 ) Для локали даты и времени, независимо от того, какой клиент браузера использует.

4 ответа

Краткий ответ: нет. toLocaleString может быть реализован по желанию разработчиков. Ваш вопрос подразумевает, что Chrome выводит нужную вам строку.

Если вы хотите выводить этот формат последовательно, вам нужно использовать отдельную библиотеку - например, DateJS.

Для этого с DateJS потребуются некоторые стандартные спецификаторы формата, доступные в core.js, а некоторые - только в extras.js. В документации есть список всех спецификаторов формата.

Строка, которую вы хотите:

Tue Nov 13 2012 10:15:00 GMT+0530 (India Standard Time)

Таким образом, чтобы получить это от DateJS вам понадобится:

"D M d Y H:i:s \G\M\TO (e)"

Синтаксис для DateJS:

new Date ("2012-11-13T04:45:00.00").format("D M d Y H:i:s \G\M\TO (e)");

Вместо того, чтобы использовать toLocaleString() который устарел и неправильно реализован для всех веб-браузеров, я настоятельно рекомендую использовать Globalize для форматирования даты и времени.

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

Globalize.culture(theCulture);
Globalize.format( new Date(2012, 1, 20), 'd' ); // short date format
Globalize.format( new Date(2012, 1, 20), 'D' ); // long date format

Довольно просто, не правда ли? Ну, вам придется также интегрировать его с вашим приложением ASP.Net, что немного усложняет ситуацию. Во-первых, вам нужно ссылаться на globalize.js обычным способом:

<script type="text/javascript" src="path_to/globalize.js"></script>

Тогда лучше включить правильное определение культуры, которое вам нужно будет использовать при форматировании:

<script type="text/javscript" src="path_to/cultures/globalize.culture.<% = CultureInfo.CurrentCulture.ToString() %>.js"></script>

Наконец вам нужно будет установить theCulture переменная, прежде чем использовать его:

<script type="text/javscript">
    var theCulture = <% = CultureInfo.CurrentCulture.ToString() %>
</script>

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

public string IntegrateGlobalize(string pathToLibrary)
{
  var sb = new StringBuilder();
  sb.Append("<script type=\"text/javascript\" src=\"");
  sb.Append(pathToLibrary);
  sb.AppendLine("/globalize.js\"></script>");
  sb.Append("<script type=\"text/javascript\" src=\"");
  sb.Append(pathToLibrary);
  sb.AppendLine("/cultures/globalize.culture.");
  sb.Append(CultureInfo.CurrentCulture);
  sb.AppendLine(\"></script>");
  sb.Append("<script type=\"text/javascript\">");
  sb.Append("var theCulture = ");
  sb.Append(CultureInfo.CurrentCulture);
  sb.AppendLine(";</script>");

  return sb.ToString();
}

Тогда все, что вам нужно сделать, это сослаться на этот метод в заголовке страницы (master?):

<head>
  <% = IntegrateGlobalize("path_to_globalize") %>
  ...
</head>

Некоторые вопросы

Если вы хотите сделать это на 100% правильно, вам нужно улучшить генератор культуры Globalize, чтобы он включал 'g' Переключатель формата, а затем используйте этот точный переключатель на стороне клиента для форматирования даты:

Globalize.format( new Date(2012, 1, 20), 'g' ); // default date format

Это почему? Потому что "g" является форматом даты по умолчанию. Это то, что вы получите, когда просто позвоните DateTime"s ToString() метод без параметров (который будет подразумевать CultureInfo.CurrentCulture как единственный параметр...). Формат по умолчанию лучший, он будет либо коротким, либо длинным, либо любым другим, но чаще всего используется людьми, использующими эту культуру.

я сказал что toLocaleString() не подходит для всех веб-браузеров. Это почему? Это потому, что он будет использовать настройки веб-браузеров, а не обнаруженную на стороне сервера культуру. Это означает, что у вас могут быть смешанные культуры на одной веб-странице. Это может произойти, если некоторые даты отформатированы на стороне сервера, а некоторые на стороне клиента. Вот почему нам нужно было передать (обнаружить) культуру со стороны сервера.
КСТАТИ. Если вы решите включить диалоговое окно региональных настроек в свое веб-приложение, несоответствие будет еще более заметным, так как toLocaleString() не будет следовать настройкам пользователя...

Чтобы преобразовать время в специфичную для локали строку на сервере, вы можете использовать метод DateTime.ToLongDateString. На этой странице см. Примечание о "текущем объекте культуры" (на сервере) класса DateTimeFormatInfo. Убедитесь, что он установлен правильно.

Коренная причина этой проблемы никогда не была решена ни одним из ответов. ОП сказал:

Я получаю данные времени с сервера что-то вроде этого 2012-11-13T04:45:00.00 в формате GMT.

GMT это не формат. Эта строка в расширенном формате ISO 8601 без указания часового пояса. В спецификации ISO 8601 говорится, что без квалификатора это означает местное время. Чтобы указать время по Гринвичу, вы должны добавить Z до конца, или вы можете добавить смещение, такое как +00:00,

Проблема в том, что ECMAScript (v1 - v5.1) не соблюдает это положение в спецификации. Это фактически сказало, что должно интерпретироваться как UTC вместо местного времени. Некоторые браузеры соответствуют спецификации ISO, некоторые - спецификации ECMA. Это было исправлено для версии 6, и большинство браузеров выполнили.

Итак, если вы намереваетесь передавать временные метки на основе UTC/GMT, то на стороне сервера вы всегда должны отправлять Z поэтому нет никакой двусмысленности.

Тем не менее, даже если значение правильно интерпретировано, нет гарантии, что строки будут одинаково отформатированы в разных браузерах. Для этого вам действительно нужна библиотека. Я рекомендую moment.js, но есть и другие.

Другие вопросы по тегам