如何通过JS将多个时间段合并并提取出所有不重叠的时间段?
- 内容介绍
- 文章标签
- 相关推荐
本文共计927个文字,预计阅读时间需要4分钟。
javascriptimport dayjs from 'dayjs';// dayjs 是一个用于格式化时间的库,也可用于其他用途
// 示例:将字符串转换为格式化的日期时间const inputDate='2021-12-25';const formattedDate=dayjs(inputDate).format('YYYY-MM-DD HH:mm:ss');console.log(formattedDate);
原创文章。转载请注明原链接:www.cnblogs.com/justif/p/16266861.html 或直接使用npm库。github地址:github.com/Petter-li/lxways
import dayjs from 'dayjs'; // 一个用来格式化时间的库,也可用其他代替
//根据时间开始结束日期,生成连续的时间数组(以天为单位)
export function makeDateBetweenArr(startDate, endDate) {
let dates = [];
const theDate = new Date(startDate);
while (theDate < new Date(endDate)) {
dates = [...dates, dayjs(new Date(theDate)).format('YYYY-MM-DD')];
theDate.setDate(theDate.getDate() + 1);
}
dates = [...dates, dayjs(new Date(theDate)).format('YYYY-MM-DD')];
return dates;
}
// 快速排序
export function hurryShift(arr) {
if (arr.length === 1 || arr.length === 0) {
return arr;
}
let fix = arr[0];
let left = [];
let right = [];
for(let i = 1; i< arr.length; i++) {
if(arr[i] <= fix) {
left.push(arr[i]);
}
if(arr[i] > fix) {
right.push(arr[i]);
}
}
return hurryShift(left).concat([fix],hurryShift(right));
}
// 算法:根据多个起止时间段日期,凡是有日期重叠的时间段都要合并,得出一个或多个时间段
export function calculateDates(arr) {
// 根据起止日期,把时间段补全为每一天组成的时间段
const dates = arr.map(item => makeDateBetweenArr(item.startDate, item.endDate));
// 把所有时间段的每一天push到一个数组里
const allDates = [];
dates.forEach(item => allDates.push(...item));
// 把数组去重,日期相同的天数去重
if(allDates.length === 0) {
return [];
}
const onlyDates = Array.from(new Set(allDates));
// 每天转化为时间戳,进行快速排序,时间早的放前面
const times = onlyDates.map(item => new Date(item).getTime());
const orderTimes = hurryShift(times);
// 算法核心:根据相邻日期的时间戳差值是否大于一天的毫秒数判断日期是否连续,不连续则为新的时间段的起止日期
// 把起止日期push到一个数组里,数组长度必为偶数
const temp = [];
if(orderTimes.length === 1) {
temp.push(...[orderTimes[0],orderTimes[0]]);
}else {
orderTimes.forEach((item, index) => {
if(index === 0) {
temp.push(dayjs(item).format('YYYY-MM-DD'));
}else {
if(item -orderTimes[index - 1] > 86400000) {
temp.push(orderTimes[index - 1]);
temp.push(dayjs(item).format('YYYY-MM-DD'));
}
if(index === orderTimes.length - 1) {
temp.push(dayjs(item).format('YYYY-MM-DD'));
}
}
})
}
// 把结果数组根据每2个的长度截断为新的数组,第一个值为时间段的开始日期,第二个为结束日期
let result = [];
if(temp.length > 0) {
let index = 0;
let resIndex = 0;
result = new Array(Math.ceil(temp.length / 2));
while(index < temp.length) {
result[resIndex++] = temp.slice(index ,(index+=2))
}
}
return result;
};
// 示例
calculateDates([
{startDate: '2022-05-12', endDate: '2022-05-25'},
{startDate: '2022-05-15', endDate: '2022-05-30'},
{startDate: '2022-06-15', endDate: '2022-06-20'},
{startDate: '2022-06-10', endDate: '2022-06-25'},
])
// 结果:
本文共计927个文字,预计阅读时间需要4分钟。
javascriptimport dayjs from 'dayjs';// dayjs 是一个用于格式化时间的库,也可用于其他用途
// 示例:将字符串转换为格式化的日期时间const inputDate='2021-12-25';const formattedDate=dayjs(inputDate).format('YYYY-MM-DD HH:mm:ss');console.log(formattedDate);
原创文章。转载请注明原链接:www.cnblogs.com/justif/p/16266861.html 或直接使用npm库。github地址:github.com/Petter-li/lxways
import dayjs from 'dayjs'; // 一个用来格式化时间的库,也可用其他代替
//根据时间开始结束日期,生成连续的时间数组(以天为单位)
export function makeDateBetweenArr(startDate, endDate) {
let dates = [];
const theDate = new Date(startDate);
while (theDate < new Date(endDate)) {
dates = [...dates, dayjs(new Date(theDate)).format('YYYY-MM-DD')];
theDate.setDate(theDate.getDate() + 1);
}
dates = [...dates, dayjs(new Date(theDate)).format('YYYY-MM-DD')];
return dates;
}
// 快速排序
export function hurryShift(arr) {
if (arr.length === 1 || arr.length === 0) {
return arr;
}
let fix = arr[0];
let left = [];
let right = [];
for(let i = 1; i< arr.length; i++) {
if(arr[i] <= fix) {
left.push(arr[i]);
}
if(arr[i] > fix) {
right.push(arr[i]);
}
}
return hurryShift(left).concat([fix],hurryShift(right));
}
// 算法:根据多个起止时间段日期,凡是有日期重叠的时间段都要合并,得出一个或多个时间段
export function calculateDates(arr) {
// 根据起止日期,把时间段补全为每一天组成的时间段
const dates = arr.map(item => makeDateBetweenArr(item.startDate, item.endDate));
// 把所有时间段的每一天push到一个数组里
const allDates = [];
dates.forEach(item => allDates.push(...item));
// 把数组去重,日期相同的天数去重
if(allDates.length === 0) {
return [];
}
const onlyDates = Array.from(new Set(allDates));
// 每天转化为时间戳,进行快速排序,时间早的放前面
const times = onlyDates.map(item => new Date(item).getTime());
const orderTimes = hurryShift(times);
// 算法核心:根据相邻日期的时间戳差值是否大于一天的毫秒数判断日期是否连续,不连续则为新的时间段的起止日期
// 把起止日期push到一个数组里,数组长度必为偶数
const temp = [];
if(orderTimes.length === 1) {
temp.push(...[orderTimes[0],orderTimes[0]]);
}else {
orderTimes.forEach((item, index) => {
if(index === 0) {
temp.push(dayjs(item).format('YYYY-MM-DD'));
}else {
if(item -orderTimes[index - 1] > 86400000) {
temp.push(orderTimes[index - 1]);
temp.push(dayjs(item).format('YYYY-MM-DD'));
}
if(index === orderTimes.length - 1) {
temp.push(dayjs(item).format('YYYY-MM-DD'));
}
}
})
}
// 把结果数组根据每2个的长度截断为新的数组,第一个值为时间段的开始日期,第二个为结束日期
let result = [];
if(temp.length > 0) {
let index = 0;
let resIndex = 0;
result = new Array(Math.ceil(temp.length / 2));
while(index < temp.length) {
result[resIndex++] = temp.slice(index ,(index+=2))
}
}
return result;
};
// 示例
calculateDates([
{startDate: '2022-05-12', endDate: '2022-05-25'},
{startDate: '2022-05-15', endDate: '2022-05-30'},
{startDate: '2022-06-15', endDate: '2022-06-20'},
{startDate: '2022-06-10', endDate: '2022-06-25'},
])
// 结果:

