需求 展示从本月初开始 一年的时间 或N年的时间 以便用户选择
思路 一年12个月 是已知的 从本月到12月可以生成本年的每天数据
从1月至上月可以生成所需得到最后一年的数据
今年加最后一年的月份可拼接一年时间 所以中间年份是所需年分-1的数组数据
中间年份都是1-12月 可以通过年份加1获取今年至N年的每天数据
效果图
下面是方法的分解 在最后会提供一个完整的demo
- 获取本月至年末的 以月划分 每日时间
let date = new Date() //获取当前时间
let [currentYear, currentMonth] = [date.getFullYear(), date.getMonth() + 1] //获取当前年 月
//一年为12月 用月份减去当前月+1 为今年所剩余的月份 生成与月份相同长度的数组 存储每月天数
let current_year = new Array(12 - currentMonth + 1).fill({}).map((item, index) => {
return {
year: currentYear,
month: index + currentMonth,
days: this.setDays(currentYear, index + currentMonth)
}
})
//setDays 通过获取月份天数生成与天数相同长度的数组 存储每天的时间戳 及相关数据 返回生成的数组
//参数year,month需要获取每月天数的年和月
this.setDays = function(year, month) {
return new Array(new Date(year, month, 0).getDate()).fill({}).map((v, i) => {
return {
time_stamp: parseInt(new Date(year, month, i + 1).getTime() / 1000),
day: i + 1,
check: false,
}
})
}
- 获取最后一年 年初至结束月份 每日时间
//一年为12月 当前月份减1 为最后一年所需的月份长度 生成与月份相同长度的数组 存储每月天数
//this.config.year 为所要获取的年数 加上当前年及为最后1年年份
let last_year = new Array(currentMonth - 1).fill({}).map((item, index) => {
return {
year: currentYear + this.config.year,
month: index + currentMonth,
days: this.setDays(currentYear + this.config.year, index + currentMonth)
}
})
- 获取本年和最后一年的中间年份每日数据 因为不确定是需要几年 所以这里要生成一个二维数组 以便存储
//this.config.year 所需年数
// 所需年数 this.config.year-1 是需要减去本年和最后一年拼接出来的一年
//生成年数-1长度的数组 数组中为12个月的基础数据
//循环月份的数组生成月份对应的每日数据
let middle_year = new Array(this.config.year - 1).fill([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]).map((item, index) => {
return new Array(item.length).fill({}).map((v, k) => {
return {
year: currentYear + index + 1,
month: k + 1,
days: this.setDays(currentYear + index + 1, k + 1)
}
})
})
- 合并本年中间年和最后一年数据
//因中间年为二维数组 所以需要展开一下 才能拼接
this.TIME_ARRAY = [...current_year, ...middle_year.flat(Infinity), ...last_year]
console.log(this.TIME_ARRAY) //这里可以看到生成的数据
- 数据渲染
//获取日期对应的星期
this.setWeek = function(time) {
let dayArr = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
if (time.toString().length < 13) time = time * 1000
return dayArr[new Date(time).getDay()]
}
//循环渲染数据
this.setHtml = function() {
$(this.config.el).html(
`
${this.TIME_ARRAY.map(item=>{
return `<div class="section">
<div class="time-title">${item.year+'年'+item.month}月 <span class="select-all ${item.days.every(k=>k.check==true)?'allActive':''}" data-id="${item.year+'_'+item.month}">全选</span></div>
<div class="time-box">
<ul>
${item.days.map(v=>{
return `<li class="${v.check?'active':''}" data-id="${item.year+'_'+item.month+'_'+v.day}">
<div>${this.setWeek(v.time_stamp)}</div>
<div>${v.day}日</div>
</li>`
}).join('')}
</ul>
</div>
</div>`
}).join('')}
`
)
}
//执行方法渲染数据
this.setHtml()
以下是完整的demo
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
* {
padding: 0;
margin: 0;
list-style: none;
box-sizing: border-box;
}
.content {
max-width: 60%;
margin: 0 auto;
padding-top: 30px;
}
.section {
padding-bottom: 20px;
}
.time-title {
font-size: 18px;
color: #333;
font-weight: bold;
cursor: pointer;
}
.time-box {
margin-top: 10px;
padding: 10px;
border: 1px solid #ccc;
}
.time-box ul {
display: grid;
grid-template-columns: repeat(7, 1fr);
column-gap: 10px;
row-gap: 10px;
}
.time-box ul li {
padding: 5px 0;
text-align: center;
border: 1px solid #ccc;
border-radius: 4px;
cursor: pointer;
}
.time-box ul li div:first-child {
font-size: 12px;
color: #999;
}
.time-box ul li.active {
background: seagreen;
color: #fff;
}
.allActive {
color: aqua;
}
</style>
</head>
<body>
<div class="content">
</div>
</body>
<script src="https://cdn.staticfile.org/jquery/3.6.3/jquery.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
function createDateTime(options) {
this.config = {
el: options.el,
year: options.year || 1,
}
this.TIME_ARRAY = []
this.create = function() {
let date = new Date()
let [currentYear, currentMonth] = [date.getFullYear(), date.getMonth() + 1]
let current_year = new Array(12 - currentMonth + 1).fill({}).map((item, index) => {
return {
year: currentYear,
month: index + currentMonth,
days: this.setDays(currentYear, index + currentMonth)
}
})
let middle_year = new Array(this.config.year - 1).fill([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]).map((item, index) => {
return new Array(item.length).fill({}).map((v, k) => {
return {
year: currentYear + index + 1,
month: k + 1,
days: this.setDays(currentYear + index + 1, k + 1)
}
})
})
let last_year = new Array(currentMonth - 1).fill({}).map((item, index) => {
return {
year: currentYear + this.config.year,
month: index + currentMonth,
days: this.setDays(currentYear + this.config.year, index + currentMonth)
}
})
this.TIME_ARRAY = [...current_year, ...middle_year.flat(Infinity), ...last_year]
this.setHtml()
}
this.setDays = function(year, month) {
return new Array(new Date(year, month, 0).getDate()).fill({}).map((v, i) => {
return {
time_stamp: parseInt(new Date(year, month, i + 1)
.getTime() / 1000),
day: i + 1,
check: false,
}
})
}
this.setWeek = function(time) {
let dayArr = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
if (time.toString().length < 13) time = time * 1000
return dayArr[new Date(time).getDay()]
}
this.setHtml = function() {
$(this.config.el).html(
`
${this.TIME_ARRAY.map(item=>{
return `<div class="section">
<div class="time-title">${item.year+'年'+item.month}月 <span class="select-all ${item.days.every(k=>k.check==true)?'allActive':''}" data-id="${item.year+'_'+item.month}">全选</span></div>
<div class="time-box">
<ul>
${item.days.map(v=>{
return `<li class="${v.check?'active':''}" data-id="${item.year+'_'+item.month+'_'+v.day}">
<div>${this.setWeek(v.time_stamp)}</div>
<div>${v.day}日</div>
</li>`
}).join('')}
</ul>
</div>
</div>`
}).join('')}
`
)
}
this.getCheckDays=function(){
let arr=[]
this.TIME_ARRAY.forEach(item=>{
item.days.forEach(v=>{
if(v.check){
arr.push(v)
}
})
})
return arr
}
$(this.config.el).on('click', 'li', (event) => {
let el = $(event.target)
if (el[0].localName == 'div') {
el = el.parent()
}
let [year, month, day] = el.attr('data-id').split('_')
this.TIME_ARRAY = this.TIME_ARRAY.map(item => {
if (item.year == year && item.month == month) {
item.days = item.days.map(v => {
if (v.day == day) {
v.check = !v.check
}
return v
})
}
return item
})
this.setHtml()
})
$(this.config.el).on('click', '.select-all', (event) => {
let el = $(event.target)
let [year, month] = el.attr('data-id').split('_')
let flag = el.hasClass('allActive')
this.TIME_ARRAY = this.TIME_ARRAY.map(item => {
if (item.year == year && item.month == month) {
item.days = item.days.map(v => {
v.check = !flag
return v
})
}
return item
})
this.setHtml()
})
}
let daysFn = new createDateTime({
el: '.content',
})
daysFn.create()
console.log(daysFn.getCheckDays())
</script>
</html>