比如用户选择开始日期2022-01-15和结束日期2022-10-20,然后按月度分段,则会返回分段后的日期范围:
[
{startDate:2022-01-15, endDate:2022-01-31},
{startDate:2022-02-01, endDate:2022-02-28},
{startDate:2022-03-01, endDate:2022-03-31},
// ......
{startDate:2022-10-01, endDate:2022-10-20},
]
比如用户选择开始日期2022-01-15和结束日期2022-10-20,然后按月度分段,则会返回分段后的日期范围:
[
{startDate:2022-01-15, endDate:2022-01-31},
{startDate:2022-02-01, endDate:2022-02-28},
{startDate:2022-03-01, endDate:2022-03-31},
// ......
{startDate:2022-10-01, endDate:2022-10-20},
]
import dayjs from 'dayjs'
const getDateRange = (start, end) => {
start = dayjs(start)
end = dayjs(end)
if (! start.isBefore(end)) [start, end] = [end, start] // 确保 start 在 end 前面
const range = []
let startDate = start, endDate
while (! (startDate.isSame(end, 'month') && startDate.isSame(end, 'year'))) { // 到和最后一个日期同月份的时候就可以结束了
endDate = startDate.endOf('month') // 到月末结束
range.push({ startDate, endDate })
startDate = endDate.add(1, 'day') // 月末的下一天是月初
}
range.push({ startDate, endDate: end }) // 把最后一段加上
return range
}
function getDateRangeByMonth(start,end) {
const s = new Date(start);
const e = new Date(end);
const range = [];
while(s <= e) {
const startDate = s.toISOString().slice(0,10)
// 到结束日期月份,直接结束循环
if(s.getFullYear()==e.getFullYear()&&s.getMonth()==e.getMonth()) {
range.push({startDate, endDate: end})
break;
}
// 获取月份最后一天分两步,一:月份加1;二:setDate参数为0则为上一月最后一天
// 由于月份天数不一致,当当前月份的日期超过下一个月的日期,月份加1会溢出等同于加2,如当前2022-01-31,setMonth加1时会变成3月,所以这里先setDate至1
s.setDate(1)
s.setMonth(s.getMonth()+1)
s.setDate(0)
range.push({
startDate,
endDate: s.toISOString().slice(0,10)
})
// push后,天数加1则回到下一月的头一天
s.setDate(s.getDate()+1)
}
return range;
}
getDateRangeByMonth('2022-01-15','2022-10-20')
针对评论所说的情况做了修改
js
代码function f(start, end) {
let ranges = []
let [i, j] = [start, end].map(i => new Date(i)).sort((a, b) => a - b)
while (i <= j) {
const startDate = i.toISOString().slice(0, 10)
i = new Date(i.getFullYear(), i.getMonth() + 1, 0, i.getHours())
const endDate = new Date(Math.min(+i, +j)).toISOString().slice(0, 10)
i.setDate(i.getDate() + 1)
ranges.push({startDate, endDate})
}
return ranges
}
f('2022-01-15','2022-10-20')
[
{"startDate": "2022-01-15", "endDate": "2022-01-31"},
{"startDate": "2022-02-01", "endDate": "2022-02-28"},
{"startDate": "2022-03-01", "endDate": "2022-03-31"},
{"startDate": "2022-04-01", "endDate": "2022-04-30"},
{"startDate": "2022-05-01", "endDate": "2022-05-31"},
{"startDate": "2022-06-01", "endDate": "2022-06-30"},
{"startDate": "2022-07-01", "endDate": "2022-07-31"},
{"startDate": "2022-08-01", "endDate": "2022-08-31"},
{"startDate": "2022-09-01", "endDate": "2022-09-30"},
{"startDate": "2022-10-01", "endDate": "2022-10-20"}
]
我这边是借助了第三方库dayjs完成。
思路是:取值每一个月份的月底日期,完成一次分段的取值,借助月底日期计算下一次的初始日期
import dayjs from "dayjs"
const getMonthBySub = (start,end) => {
// 标准输入月份字符串
let lastMonth = dayjs(start);
const endMonth = dayjs(end);
const subMonth = []; // 分段月份存放
do {
const startDate = lastMonth.format("YYYY-MM-DD");
// 计算一个月的月底日期 28 29 30 31
const endDate = dayjs(lastMonth.endOf('month').format("YYYY-MM-DD"));// endof 会取值到59分59秒 导致while里面比较出错 统一格式
// 计算下一个lastMoth
lastMonth = endDate.add(1, "day"); // eg: 2022-01-31 => 2022-02-01
const endDateMonth = lastMonth <= endMonth ? endDate : endMonth;
subMonth.push({startDate, endDate: endDateMonth.format("YYYY-MM-DD")});
}while(lastMonth <= endMonth )
console.log(subMonth)
return subMonth
}
getMonthBySub('2022-01-15', '2022-10-20')
getMonthBySub('2022-01-01', '2023-01-03')
getMonthBySub('2022-01-01', '2022-01-03')
function changeDate(val) {
return +(val.split('-').join('').slice(0, -2))
}
function getDate(val) {
let y = val.split('-')[0] // 2022
let m = val.split('-')[1] // 01
let d = val.split('-')[2] // 15
return {y, m, d}
}
function date(start, end) {
let {y, m, d} = getDate(start)
let list = []
let obj = {startDate: start, endDate: `${y}-${m}-${new Date(y, m, 0).getDate()}`}
while ((list.length && changeDate(list[list.length - 1].startDate)) < changeDate(end)) {
list = [...list, obj]
let {y: y1, m: m1, d: d1} = getDate(list[list.length - 1].startDate)
obj = {startDate: `${++m1 <= 12 ? y1 : ++y1}-${(m1 <= 12 ? m1 < 10 ? '0' + m1 : m1 : m1 = 1 && '01')}-01`, endDate: `${y1}-${(m1 < 10 ? '0' + +m1 : m1)}-${new Date(y1, m1, 0).getDate()}`}
}
list[list.length - 1].endDate = end
return list
}
console.log(date('2022-01-15', '2024-02-20'))
27 回答13k 阅读
8 回答3.5k 阅读✓ 已解决
6 回答1.3k 阅读✓ 已解决
5 回答5.3k 阅读✓ 已解决
4 回答1.6k 阅读✓ 已解决
3 回答1.7k 阅读
4 回答2.3k 阅读✓ 已解决
之所以不用
toISOString().slice(0, 10)
要自己写format
,是因为下图的原因用迭代的办法确实代码要短好多
iterate 的 mBegin 和 end 之所以重新生成,一个是下图时区的原因。另一个,需要去除输入 Date 对象的时间部分(万一有呢)