Во время недавнего опыта написания JS-переводчика я много боролся с внутренней работой дат ECMA / JS. Итак, я полагаю, что я брошу свои 2 цента здесь. Надеемся, что совместное использование этого материала поможет другим с любыми вопросами о различиях между браузерами в том, как они обрабатывают даты.
Все реализации хранят свои значения даты внутри себя как 64-разрядные номера которые представляют собой миллисекунды с 01.01.1970 UTC (GMT - это то же самое, что и UTC). Даты, возникающие после 1/1/1970 00:00:00
, являются положительными числами, а даты предшествуют отрицательным.
Поэтому следующий код дает точный результат во всех браузерах.
Date.parse('1/1/1970');
В моей временной зоне ( EST), результат составляет 18000000, потому что это то, сколько мс составляет 5 часов (это всего 4 часа в летние месяцы). Значение будет отличаться в разных часовых поясах. Все основные браузеры делают это одинаково.
Вот и все. Несмотря на то, что в форматах входных строк есть некоторые отклонения, которые основные браузеры будут анализировать как даты, они по существу интерпретируют их одинаково с часовыми поясами и летней экономией. Один из них - формат ISO 8601. Это единственный формат, специально описанный в спецификации ECMA-262 v.5. Для всех других строковых форматов интерпретация зависит от реализации. По иронии судьбы, это формат, в котором браузеры могут отличаться. Ниже приведен сравнительный вывод Chrome vs Firefox для 1/1/1970 на моей машине с использованием формата строки ISO 8601.
Date.parse('1970-01-01T00:00:00Z'); // Chrome: 0 FF: 0
Date.parse('1970-01-01T00:00:00-0500'); // Chrome: 18000000 FF: 18000000
Date.parse('1970-01-01T00:00:00'); // Chrome: 0 FF: 18000000
toString
для соответствия моему входному значению, если я не укажу альтернативный часовой пояс, который я никогда не делаю. Отсутствие спецификатора должно предполагать местный вход времени. Но здесь ситуация ухудшается, FF обрабатывает краткую форму формата ISO 8601 («YYYY -MM-DD ") по-разному, чем обрабатывает длинную форму (« YYYY-MM-DDTHH: mm: ss: sssZ ») без каких-либо логических причин. Вот результат из FF с длинными и короткими форматами даты ISO без спецификатора часового пояса.
Date.parse('1970-01-01T00:00:00'); // 18000000
Date.parse('1970-01-01'); // 0
Итак, чтобы ответить на вопрос первоначального вопросчика, "YYYY-MM-DD"
- это короткая форма ISO 8601 "YYYY-MM-DDTHH:mm:ss:sssZ"
. Таким образом, это интерпретируется как время UTC, тогда как другое интерпретируется как локальное. Вот почему,
console.log(new Date(Date.parse("Jul 8, 2005")).toString());
console.log(new Date(Date.parse("2005-07-08")).toString());
console.log(new Date(Date.parse("Jul 8, 2005")).toString());
console.log(new Date(Date.parse("2005-07-08T00:00:00")).toString());
Нижняя строка - это строка синтаксического анализа. Единственная строка ISO 8601, которую вы можете безопасно анализировать в браузерах, - это длинная форма. И ВСЕГДА используйте спецификатор «Z». Если вы это сделаете, вы можете спокойно перемещаться между локальным и UTC.
console.log(new Date(Date.parse("2005-07-08T00:00:00Z")).toString());
К счастью, большинство современных браузеров другие форматы ввода одинаково, включая наиболее часто используемые форматы «1/1/1970» и «1/1/1970 00:00:00 AM». Все следующие форматы (и другие) рассматриваются как локальный ввод времени во всех браузерах и конвертируются в UTC перед хранением. Таким образом, они совместимы с кросс-браузером. Выходной код этого кода во всех браузерах в моем часовом поясе одинаковый.
console.log(Date.parse("1/1/1970"));
console.log(Date.parse("1/1/1970 12:00:00 AM"));
console.log(Date.parse("Thu Jan 01 1970"));
console.log(Date.parse("Thu Jan 01 1970 00:00:00"));
console.log(Date.parse("Thu Jan 01 1970 00:00:00 GMT-0500"));
. На стороне вывода все браузеры переводили часовые пояса одинаково, но они обрабатывать строковые форматы по-разному. Вот функции toString
и то, что они выводят. Обратите внимание на то, что функции toUTCString
и toISOString
выводят на моей машине 5:00 AM.
Конвертирует с UTC в локальное время перед печатью
- toString
- toDateString
- toTimeString
- toLocaleString
- toLocaleDateString
- toLocaleTimeString
Прямая печать сохраненного времени UTC
- toUTCString
- toISOString
In Chrome
toString Thu Jan 01 1970 00:00:00 GMT-05:00 (Eastern Standard Time)
toDateString Thu Jan 01 1970
toTimeString 00:00:00 GMT-05:00 (Eastern Standard Time)
toLocaleString 1/1/1970 12:00:00 AM
toLocaleDateString 1/1/1970
toLocaleTimeString 00:00:00 AM
toUTCString Thu, 01 Jan 1970 05:00:00 GMT
toISOString 1970-01-01T05:00:00.000Z
In Firefox
toString Thu Jan 01 1970 00:00:00 GMT-05:00 (Eastern Standard Time)
toDateString Thu Jan 01 1970
toTimeString 00:00:00 GMT-0500 (Eastern Standard Time)
toLocaleString Thursday, January 01, 1970 12:00:00 AM
toLocaleDateString Thursday, January 01, 1970
toLocaleTimeString 12:00:00 AM
toUTCString Thu, 01 Jan 1970 05:00:00 GMT
toISOString 1970-01-01T05:00:00.000Z
Я обычно не используйте формат ISO для ввода строки. Единственный раз, когда использование этого формата полезно для меня, - это когда даты нужно сортировать как строки. Формат ISO можно сортировать как есть, а другие - нет. Если у вас есть совместимость с несколькими браузерами, укажите либо часовой пояс, либо используйте совместимый строковый формат.
Код new Date('12/4/2013').toString()
проходит через следующее внутреннее псевдопреобразование:
"12/4/2013" -> toUCT -> [storage] -> toLocal -> print "12/4/2013"
Надеюсь, этот ответ был полезен.
Неуниверсальные наборы являются столь устаревшими, что они были удалены из CoreCLR, используемого в Silverlight и Живой Сетке.
Существуют также проблемы с видимостью COM - взаимодействующие с COM, не может использоваться с дженериками
Продвижение только универсальных наборов должно использоваться. Существует также преимущество предотвращения упаковки/распаковывания типов в наборе. Это неэффективно, особенно когда у Вас есть набор типов значения, которые преобразовываются в Систему. Объект, когда сохранено на наборе, следовательно храня значения на "куче" вместо стека вызовов.
Относительно использования неуниверсальных наборов для хранения неоднородных наборов материала можно всегда использовать List< object> выполнять то же самое. Поэтому один, я сказал бы, что нет почти никакой причины вообще для касания неуниверсальных наборов когда-либо снова.
исключение к этому должно было бы поддержать совместимость с системами, записанными на других языках, или против предыдущих версий платформы.NET, но это - "довольно острый" случай, если Вы спрашиваете меня.
Я могу сказать Вам, что сериализация XAML наборов полагается на них реализующий или IList или IDictionary, таким образом, неуниверсальные наборы будут с нами в течение некоторого времени.
Я не перешел бы и сказал бы, что это является устаревшим или будет удаленным в ближайшее время. Это верно, что необходимо избегать использования неуниверсальных наборов, если у Вас нет причины не не, используют универсальную версию. Тысячи строк наследия (не так прежней версии) код все еще плавает вокруг (и будет в течение многих лет), что неуниверсальные наборы поддержки, такие как ArrayLists. Так как они были [только 110] наборы в.NET 1.0 и 1.1, она широко использовалась (и злоупотреблялась) в течение года.
я все еще иногда должен взаимодействовать со старым картопостроителем O/R, записанным в.NET 1.1, который возвращает объекты IList. У меня есть метод, который делает преобразование в универсальный List<>, который не эффективен, но это - способ, которым это.
И если необходимо хранить различные объекты в том же массиве (странный, но возможный) Вы будете нуждаться в неуниверсальном наборе. Штраф Упаковки и Распаковывания - что-то, что необходимо будет заплатить так или иначе.
не боятся использовать их, если Вы чувствуете, что имеете к.
Да, насколько я понимаю, что они только там для совместимости с существующими продуктами. Необходимо всегда использовать безопасную с точки зрения типов версию (т.е. использовать Систему. Наборы. Универсальный по Системе. Наборы).
Могли бы быть экземпляры, где необходимо хранить объекты неизвестных типов или объекты нескольких различных типов, но если Вы действительно знаете тип объектов, которые Вы хотите хранить тогда, я не вижу причины не использовать универсальную версию.
Редактирование: Как прокомментировано можно просто использовать List<Object>
- doh!