javascript - 在 momentjs 中查找每 5 天的连续日期

标签 javascript date momentjs

我有一个日历,用户必须在其中标记日期 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< 时,我才需要向用户显示本地通知 对象。

因此,我们假设用户在 2018-01-10 开始标记(所有 4 个点),当时他标记了所有 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,但我不知道如何检查所有日期是否连续且不包含 null。这是一个很难解决的问题!

最佳答案

我假设您使用的是日期格式 YYYY-DD-MM。 (以前没见过)

我的方法是首先对列表进行排序并删除任何带有空点的内容,因为它们无论如何都不会被视为连续天。然后,我们从最小日期开始,浏览列表并检查自上次输入以来是否已经过去了一天。当有 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>

希望这能解决您的问题。

关于javascript - 在 momentjs 中查找每 5 天的连续日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52597805/

相关文章:

javascript - 表单提交两次(ajax 和 jquery)

javascript - javascript中使用prompt()方法初始化变量时,初始化变量的类型是什么?

javascript - 石头、剪刀、布增量分数不起作用,有人可以告诉我我做错了什么吗?

php - 如何使用mysql按月获取值的总和

javascript - HH :MM with Moment. js(或没有)的小时数

php - 可以使用Javascript从其他网站获取数据吗?

php - Mysql 使用 where in 子句查找日期,或最接近数组中日期的日期

日期算术 : Cassandra 4

javascript - Momentjs 弃用错误和不同的浏览器功能

javascript - 使用 moment.js 检查当天不会在新的一天更新