UNPKG

lunisolar

Version:

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

267 lines (229 loc) 7.31 kB
import { LUNAR_UNITS_SET } from '../constants' import { parseDate, prettyUnit, computeSBMonthValueByTerm, getTranslation, computeUtcOffset, getDateData } from '../utils' import { dateDiff, lunarDateDiff } from '../utils/dateDiff' import { dateAdd } from '../utils/dateAdd' import { format } from '../utils/format' import { Lunar } from './lunar' import { SolarTerm } from './solarTerm' import { Char8 } from './char8' import { FIRST_YEAR, LAST_YEAR } from '../constants/lunarData' import { _GlobalConfig } from '../config' import { SB } from './stemBranch' import lunisolarFac from '../index' import { cache } from '../utils/decorators' import { CacheClass } from './CacheClass' import { Markers } from './markers' export class Lunisolar extends CacheClass { readonly _config: LunisolarConfigData readonly _date: Date readonly _offset: number constructor(date?: DateParamType, config?: lunisolar.ConfigType) { super() this._config = Object.assign({ extra: {} }, _GlobalConfig, config) const { isUTC, offset } = this._config const _date = parseDate(date, isUTC) if (offset !== 0) { _date.setMinutes(_date.getMinutes() + offset) } const localTimezoneOffset = -1 * parseDate(date).getTimezoneOffset() this._config.extra.localTimezoneOffset = localTimezoneOffset this._date = _date this._offset = offset } get lunisolar(): typeof lunisolar { return lunisolarFac } get year(): number { return getDateData(this._date, 'FullYear', this.isUTC()) } get month(): number { return getDateData(this._date, 'Month', this.isUTC()) + 1 } get day(): number { return getDateData(this._date, 'Date', this.isUTC()) } get dayOfWeek(): number { return getDateData(this._date, 'Day', this.isUTC()) } get hour(): number { return getDateData(this._date, 'Hours', this.isUTC()) } get minute(): number { return getDateData(this._date, 'Minutes', this.isUTC()) } get second(): number { return getDateData(this._date, 'Seconds', this.isUTC()) } get millis(): number { return getDateData(this._date, 'Milliseconds', this.isUTC()) } @cache('lunisolar:lunar') get lunar(): Lunar { return new Lunar(this._date, { lang: this._config.lang, isUTC: this.isUTC() }) } // 八字 @cache('lunisolar:char8') get char8(): Char8 { const config = { lang: this._config.lang, changeAgeTerm: this._config.changeAgeTerm, isUTC: this.isUTC(), offset: this._offset } return new Char8(this._date, config) } // markers @cache('lunisolar:markers') get markers(): Markers { return new Markers(this) } // 节气 @cache('lunisolar:solarTerm') get solarTerm(): SolarTerm | null { const year = this.year if (year < FIRST_YEAR || year > LAST_YEAR) { throw new Error(`${year} is not in the allowed time range.`) } const month = this.month const date = this.day const [term1, term2] = SolarTerm.getMonthTerms(year, month) const config = { lang: this._config.lang } if (date === term1) return new SolarTerm((month - 1) * 2, config) else if (date === term2) return new SolarTerm((month - 1) * 2 + 1, config) else return null } /** * 取得当前日期之前的最近的节气点 * @param nodeFlag 取的节气点,0: 取节, 1: 取气, 2: 节或气都取 */ @cache('lunisolar:recentSolarTerm', true) recentSolarTerm(nodeFlag: 0 | 1 | 2): [SolarTerm, Date] { return SolarTerm.findNode<false>(this._date, { lang: this._config.lang, nodeFlag, returnValue: false }) } /** * 取得當前日期所在的月建或月將地支, 月建:子月從0開始,月將:子月月將日到丑月月將日為0,類推 * @param flag 為0時取月建,為1時取月將 */ @cache('lunisolar:getMonthBuilder', true) getMonthBuilder(flag: 0 | 1 = 0): [SB, lunisolar.SolarTerm, Date] { const sbConfig = { lang: this.getConfig('lang') as string } const [term, termDate] = this.recentSolarTerm(flag) const sbValue = computeSBMonthValueByTerm(this.toDate(), term.value, termDate) const sb = new SB(sbValue, undefined, sbConfig) return [sb, term, termDate] } getSeasonIndex(): number { const rst = this.recentSolarTerm(0) const termVal = rst[0].value if (2 <= termVal && termVal < 8) return 0 if (8 <= termVal && termVal < 14) return 1 if (14 <= termVal && termVal < 20) return 2 return 3 } getSeason(isShortName: boolean = false): string { const ssv = this.getSeasonIndex() const locale = this.getLocale() return isShortName && locale.seasonShortName ? locale.seasonShortName[ssv] : locale.seasonName[ssv] } getLocale(lang?: string): LocaleData { return _GlobalConfig.locales[lang ?? this._config.lang] } L(key: keyof LocaleData): LocaleData[typeof key] L<T = any>(key: string): T | string { const locale = this.getLocale() return getTranslation<T, LocaleData>(locale, key) } getConfig(): LunisolarConfigData getConfig(key: keyof LunisolarConfigData): LunisolarConfigData[typeof key] getConfig(key?: keyof LunisolarConfigData): any { if (typeof key === 'undefined') return this._config if (typeof this._config[key]) return this._config[key] return undefined } toDate(): Date { return new Date(this.valueOf()) } clone() { return new Lunisolar(this.valueOf(), this._config) } unix() { return Math.floor(this.valueOf() / 1000) } valueOf() { return this._date.valueOf() - this._offset * 60 * 1000 } local() { const config = Object.assign({}, this._config, { isUTC: false, offset: 0 }) return new Lunisolar(this.toDate(), config) } utc(): Lunisolar { return this.utcOffset(-this._offset) } isUTC() { return this._config.isUTC } utcOffset(): number utcOffset(utcOffset: number): Lunisolar utcOffset(utcOffset?: number): number | Lunisolar { if (utcOffset === void 0) { if (this.isUTC()) return this._offset return computeUtcOffset(this._date) } const config = Object.assign({}, this._config, { isUTC: true, offset: Math.abs(utcOffset) <= 16 ? utcOffset * 60 : utcOffset }) return new Lunisolar(this._date, config) } toISOString() { return this._date.toISOString() } toUTCString() { return this._date.toUTCString() } toString() { return this._date.toUTCString() + ` (${this.lunar})` + ` utcOffset: ${this.utcOffset()}` } format(formatStr: string): string { return format(formatStr, this) } diff(date: DateParamType, unit?: Unit, float: boolean = false): number { unit = (unit ? prettyUnit(unit) : 'millisecond') as UnitFullNameLower if (LUNAR_UNITS_SET.has(unit)) { // 如果是农历查询 return lunarDateDiff( this, date instanceof Lunisolar ? date : new Lunisolar(date, this._config), unit as LunarUnit, float ) } return dateDiff(this._date, date, unit as GreUnit, float) } add(value: number, unit?: DateAddUnit): Lunisolar { const date = this.toDate() const newDate = dateAdd(date, value, unit) return new Lunisolar(newDate, this.getConfig()) } }