jm-mrc-components
Version:
移动端可复用组件库
184 lines (168 loc) • 3.87 kB
text/typescript
import { solarToLunar } from 'chinese-lunar'
import memoize from 'lodash/memoize'
export const holidays = {
// 新历假日
gregorian: {
'1-1': '元旦',
'2-14': '情人节',
'3-8': '妇女节',
'5-1': '劳动节',
'5-4': '青年节',
'6-1': '儿童节',
'7-1': '建党节',
'8-1': '建军节',
'9-10': '教师节',
'10-1': '国庆节',
// 动态节日(节气都是动态节日,暂时不展示)
// '4-4': '清明节',
// '12-22': '冬至',
// '6-22': '夏至',
'12-25': '圣诞节',
},
lunar: {
'12-8': '腊八',
'12-29-leap': '除夕',
'12-30': '除夕',
'1-1': '春节',
'1-15': '元宵节',
'5-5': '端午节',
'7-7': '七夕',
'8-15': '中秋节',
'9-9': '重阳节',
},
byWeek: {
'5-2-0': '母亲节',
// 六月第三个星期日
'6-3-0': '父亲节',
},
}
/**
* 获取节假日
*/
export default function getHoliday(date: Date) {
const gregorian = `${date.getMonth() + 1}-${date.getDate()}`
if (gregorian in holidays.gregorian) {
return holidays.gregorian[gregorian]
}
// 动态节日
const dynamicHolidays = getDynamicHoliday(date.getFullYear())
if (gregorian in dynamicHolidays) {
return dynamicHolidays[gregorian]
}
for (let key in holidays.byWeek) {
const [month, week, day] = key.split('-').map(i => parseInt(i))
if (month !== date.getMonth() + 1) {
continue
}
if (day !== date.getDay()) {
continue
}
const holiday = getNthWeek(date, week, day)
if (holiday.getDate() === date.getDate()) {
return holidays.byWeek[key]
}
}
// 农历节假日
const lunar = solarToLunar(date)
let lunarKey = `${lunar.month}-${lunar.day}`
if (lunar.leap && lunar.month === 12) {
lunarKey += '-leap'
}
return holidays.lunar[lunarKey]
}
export const getDynamicHoliday = memoize((year: number) => {
let result: { [key: string]: string } = {}
try {
// const dongzhi = getDongzhiForYear(year)
// result[`12-${dongzhi}`] = '冬至'
const qingming = getQingMingForYear(year)
result[`4-${qingming}`] = '清明'
} catch {
// ignore
}
return result
})
export function getDongzhiForYear(year: number) {
if (year == 2767) {
return 23
}
if (year == 2227 || year == 3068) {
return 22
}
if (year < 1700) {
throw new TypeError('1700年以前暂时不支持')
}
if (year >= 3100) {
throw new TypeError('3100年以后暂时不支持')
}
const coefficient = [
22.11,
22.39,
22.66,
21.9,
22.18,
22.472,
22.72,
21.995,
22.27,
22.51,
22.75,
22.02,
22.27,
22.519,
22.8,
]
const mod = year % 100
const index = Math.trunc(year / 100 - 17)
return Math.trunc(mod * 0.2422 + coefficient[index] - Math.trunc(mod / 4))
}
export function getQingMingForYear(year: number) {
if (year == 2231) {
return 23
}
if (year == 2227 || year == 3068) {
return 22
}
if (year < 1700) {
throw new TypeError('1700年以前暂时不支持')
}
if (year >= 3100) {
throw new TypeError('3100年以后暂时不支持')
}
const coefficient = [
5.15,
5.37,
5.59,
4.82,
5.02,
5.26,
5.48,
4.7,
4.92,
5.135,
5.36,
4.6,
4.81,
5.04,
5.26,
]
const mod = year % 100
const index = Math.trunc(year / 100 - 17)
return Math.trunc(mod * 0.2422 + coefficient[index] - Math.trunc(mod / 4))
}
/**
* 获取当月第N个星期*
*/
export function getNthWeek(date: Date, n: number, day: number) {
const copy = new Date(date)
copy.setDate(1)
let firstDay = copy.getDay()
// first week end
if (firstDay > day) {
copy.setDate(1 + 7 - (firstDay - day))
} else {
copy.setDate(1 + (day - firstDay))
}
copy.setDate(copy.getDate() + (n - 1) * 7)
return copy
}