简体   繁体   English

将moment js给出的日期范围除以周

[英]Divide the date range given by moment js by weeks

I want to divide a given date range into months.我想将给定的日期范围划分为几个月。 And I want to separate these months according to weeks.我想将这些月份按周分开。 I want to get the date from the start date to the end of the month at 7-day intervals.我想以 7 天的间隔获取从开始日期到月底的日期。 For example: (Like 15/12/2020, 22/12/2020, 29/12/2020 -newMonth- 05/01/2020)例如:(如 15/12/2020、22/12/2020、29/12/2020 -newMonth- 05/01/2020)

It is difficult to understand with this explanation.这种解释很难理解。 After all I want to create a json like this.毕竟我想像这样创建一个 json。

Starting Date: 15/11/2020 - End Date: 20/01/2021开始日期:15/11/2020 - 结束日期:20/01/2021

[
  {
    "dates": [
      15, // Starting date(15/11/2020)
      22, // 1 week later
      29 // 1 week later
    ],
    "firstDay": "15/11/2020"
  },
    {
    "dates": [
      6,
      13,
      20,
      27
    ],
    "firstDay": "06/12/2020"
  },
  {
    "dates": [
      3,
      10,
      17
    ],
    "firstDay": "03/01/2021"
  }
]

There are a few tricks that you can use to create the array structure you want:您可以使用一些技巧来创建所需的数组结构:

  1. Use a while loop, which keeps a current date that is constantly incremented by 7 days, to be compared against the end date.使用while循环保持current日期不断增加 7 天,以便与end日期进行比较。 The current date should be initialized using the start date in the beginning of the loop. current日期应使用循环开始时的start日期进行初始化。
  2. To perform the "group by month" in your desired structure, you will need to using an object (which serves as a dictionary).要在所需结构中执行“按月分组”,您需要使用 object(用作字典)。 The object will use the month + year combination as key, so that if your date ranges span over multiple years you won't collapse months from different years into the same entry. object 将使用month + year组合作为键,这样如果您的日期范围跨越多年,您就不会将不同年份的月份折叠到同一个条目中。

For each iteration of the while loop, you construct the key from the current date, and then check if the key exists in your dictionary.对于while循环的每次迭代,您从当前日期构造键,然后检查该键是否存在于您的字典中。 If not, then we can push this object into your dictionary:如果没有,那么我们可以将这个 object 推送到您的字典中:

{
  dates: [currentDate],
  firstDate: currentDate
}

If it already exists, then you simply push the date into the dates array of the sub-object.如果它已经存在,那么您只需将日期推送到子对象的dates数组中。

Finally, to convert your dictionary into the array strcuture you wanted, using ES6 Object.values() will work.最后,要将您的字典转换为您想要的数组结构,使用 ES6 Object.values()将起作用。 See proof-of-concept below:请参阅下面的概念验证:

 function generateRanges(startDate, endDate) { let current = moment(startDate, 'DD/MM/YYYY'); const end = moment(endDate, 'DD/MM/YYYY'); // A dictionary to track unique month+year combinations const daysByMonth = {}; while (current < end) { // Construct key based on month+year const key = `${current.month()}${current.year()}`; const date = current.date(); // If key already exists, then we push into the `dates` array if (key in daysByMonth) { daysByMonth[key].dates.push(date); } // Otherwise we construct a brand new sub-object else { daysByMonth[key] = { dates: [date], // Since this is the first time we encounter the key, // We can assume this is the earliest/first date of the month firstDate: current.format('DD/MM/YYYY') } } // At the end of the while loop, increment by a week, rinse and repeat current.add(7, 'days'); } // Once done, we only want the values in the dictionary // We don't need to keep the unique month+year key return Object.values(daysByMonth); } const range = generateRanges('15/11/2020', '20/01/2021'); console.log(range);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>

When dealing with date or datetime is always a good practice to use milliseconds.在处理日期或日期时间时,使用毫秒总是一个好习惯。 Also it is space efficient, a long integer = 4kb instead of a Date() object which is 32bytes.它还节省空间,长 integer = 4kb 而不是 Date() object 32 字节。

In your case it is very straightforward to convert our dates to milliseconds, find how many weeks are between as integer and then run a loop increment by this iteration.在您的情况下,将我们的日期转换为毫秒非常简单,找到 integer 之间的周数,然后通过此迭代运行循环增量。

let from = new Date('2020/11/15').getTime();
let to = new Date('2021/01/20').getTime();
let week = 604800000;
let day = 86400000;
let allWeeks = [];
let current =0;

let weeks = (to-from)/day/7

for (i=0; i<weeks; i++){
  allWeeks.push(new Date(from += week).toLocaleDateString())
}

console.log(JSON.stringify(allWeeks))
//["22/11/2020","29/11/2020","06/12/2020","13/12/2020","20/12/2020","27/12/2020","03/01/2021","10/01/2021","17/01/2021","24/01/2021"]

Finally you will have a list applicable for JSON to build any logic you prefer.最后,您将有一个适用于 JSON 的列表来构建您喜欢的任何逻辑。

I hope to pin point a differed approach to your case!我希望为您的案例指出不同的方法!

The Moment.JS has an API for adding days to a date: the add function. Moment.JS 有一个 API 用于向日期添加天数:添加function。

In order to build your final object, you would start from your startDate, and add 7 days for each loop iteration until reaching the end date.为了构建最终的 object,您将从 startDate 开始,并为每个循环迭代添加 7 天,直到到达结束日期。 Like this:像这样:

let currentDate = moment(startDate);

while(currentDate < endDate) { // Make sure endDate is also a moment object
  // Add the current date - you will want to adapt this
  dates.push(currentDate.clone()); // Since .add() will mutate the currentDate object, clone the object when adding it to the array so that it's not affected by the add()
  // Prepare for the next iteration
  currentDate.add({days: 7});
}

As for month changes, remember the last month for every iteration (use month ) and create a new object in your final array, then add dates to object instead of the previous one.至于月份更改,请记住每次迭代的最后一个月(使用月份)并在最终数组中创建一个新的 object,然后将日期添加到 object 而不是上一个。

Side note : Months are zero-indexed in Javascript, which is not the case for the month day ( date )旁注:月份在 Javascript 中为零索引,而月份日期(日期)不是这种情况

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM