Было предложено передать массив для форматов в $.fn.dataTable.moment(...)
, но это работает тогда и только тогда, когда никогда не случится, что данные соответствуют более чем одному формату в массиве. Если вы не можете гарантировать это, передача множества форматов не является решением.
Вы начали с примера DD.MM.YYYY
и MM/DD/YYYY
. Дата будет соответствовать одному или другому формату, но не обоим, потому что, если она имеет разделители периода, то она соответствует 1-му формату, но не 2-му, и если она имеет разделители косой черты, она соответствует 2-му формату, но не 1-му. Тем не менее, в целом, если у вас есть даты не из США или Германии, вы столкнетесь с неоднозначными случаями. Мэтт Джонсон упомянул, например, такую дату, как "01/04/2019", которая может соответствовать формату MM/DD/YYYY
и интерпретироваться как "4 января 2019", или соответствовать формату DD/MM/YYYY
и интерпретироваться как «1 апреля 2019 года».
Если у вас могут быть даты в формате DD/MM/YYYY
или MM/DD/YYYY
и вы вызываете $.fn.dataTable.moment(["DD/MM/YYYY", "MM/DD/YYYY"])
, то иногда вы получите неправильные результаты. Проблема в том, что плагин, реализующий функцию, которую вы ' Вызывающий смотрит на каждую ячейку в изоляции .
Таблица 1
Предположим, что таблица предназначена для использования дат в формате DD/MM/YYYY
со следующими ячейками:
- 21/2/2019 * +1027 *
* 1 028 * 1/4/2019
- 24/12/2019
Таблица 2
Предположим, что таблица предназначена для использования дат в формате MM/DD/YYYY
со следующими ячейками:
- 4/1/2019
- 12/24/2019
Две таблицы на самом деле содержат одинаковые даты. Они просто представлены по-разному.
Предположим, вы настроили свою таблицу с $.fn.dataTable.moment(["DD/MM/YYYY", "MM/DD/YYYY"])
. Таблица 1 будет интерпретирована правильно. Однако строка 2 в таблице 2 будет интерпретирована неправильно. Дата 4/1/2019
соответствует первому формату в массиве (DD/MM/YYYY
), и именно так moment
будет ее интерпретировать. Неважно, сколько других ячеек не может уместиться DD/MM/YYYY
, потому что плагин, который вызывает moment
, не выполняет статистический анализ. Он смотрит на каждую клетку изолированно. Вот соответствующий код (с удалением нескольких пустых строк):
$.fn.dataTable.moment = function ( format, locale, reverseEmpties ) {
var types = $.fn.dataTable.ext.type;
// Add type detection
types.detect.unshift( function ( d ) {
if ( d ) {
// Strip HTML tags and newline characters if possible
if ( d.replace ) {
d = d.replace(/(<.*?>)|(\r?\n|\r)/g, '');
}
// Strip out surrounding white space
d = $.trim( d );
}
// Null and empty values are acceptable
if ( d === '' || d === null ) {
return 'moment-'+format;
}
return moment( d, format, locale, true ).isValid() ?
'moment-'+format :
null;
} );
// Add sorting method - use an integer for the sorting
types.order[ 'moment-'+format+'-pre' ] = function ( d ) {
if ( d ) {
// Strip HTML tags and newline characters if possible
if ( d.replace ) {
d = d.replace(/(<.*?>)|(\r?\n|\r)/g, '');
}
// Strip out surrounding white space
d = $.trim( d );
}
return !moment(d, format, locale, true).isValid() ?
(reverseEmpties ? -Infinity : Infinity) :
parseInt( moment( d, format, locale, true ).format( 'x' ), 10 );
};
};
Вы могли бы перевернуть аргументы и вызвать $.fn.dataTable.moment(["MM/DD/YYYY", "DD/MM/YYYY"])
. Теперь со 2-й таблицей все будет в порядке, но та же проблема возникнет в 1-й таблице.
Хорошо, что тогда?
Если бэкэнд уже содержит метки времени UTC, то я просто отправляю эти метки времени во внешний интерфейс вместо отправки локализованных значений. На этапе рендеринга ячейки, содержащей дату, я бы хотел, чтобы клиентский интерфейс преобразовал дату UTC в формат, который имеет смысл для пользователя. Datatable будет выполнять сортировку на основе значений UTC, которые можно сравнивать без неоднозначности.
Если бэкэнд не хранит свои даты в виде меток времени UTC, я бы изменил его структуру, чтобы он сделал, а затем сделал бы то, что я описал в предыдущем абзаце.
В противном случае может быть способом сделать во внешнем интерфейсе статистический анализ вашей таблицы до того, как Datatables попытается отрендерить и упорядочить ее. Таким образом, вы можете узнать, какой формат используется, а затем передать его в Datatables. Тем не менее, это все еще кажется мне хрупким. Если в таблице используется серверный протокол, то одновременно доступна только небольшая часть данных. Если вы выполняете анализ только первого ответа от сервера, более поздний ответ, охватывающий более позднюю часть таблицы, может опровергнуть первоначальное предположение. Более того, могут быть случаи, когда все даты в датированных данных неоднозначны. В большом и нефильтрованном наборе данных это может быть маловероятным, но как только пользователям будет разрешено фильтровать набор данных для отображения только подмножества, они могут отфильтровать его таким образом, что все даты в конкретном подмножестве будут неоднозначными. Я бы не стал развертывать приложение в надежде, что этого никогда не произойдет.