Почему спецификация ISO-8601 выглядит повсеместно игнорируемой, когда речь идет о десятичных знаках?

Из ISO-8601: 2004 (E) Спецификация:

4.2.2.4 Представления с десятичной дроби

При необходимости для конкретного приложения десятичная доля часа, минуты или секунды могут быть включены. Если включена десятичная дробь, время младшего порядка элементы (если таковые имеются) должны быть опущены, а десятичная дробь должна быть разделенный на целую часть на десятичный знак, указанный в ISO 31-0, т.е. Запятая [,] или полная остановка [.]. Из них запятая предпочтительный знак.

Прост достаточно. Таким образом, согласно этой спецификации, доли секунды предпочтительнее записывать с использованием запятой, разделяющей целую и десятичную части, такие как 2014-01-01T00:00:00,123. Однако кажется, что почти везде принимается только десятичная точка (ака "полная остановка" )

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

Ниже приведен список тех, где я тестировал. Не стесняйтесь редактировать вопрос, чтобы увеличить мой список, если найдете другие. Спасибо.

.NET/С#

DateTime dt = DateTime.Parse("2014-01-01T00:00:00,123");

Выдает сообщение FormatException с сообщением "String не был признан действительным DateTime". То же самое с периодом, а не с запятой, успешно выполняется.

Объект даты JavaScript

Протестировано последним (на момент написания этой статьи) Chrome, Internet Explorer, Firefox и Node.js:

var dt = new Date('2014-01-01T00:00:00,123');

Возвращает "Invalid Date". Использование периода вместо этого отлично работает.

JavaScript с moment.js

var valid = moment("2014-01-01T00:00:00,123").isValid();

Возвращает false. Использование периода вместо этого возвращает true.

PHP

echo strtotime('2014-01-01T00:00:00,123');

Возвращает пустую строку. Использование периода вместо этого отлично работает.

рубин

require 'time'
puts Time.iso8601("2014-01-01T00:00:00,123")

Дает ошибку времени выполнения. Пока Time не сохраняет дробные секунды, это не должно быть ошибкой - и действительно, если используется период, он работает.

Ответ 1

Чистый синтаксический анализатор, совместимый с ISO-8601, ДОЛЖЕН поддерживать как запятую, так и точку. Запятая не требуется строго, рекомендуется только. Поэтому в отношении этого стандарта приведенные примеры JavaScript, PHP, Ruby и т.д. Четко указывают на ошибку этих реализаций парсера.

RFC3339 действительно поддерживает только подмножество (исключая запятую AND также исключая десятичные часы или десятичные минуты!) - поэтому не полностью соответствует ISO.

XML-схема похожа. К сожалению, это исключает запятую (см. Документ W3C).

Итак, вы спрашиваете, почему? Это мое подозрение: в мире программирования сильно доминируют США. В американской культуре точка используется как десятичный разделитель в числах. Поэтому большинство людей, разрабатывающих такие рамки, стандарты и библиотеки, сидят в США и ошибочно считают, что точки являются квази-международным стандартом.

Итак, остается вопрос, почему ISO использует/рекомендует запятую? Я точно не знаю, но мы все знаем, что офис группы ИСО находится в Париже, а не в США. А в Европе (исключая Великобританию) запятая обычно предпочтительнее как десятичный разделитель, а также культурный аспект.

Наконец, не все парсеры ошибаются. По крайней мере Joda-Time поддерживает запятую, хотя предпочитает точку в печати. Какова ситуация в NodaTime? Надеюсь, по крайней мере, похоже на Joda-Time. Продолжайте поддерживать разбор запятой. С европейской точки зрения приятно видеть, что не все вещи выглядят как американские; -).

Ответ 2

RFC3339, как определено IETF, указывается только . как разделитель.

Здесь раздел 5.6:

5.6. Internet Date/Time Format

   The following profile of ISO 8601 [ISO8601] dates SHOULD be used in
   new protocols on the Internet.  This is specified using the syntax
   description notation defined in [ABNF].

   date-fullyear   = 4DIGIT
   date-month      = 2DIGIT  ; 01-12
   date-mday       = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on
                             ; month/year
   time-hour       = 2DIGIT  ; 00-23
   time-minute     = 2DIGIT  ; 00-59
   time-second     = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second
                             ; rules
   time-secfrac    = "." 1*DIGIT
   time-numoffset  = ("+" / "-") time-hour ":" time-minute
   time-offset     = "Z" / time-numoffset

   partial-time    = time-hour ":" time-minute ":" time-second
                     [time-secfrac]
   full-date       = date-fullyear "-" date-month "-" date-mday
   full-time       = partial-time time-offset

   date-time       = full-date "T" full-time