Henry Henry
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)

Henry

小学生中的前端大佬
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)
  • JavaScript

    • js 编码指南
    • 日期使用斜杠 点 中划线分隔的不同
    • forEach 会改变原数组值吗
    • 前端表单验证常用的正则表达式 - reg
    • JS 如何取得 URL 里的参数
    • JavaScript 数组去重
    • JavaScript 循环中断研究与总结-关键字篇
    • JavaScript 循环中断研究与总结-用法篇
    • js 中的 Error
    • 跳出 forEach
    • Location 对象
    • Date 方法预览
    • Reg 正则中的问题
    • JavaScript toFixed() 方法
    • query 和 params 的使用区别
    • axios post 请求中下载文件流
    • 实用的 js 技巧
    • JS 之数组的几个不 low 操作
    • 深入浅出深拷贝与浅拷贝
    • 如何实现一个深拷贝
    • 使用 iframe 中的一些问题
    • 在 js 中更好地使用数组
    • echarts 在坐标轴两侧各增加一格坐标
    • 从头认识js的事件循环模型
    • moment 根据周截至日算出指定月有几周及开始结束日期
      • 需求
      • 开发环境
      • 修改 moment 周起始日
      • 通过 weekday 计算
    • 正则 reg 中 /number 的用法
    • 正则 reg 中 match 和 exec 异同
  • TypeScript

  • Vue

  • ElementUI

  • React

  • AntD

  • 前端
  • JavaScript
Henry
2022-06-10
目录

moment 根据周截至日算出指定月有几周及开始结束日期

# 需求

最近遇到这么一个需求:

用户可以指定每周的截止日,包含截至日当天。如:截至日为周日,则每个周期都是:周一 ~ 周日;截至日为周四,则每个周期都是上周五 ~ 本周四

如上图,截至日为周日,则 6 月的周期为:

  • 5.30~6.5
  • 6.6~6.12
  • 6.13~6.19
  • 6.20~6.26

由于 6.27~7.3 的结束日已不在 6 月,故不属于 6 月的周期

截至日为周四,则 6 月的周期为:

  • 5.27~6.2
  • 6.3~6.9
  • 6.10~6.16
  • 6.17~6.23
  • 6.24~6.30

# 开发环境

开发环境:"react": "^17.0.2", "moment": "^2.29.1", "antd": "^4.18.8",

# 修改 moment 周起始日

一开始的想法是当用户设置截至日后,更改 moment 的周起始日(值为截至日的后一天,如截至日为周日,则起始日为周一),这样我们就不需要计算了,moment 帮我们计算好了,我们只需要获取该月的周期即可,结果发现修改是全局的,别的日期组件的周起始日都改变了,这种肯定是不可以的,当然如果你的需求就是这样的,那其实就可以了

moment 不同版本修改周起始日不同,可以参考这里 (opens new window)

// 从 2.12.0 开始
moment.updateLocale('zh-cn', {
  week: {
    dow: weekEnd // Locale#week.dow 应是代表星期中第一天的整数,1 是星期一、2 是星期二、...、7 是星期日
  }
})
1
2
3
4
5
6

由于我们使用的是中文日期,周起始日为周一,dow 为 1,而由于周起始日为截至日的后一天,故对应的截至日为周日,所以周日的值为 1,以此类推可以得出:

const weekEndOptions = '日一二三四五六'.split('').map((item, index) => ({
  label: `星期${item}`,
  value: ++index
}))
1
2
3
4

当周截至日改变后,就需要执行一下上面的代码,更新周起始日

接下来就是获取当前月有几周及其对应的开始结束日期了,主要思路就是先获取月第一周第一天,然后循环加 7 天,直到结束日期不在本月为止

主要代码:

const cycleChart = '一二三四五六' // 月第几周期
moment.updateLocale('zh-cn', {
  week: {
    dow: weekEnd // 周截至日
  }
})
const year = monthValue.year() // monthValue: antd 月份组件获取的值
const month = monthValue.month()
// moment([year, month]): 设置为 年月第一天 0 时 0 分 0 秒,startOf('week') 获取第一周第一天
let start = moment([year, month]).startOf('week')
const result = []
let index = 0
loop()
function loop() {
  const end = moment(start) // 这里使用 moment(start) 是因为 add/subtract 会改变原值
    .add(7, 'd')
    .subtract(1, 's')
  if (end.month() === month) {
    result.push({
      label: `第${cycleChart.charAt(index)}周期(${start.format('MM-DD')}~${end.format('MM-DD')})`,
      time: [moment(start), end],
      value: index
    })
    start.add(7, 'd')
    loop()
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 通过 weekday 计算

主要思路就是通过 weekEnd 获取当月第一周周 weekEnd 的日期,比如 weekEnd 为周日,则 6 月第一周周日是 6.5,weekEnd 为周二,则 6 月第一周周二为 5.31;获取的这个日期是每周期的结束日期,故需要判断该日期的月份是否等于当前月,如果小于,则需要加 7 天,如果等于,则计入周期,也需要判断年份

然后循环加 7 天,直到结束日期不在本月为止

const year = monthValue.year()
const month = monthValue.month()
let end = moment([year, month])
  .weekday(weekEnd)
  .add(1, 'd')
  .subtract(1, 's')
const result = []
let index = 0
loop()
function loop() {
  if (end.month() < month || end.year() < year) {
    end.add(7, 'd')
    loop()
  } else if (end.month() === month) {
    const start = moment(end)
      .subtract(7, 'd')
      .add(1, 's')
    result.push({
      label: `第${cycleChart.charAt(index)}周期(${start.format('MM-DD')}~${end.format('MM-DD')})`,
      time: [start, moment(end)],
      value: index
    })
    end.add(7, 'd')
    index++
    loop()
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
编辑 (opens new window)
#moment#antd#React
上次更新: 5/27/2023, 1:02:05 PM
从头认识js的事件循环模型
正则 reg 中 /number 的用法

← 从头认识js的事件循环模型 正则 reg 中 /number 的用法→

最近更新
01
version 1.15
07-01
02
version 1.14
06-27
03
version 1.13
06-27
更多文章>
Theme by Vdoing | Copyright © 2017-2023 HenryTSZ | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式