У меня есть объект, который выглядит так:
myObject = {
publishedDate: string;
Url: string;
Title: string;
}
Свойство «publishedDate» представляет собой строку в формате «19.01.2021». Например, он может иметь дату в будущем, то есть значение больше, чем сегодня. Другими словами, я хочу сохранить все объекты, у которых publishDate меньше или равно сегодняшнему дню (и удалить все, что закончилось). Объекты сохраняются в моем состоянии (массив):
this.state.data
Сначала я создаю переменную даты для сегодняшнего значения, чтобы сравнить ее с опубликованной датой. Я также использую moment() для форматирования даты в том же формате, что и объект:
let today = moment().format("DD/MM/YYYY");
Затем я использую метод фильтра для сравнения и фильтрации данных:
this.state.data.filter(item => new Date(item.publishedDate) >= new Date(today))
И я также пробовал:
this.state.data.filter(function(item) {
if (new Date(item.publishedDate) >= new Date(today)) {
return false;
}
return true;
});
Мало того, что не работает, у меня еще все объекты в массиве и ничего не отфильтровывается. Что не так с кодом?
Конструктор Date
не примет формат, который вы сейчас используете, но распознает формат MM/DD/YYYY
. Кроме того, filter
сохраняет элементы, для которых функция возвращает значение true, поэтому вам следует проверить, меньше или равно ли Date
текущему Date
.
const today = new Date;
this.state.data = this.state.data.filter(({publishedDate})=>{
const [d, m, y] = publishedDate.split("/");
return new Date(m + "/" + d + "/" + y) <= today;
});
На данный момент new Date("19/01/2021")
возвращается: Invalid Date
.
Это возможное решение:
let today = moment().format("YYYY-MM-DD");
this.state.data.filter(function(item) {
const pubDate = item.publishedDate.split('/').reverse().join('-');
if (new Date(pubDate) >= new Date(today)) {
return false;
}
return true;
});
Вы должны сделать небольшую точную настройку строки даты, прежде чем сравнивать с сегодняшним днем. Вы можете попробовать это-
const data = [
{
publishedDate: "19/01/2021",
url: '',
title: 'date1'
},
{
publishedDate: "19/05/2021",
url: '',
title: 'date2'
},
{
publishedDate: "13/01/2020",
url: '',
title: 'date3'
},
{
publishedDate: "16/09/2009",
url: '',
title: 'date4'
},
];
const parseDate = (dateString) => new Date(...dateString.split('/').reverse());
const result = data.filter(item => parseDate(item.publishedDate) <= new Date());
console.info(result);
Хранение дат в виде строк — это запах кода. Их сложнее сравнивать, хранить и преобразовывать, а не хранить как собственный формат даты JS или альтернативы, такие как объект даты Moment.JS.
Вот тривиальный пример того, как вы могли бы это сделать, если бы вы сохранили свои объекты как дату.
Обратите внимание, что третий объект был отфильтрован.
const myObject1 = {
publishedDate: new Date("2019-01-01"), // NEW
Url: "whatever",
Title: "sample",
}
const myObject2 = {
publishedDate: new Date("2020-01-01"), // NEW
Url: "whatever",
Title: "sample",
}
const myObject3 = {
publishedDate: new Date("2099-01-01"), // NEW
Url: "whatever",
Title: "sample",
}
const arr = [myObject1, myObject2, myObject3];
const today = new Date();
const filtered = arr.filter((obj) => obj.publishedDate < today);
console.info(filtered);
Напротив, строки сериализуются тривиально, поэтому их можно использовать, например, в представлениях JSON. Но соответствующий формат был бы гораздо полезнее, если бы OP контролировала структуру данных.
Я согласен с тем, что строки легко конвертируются в JSON и удобочитаемы для людей. Однако у хранения дат в виде строк есть множество недостатков: их сложно преобразовать, трудно обеспечить достоверность, сложнее арифметика дат и т. д. См. refactoring.guru/smells/primitive-obsession
Помните, что OP начался с «У меня есть объект, который выглядит» с датами в строковом формате. Мы оба согласны с тем, что формат ужасен, но я не согласен с тем, что строковый формат здесь неуместен. Я определенно думаю, что это лучше, чем настоятельно не рекомендуется синтаксический анализ строк для создания новой даты. Я нахожу ISO 8601 полезной серединой — простой, сортируемый, сериализуемый, относительно легко конвертируемый в объекты Date. Если делать математику даты, я согласен.
Вы можете просто использовать встроенные компараторы moment
, подобные этому
this.state.data.filter(item => moment(item.publishedDate,'DD/MM/YYYY').isSameOrAfter(today))
Используя момент String + инициализатор формата и Is Same Or After:
this.state.data.filter(item => moment(item.publishedDate, 'DD/MM/YYYY').isSameOrAfter())
Одна из возможностей — использование вспомогательной функции notAfterToday
, которая принимает имя свойства (в нашем случае 'publishedDate'
) и возвращает функцию, которая принимает объект с этим именем свойства и сообщает, является ли эта дата предшествующей или текущей датой.
Он делает это путем преобразования, скажем, 18 декабря 2020 года в «20201218» и использует эту строку для сравнения. Обратите внимание, что одним из преимуществ этого является то, что конструктор Date вызывается только один раз для первоначального вычисления сегодняшней даты.
const data = [{publishedDate: '18/12/2020', Url: 'http://example.com/1', Title: 'abc'}, {publishedDate: '19/01/2021', Url: 'http://example.com/2', Title: 'def'}, {publishedDate: '07/04/2014', Url: 'http://example.com/3', Title: 'ghi'}, {publishedDate: '19/07/2023', Url: 'http://example.com/4', Title: 'jkl'}, {publishedDate: '05/01/1966', Url: 'http://example.com/5', Title: 'mno'}, {publishedDate: '01/07/2041', Url: 'http://example.com/6', Title: 'pqr'}, {publishedDate: '08/05/2061', Url: 'http://example.com/7', Title: 'stu'}, {publishedDate: '10/08/1999', Url: 'http://example.com/8', Title: 'vwx'}]
const notAfterToday = (prop) => {
const reorg = (date, [d, m, y] = date.split('/')) => y + m + d
const today = new Date()
const compare = today .getFullYear() +
String ((today .getMonth () + 1)) .padStart (2, '0') +
String (today .getDate ()) .padStart (2, '0')
return (d) => compare >= reorg (d [prop])
}
console .log (data .filter (notAfterToday ('publishedDate')))
.as-console-wrapper {max-height: 100% !important; top: 0}
new Date("19/01/2021")
возвращает:Invalid Date