UNPKG

lunisolar

Version:

专业农历库,支持公历阴历互转,支持各类黄历数据查询,如八字四柱、阴历、神煞宜忌、时辰吉凶、建除十二神、胎神占方、五行纳音等。支持自定义插件。

185 lines (176 loc) 5.52 kB
import { UNITS } from '../constants' import { LUNAR_MONTH_DATAS, FIRST_YEAR } from '../constants/lunarData' import { parseDate, prettyUnit } from './index' /** * 計算兩日期的時間差 * @param date1 起始日期 * @param date2 結束日期 * @param unit 單位 * @param float 是否返回小數 * @returns {nnumber} */ export function dateDiff( date1: DateParamType, date2: DateParamType, unit?: GreUnit, float?: boolean ): number { ;[date1, date2] = [parseDate(date1), parseDate(date2)] const diffValue = date2.valueOf() - date1.valueOf() unit = (unit ? prettyUnit(unit) : 'millisecond') as GreUnitFullName let res = diffValue if (UNITS.s === unit) { res = diffValue / 1000 } else if (UNITS.m === unit) { res = diffValue / (1000 * 60) } else if (UNITS.h === unit) { res = diffValue / (1000 * 60 * 60) } else if (UNITS.d === unit) { res = diffValue / (1000 * 60 * 60 * 24) } else if (UNITS.w === unit) { res = diffValue / (1000 * 60 * 60 * 24 * 7) } else if (UNITS.M === unit) { res = monthDiff(date1, date2) } else if (UNITS.y === unit) { res = monthDiff(date1, date2) / 12 } else if (UNITS.q === unit) { res = monthDiff(date1, date2) / 3 } return float ? res : parseInt(String(res)) } /** * 月差 * @param date1 日期1 * @param date2 日期2 * @returns {number} */ export const monthDiff = (date1: DateParamType, date2: DateParamType): number => { ;[date1, date2] = [parseDate(date1), parseDate(date2)] const yearDiff = date2.getFullYear() - date1.getFullYear() const monthDiff = date2.getMonth() - date1.getMonth() const diffValue = yearDiff * 12 + monthDiff // 取得月差 // 下边计算小数部分 const anchor = new Date(date1).setMonth(date1.getMonth() + diffValue) const c = anchor.valueOf() > date2.valueOf() const anchor2 = new Date(date1).setMonth(date1.getMonth() + diffValue + (c ? -1 : 1)) return ( diffValue + (date2.valueOf() - anchor.valueOf()) / (c ? anchor - anchor2 : anchor2 - anchor) || 0 ) } /** * 計算陰歷的時間差 * @param lsr1 起始日 * @param lsr2 結束日 * @returns {number} */ export const lunarDateDiff = ( lsr1: lunisolar.Lunisolar, lsr2: lunisolar.Lunisolar, unit?: LunarUnit, float?: boolean ): number => { const [lunar1, lunar2] = [lsr1.lunar, lsr2.lunar] const [year1, year2] = [lunar1.year, lunar2.year] let diff = lsr2.valueOf() - lsr1.valueOf() unit = prettyUnit(unit) as LunarUnitFullNameLower if (unit === UNITS.ly) { const diff = year2 - year1 return float ? diff - 1 + getYearDecimals(lsr1, true) + getYearDecimals(lsr2, false) : diff } else if (unit === UNITS.lM) { return lunarMonthDiff(lsr1, lsr2, float) } else if (unit === UNITS.ld) { diff = diff / (1000 * 60 * 60 * 24) } else if (unit === UNITS.lh) { diff = diff / (1000 * 60 * 60 * 2) } return float ? diff : Math.ceil(diff) } /** * 計算陰歷的月差 * @param lsr1 起始日 * @param lsr2 結束日 * @returns {number} */ export const lunarMonthDiff = ( lsr1: lunisolar.Lunisolar, lsr2: lunisolar.Lunisolar, float?: boolean ): number => { if (lsr1 > lsr2) return -lunarMonthDiff(lsr2, lsr1) const [lunar1, lunar2] = [lsr1.lunar, lsr2.lunar] const [year1, year2] = [lunar1.year, lunar2.year] const [month1, month2] = [lunar1.month, lunar2.month] let currYear = year1 let cnt = 0 while (currYear <= year2) { let [start, end] = [1, 12] if (currYear === year1) start = month1 if (currYear === year2) end = month2 cnt += countLunarMonthInYear(currYear, start, end) currYear++ } if (!float) return cnt - 1 // 計算小數部分 if (cnt > 0) { cnt += getMonthDecimals(lsr1, true) + getMonthDecimals(lsr2, false) - 2 } else { const monthLen = lunar1.isBigMonth ? 30 : 29 cnt = (lsr2.valueOf() - lsr1.valueOf()) / (1000 * 60 * 60 * 24 * monthLen) } return cnt } /** * 計算該年有多少個月 */ export const countLunarMonthInYear = (year: number, start?: number, end?: number): number => { const monthData = LUNAR_MONTH_DATAS[year - FIRST_YEAR] LUNAR_MONTH_DATAS start = start || 1 end = end || 12 let addLeap = false if (start > 100) { start -= 100 addLeap = true } if (end > 100) { end -= 100 addLeap = true } const leapMonth = monthData >> 13 if (start <= leapMonth && leapMonth <= end) addLeap = true return end - start + 1 + (addLeap ? 1 : 0) } /** * 用于計算陰歷月差的小數部分 * @param lsr 日期 * @param isAfterPath 是否后半部分 * @returns {number} */ export const getMonthDecimals = ( lsr: lunisolar.Lunisolar, isAfterPath: boolean = false ): number => { const monthDayLen = lsr.lunar.isBigMonth ? 30 : 29 const day = lsr.lunar.day return isAfterPath ? 1 - day / monthDayLen : day / monthDayLen } /** * 用于計算陰歷年差的小數部分 * @param lsr 日期 * @param isAfterPath 是否后半部分 * @returns {number} */ export const getYearDecimals = (lsr: lunisolar.Lunisolar, isAfterPath: boolean = false): number => { const leapMonth = lsr.lunar.leapMonth const yearMonthLen = leapMonth > 0 ? 13 : 12 let isLeapMonth = false let month = lsr.lunar.month if (month > 100) { month -= 100 isLeapMonth = true } if (leapMonth > 0 && (month > leapMonth || (month === leapMonth && isLeapMonth))) month++ const md = getMonthDecimals(lsr, isAfterPath) return isAfterPath ? 1 - (month - md) / yearMonthLen : (month + md - 1) / yearMonthLen }