123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- import dayjs, { Dayjs, type ConfigType } from "../utils/dayjs";
- import { wrapDate } from '../utils'
- import {
- SOLAR_TERMS_C_NUMS,
- SOLAR_TERMS_DELTA,
- SOLAR_TERMS_MONTH,
- SOLAR_TERMS,
- type SolarTermKey,
- } from "./constants";
- /* 获取节气日期 */
- const getSolarTermDate = (
- year: number,
- month: number,
- term: SolarTermKey
- ): string => {
- const century = year >= 2000 ? 21 : 20;
- const Y = year % 100;
- const D = 0.2422;
- const C = SOLAR_TERMS_C_NUMS[term][century === 21 ? 1 : 0];
- let L = Math.floor(Y / 4);
- if (
- [
- "lesser_cold",
- "greater_cold",
- "the_beginning_of_spring",
- "rain_water",
- ].includes(term)
- ) {
- L = Math.floor((Y - 1) / 4);
- }
- let day = Math.floor(Y * D + C) - L;
- const delta = SOLAR_TERMS_DELTA[`${year}_${term}` as keyof typeof SOLAR_TERMS_DELTA];
- if (delta) {
- day += delta;
- }
- return dayjs(`${year}-${month}-${day}`).format('YYYY-MM-DD');
- };
- export interface SolarTerm {
- date: string;
- term: SolarTermKey;
- name: string;
- index?: number;
- };
- /**
- * 获取指定日期范围内的节气(仅节气当日)
- * @param start 开始日期
- * @param end 不传只查当天
- * @returns Array of solar terms => 节气开始日数组
- */
- const getSolarTerms = (
- start?: ConfigType,
- end?: ConfigType
- ): SolarTerm[] => {
- const result: SolarTerm[] = [];
- let current = wrapDate(start);
- const endDate = wrapDate(end || start);
- while (current.isBefore(endDate) || current.isSame(endDate)) {
- const year = current.year();
- const month = current.month() + 1;
- SOLAR_TERMS_MONTH[month].forEach((term: SolarTermKey) => {
- const solarTermDate = dayjs(getSolarTermDate(year, month, term));
- if (
- (solarTermDate?.isBefore(endDate) || solarTermDate?.isSame(endDate)) &&
- (solarTermDate?.isAfter(current) || solarTermDate?.isSame(current))
- ) {
- result.push({
- date: solarTermDate.format("YYYY-MM-DD"),
- term,
- name: SOLAR_TERMS[term],
- index: 1,
- });
- }
- });
- /* 处理下个日期 */
- month === 12
- ? (current = current.add(1, "year").startOf("year"))
- : (current = current.add(1, "month").startOf("month"));
- }
- return result;
- };
- /**
- * 获取指定日期范围内的所有每日节气信息
- * @param start 开始日期
- * @param end 不传只查当天
- * @returns Array of solar terms => 节气日数组
- */
- const getSolarTermsInRange = (
- start?: ConfigType,
- end?: ConfigType
- ): SolarTerm[] => {
- // 从开始日减一个月 - 结束日下一个月 计算所有节气
- let current = wrapDate(start).subtract(1, 'month');
- const endDate = wrapDate(end || start).add(1, 'month');
- const allTerms: { term: SolarTermKey, date: Dayjs }[] = []
- while (current.isBefore(endDate) || current.isSame(endDate)) {
- const year = current.year();
- const month = current.month() + 1;
- SOLAR_TERMS_MONTH[month].forEach((term: SolarTermKey) => {
- const solarTermDate = dayjs(getSolarTermDate(year, month, term));
- allTerms.push({ term, date: solarTermDate });
- });
- if (current.month() === 11) {
- current = current.add(1, 'year').startOf('year');
- } else {
- current = current.add(1, 'month').startOf('month');
- }
- }
- // 计算中间的所有日期
- const deltaDays: (Omit<SolarTerm, 'date'> & {day: Dayjs})[] = []
- allTerms.forEach((term, index) => {
- for (let date = term.date; allTerms[index + 1] && date.isBefore(allTerms[index + 1].date); date = date.add(1, 'day')) {
- deltaDays.push({ day: date, term: term.term, name: SOLAR_TERMS[term.term], index: date.diff(term.date, 'day') + 1 })
- }
- })
- if (!end) end = start
- return deltaDays.filter(trem => trem.day.isBetween(start, end, 'day')).map(trem => ({
- date: trem.day.format('YYYY-MM-DD'),
- term: trem.term,
- name: trem.name,
- index: trem.index
- }));
- };
- export {
- getSolarTermDate,
- getSolarTerms,
- getSolarTermsInRange,
- }
|