@baby_2023

Как отсортировать массив по дате в формате от и до?

Привет хабр, как возможно отсортировать массив в котором имеется статическая дата по методу от и до?
Я попробовал получить разницу в днях, между двумя датами для сортировки и пустить их в цикл и в цикле конвертировать индекс дня в дату начиная от даты который указана в сортировке типа "от", но ничего не вышло, так как получается двумерный цикл и данные обрабатываются в некорректном порядке.

К примеру мы имеем массив который содержит внутри себя 10 элементов с разными датами, к примеру от 2022-04-01 до до 2022-04-10, юзер хочет отсортировать эти данные по дате с 2022-04-02 по 2022-04-07.
  • Вопрос задан
  • 149 просмотров
Решения вопроса 2
ThunderCat
@ThunderCat Куратор тега PHP
{PHP, MySql, HTML, JS, CSS} developer
1) Зависит от формата даты. пример массива не помешает. так же как и вариант "такое хочу получить".
2) Если данные получены из бд, правильным ответом будет добавить сортировку в запрос.
Ответ написан
gzhegow
@gzhegow
aka "ОбнимиБизнесмена"
Не понимаю, если хочешь просто по дате сортировать по убыванию, то функция

$dates = [];
for ($i = 0; $i < 10; $i++) {
    $dates[] = new DateTime('now +' . $i . 'days');
}

usort($dates,function ($a, $b) {
    return null
        ?? ( $b < $a ? -1 : null )
        ?? ( $b > $a ? 1 : null )
        ?? 0;
});

var_dump($dates);


делает, что сказали.

====

Если твоя задача сортировать массив по возрастанию РАЗНИЦЫ дат, то нужно так:

$dates = [];
for ($i = 0; $i < 10; $i++) {
    $dates[] = [
        new DateTime('now +' . $i . 'days'),
        new DateTime('now +' . $i+$i . 'days')
    ];
}

usort($dates,function ($a, $b) {
    $diffA = $a[1]->getTimestamp() - $a[0]->getTimestamp();
    $diffB = $b[1]->getTimestamp() - $b[0]->getTimestamp();
	
    return null
        ?? ( $diffA < $diffB ? -1 : null )
        ?? ( $diffA > $diffB ? 1 : null )
        ?? 0;
});

var_dump($dates);


Помнить, что на getTimestamp() влияет временная зона. То есть 2 часа по Гринвичу меньше чем 2 часа по Москве, это как бы понятно, просто здесь тоже это важно.

====

Третий вариант, который "возможно" ты хотел получить здесь - как определить пересечение дат:

# опционально, можно донастраивать с помощью знаков `<=` `>=`, чтоб получить "включая-исключая"
# и оператора NOT, чтобы инвертировать.
# можно играться с оператором OR вместо AND, но это уровень 2, тебе не надо
# ещё есть кейз "вне моего промежутка", который можно получить AND двух имеющихся или NOT для "внутри промежутка"

# дай промежутки, которые помещаются в мои рамки
# '2022-01-02 00:00:00' < date_from < date_to < '2022-01-04 00:00:00'
# |----------|
#    |----|
# AND `date_from` > '2022-01-02 00:00:00'
# AND `date_to` < '2022-01-04 00:00:00'
# вернуло бы [ '2022-01-03 00:00:00', '2022-01-03 00:00:00' ]

# дай промежутки, которые пересекаются с моим только началом
# '2022-01-02 00:00:00' < date_from < '2022-01-04 00:00:00' < date_to
# |------|
#     |------|
# AND `date_from` > '2022-01-02 00:00:00'
# AND `date_to` > '2022-01-04 00:00:00'
# вернуло бы [ '2022-01-03 00:00:00', '2022-01-05 00:00:00' ]

# дай промежутки, которые пересекаются с моим только концом
# date_from < '2022-01-02 00:00:00' < date_to < '2022-01-04 00:00:00'
#    |------|
# |------|       
# AND `date_from` < '2022-01-02 00:00:00'
# AND `date_to` < '2022-01-04 00:00:00'
# вернуло бы [ '2022-01-01 00:00:00', '2022-01-03 00:00:00' ]

# дай промежутки, которые шире моих рамок (рамка внутри промежутка и потому пересечения нет, пересечение целиком)
# date_from < '2022-01-02 00:00:00' < '2022-01-04 00:00:00' < date_to
#    |----|
# |----------|
# AND `date_from` < '2022-01-02 00:00:00'
# AND `date_to` > '2022-01-04 00:00:00'
# вернуло бы [ '2022-01-01 00:00:00', '2022-01-05 00:00:00' ]


Чаще всего задача звучит "найдите все пересечения сразу", чтобы убедится, что туда можно что-то еще добавить и оно не закосячит потом. Поэтому и начинают играться с OR чтобы не писать NOT ( AND / AND / AND / AND )

Вот тут есть уровень 2 и 3 и тд.
www.michurin.net/computer-science/boolean-logic.html
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Если я правильно понял проблему, то это можно сделать в два действия: отсортировать весь массив по дате, а потом взять из него кусочек в соответствии с вашими "от", "до"
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы