Найти последовательные даты каждые 5 дней в моментах - PullRequest
0 голосов
/ 01 октября 2018

У меня есть календарь, в котором пользователь должен отмечать дату 4 раза.Предположим, что за каждый день пользователь может пометить и вернуть следующий объект:

{
 date: '2018-01-10',
 dots: [{
         color: 'blue',
         key: 'markOne'
        }, 
        {
         color: 'red',
         key: 'markTwo'
        },
        {
         color: 'black',
         key: 'markThree'
        }, 
        {
         color: 'yellow',
         key: 'markFour'
        }
       ] 
},
{
 date: '2018-02-10',
 dots: [{
         color: 'blue',
         key: 'markOne'
        }, 
        {
         color: 'red',
         key: 'markTwo'
        },
        {
         color: 'black',
         key: 'markThree'
        }, 
        {
         color: 'yellow',
         key: 'markFour'
        }
       ]
},
{
 date: '2018-03-10',
 dots: [{
         color: 'blue',
         key: 'markOne'
        }, 
        {
         color: 'blue',
         key: 'markTwo'
        },
        {
         color: 'black',
         key: 'markThree'
        }, 
        null
       ]
},
{...day4},
{...day5 and so on}

Мне нужно показывать локальное уведомление пользователю, только если date подряд в течение 5 дней и только если dots не имеет null объекта.

Итак, давайте предположим, что пользователь начал отмечать (все 4 точки) с 2018-01-10, когда он отмечает все 4 точки до 2018-05-10, тогда локальное уведомление должно бытьпоказано (это еще одна логика, которую я уже реализовал).

Если даты последовательные, но в массиве dots есть хотя бы один null, тогда он не должен отправлять уведомление.

Даты следует разбивать каждые 5 дней, поэтому каждый 5,10,15,20,25,30 месяца должно отображаться другое уведомление:

const notificationsEveryFiveDays = [
 {day5: 'day 5 notification'},
 {day10: 'day 10 notification'},
 {day15: 'day15 notification'},
 {day20: 'day20 notification'},
 {day25: 'day25 notification'},
 {day30: 'day 30 notification'}
];

Пока мне удалось получить вседаты и манипулировать ключами объекта, чтобы вернуть отсортированный по дате массив.

export const MarkedDates = () => {
  MyStorage.getItem('markedDates').then((items) => {
    if (items) {
        let dates = _.map(items, (val, id) => {
            return {...val, date: id};
        });
        let sortedDates = _.sortBy(dates, 'date');
        console.log(sortedDates);
    }
});

};

Я пытаюсь использовать moment-range, но не могу понять, как проверить, все ли dates последовательны, а dots нетсодержат null.Это сложная проблема для решения!

1 Ответ

0 голосов
/ 02 октября 2018

Я предполагаю, что вы используете формат даты ГГГГ-ДД-ММ.(раньше такого не видел)

Мой подход состоит в том, чтобы сначала отсортировать список и удалить что-либо с нулевыми точками, так как они все равно не считаются последовательными днями.После этого мы начинаем с минимального дня, просматриваем список и проверяем, прошел ли один день с момента последней записи.Если есть 5 последовательных дней, добавьте список последовательных дней в последовательный массив.

const dates = [
{
 date: '2018-02-10',
 dots: [{color: 'yellow', key: 'markFour' } ]
},
{
 date: '2018-01-10',
 dots: [ { color: 'yellow', key: 'markFour' } ] 
},
{
 date: '2018-03-10',
 dots: [{ color: 'black', key: 'markThree' }]
},
{
  date: '2018-04-10',
  dots: [{color: "blue", key: 'markOne'}]
},
{
  date: '2018-05-10',
  dots: [{color: "blue", key: 'markOne'}]
}]

// if there is a null then do nothing. Let get that check out of the way first
const dotsHasNull = dates.filter(pair => (pair.dots.filter(dot => dot == null) ).length).length != 0


const sortedDates = dates.map(pair => { 
  // convert date to moment date to use the diff function later
  return {date: moment(pair.date, "YYYY-DD-MM"), dots: pair.dots} 
})
.filter( (pair) => {
	// filter out all days that contain null dots 
	// this is done to handle a case where days 1-7 are consecutive but day 1 contain a null dot, which would discard the entire range 
	// we want it to create a range from 2-7 instead.
	return pair.dots.filter(dot => dot == null).length == 0
	// Maybe you want it to discard the entire range if the range contains a dot, then move this check to after we have found the ranges.
})
.sort((a,b) => a.date.valueOf() - b.date.valueOf() ) // there are probably more efficient sorting methods:)


var consecutivePairs = [];

var currentConsecutive = [];

sortedDates.forEach(pair => {
  if (currentConsecutive.length == 0) {
    currentConsecutive.push(pair)
    return
  }
  const lastConsecutivePair = currentConsecutive[currentConsecutive.length -1];
  // as long as only one day has passed then keep adding to the list
  if (pair.date.diff(lastConsecutivePair.date, 'days') == 1) {
	  currentConsecutive.push(pair)
  } else {
	  // start with an array containing the current pair because otherwise we might skip some days
	  currentConsecutive = [pair];
  }
  if (currentConsecutive.length == 5) {
	  // when we have a range that is atleast 5 days long that add it to 
	consecutivePairs.push(currentConsecutive)
  }
})

consecutivePairs.forEach(consecutive => {
	// sounds like you have some specific requirements for the the notification
	// so you probably have to replace this

	// find every 5 days
	const mark = consecutive.length - (consecutive.length % 5)
	console.log("consecutive days notifications: ", "day " + mark + " notification");
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.js"></script>

Надеюсь, это решит вашу проблему.

...