@marchingy/lunar
Version:
Chinese calendar with the 24 solar terms.
123 lines (122 loc) • 5.88 kB
JavaScript
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "ephemeris", "./tool", "./intl", "./lunar-calendar"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTermsOnYear = exports.countSolarTerms = exports.getTermOnDay = exports.calcDiffOfSunAndMoon = exports.calcSunEclipticLongitude = exports.calcMoonEclipticLongitude = exports.create24SolarTerms = exports.SolarTerm = void 0;
const ephemeris_1 = require("ephemeris");
const tool_1 = require("./tool");
const intl_1 = require("./intl");
const lunar_calendar_1 = require("./lunar-calendar");
/**
* @description GB/T 33661-2017 农历的编算和颁行
* @link http://c.gb688.cn/bzgk/gb/showGb?type=online&hcno=E107EA4DE9725EDF819F33C60A44B296
*/
class SolarTerm {
constructor(order, label) {
this.label = label;
this.toString = () => {
var _a;
return `${this.label}` + (this.date ? ` ${(_a = this.date) === null || _a === void 0 ? void 0 : _a.toChineseString()}` : ``);
};
if (order < 1 || order > 24 || order % 1 !== 0) {
throw new Error(`Illegal parameter "order": ${order}, this must be an integer from 1 to 24.`);
}
this.order = order;
this.longitude = (order - 1) * 15;
}
isMidTerm() {
return this.longitude % 30 === 0;
}
static create(index, lang = intl_1.SOLAR_TERMS_ZH) {
return new SolarTerm((0, tool_1.coerceInteger)(index), lang[index - 1]);
}
}
exports.SolarTerm = SolarTerm;
function create24SolarTerms(lang = intl_1.SOLAR_TERMS_ZH) {
const terms = new Map();
for (let i = 1; i <= 24; i++) {
terms.set(i, SolarTerm.create(i, lang));
}
return terms;
}
exports.create24SolarTerms = create24SolarTerms;
function calcMoonEclipticLongitude(targetDate, coordinate = intl_1.CH_STANDARD_POSITION) {
return (0, ephemeris_1.getPlanet)('moon', targetDate, coordinate[0], coordinate[1], 0).observed.moon.apparentLongitudeDd;
}
exports.calcMoonEclipticLongitude = calcMoonEclipticLongitude;
;
function calcSunEclipticLongitude(targetDate, coordinate = intl_1.CH_STANDARD_POSITION) {
return (0, ephemeris_1.getPlanet)('sun', targetDate, coordinate[0], coordinate[1], 0).observed.sun.apparentLongitudeDd;
}
exports.calcSunEclipticLongitude = calcSunEclipticLongitude;
;
function calcDiffOfSunAndMoon(time, coordinate = intl_1.CH_STANDARD_POSITION) {
const sunResult = calcSunEclipticLongitude(time, coordinate);
const moonResult = calcMoonEclipticLongitude(time, coordinate);
return Math.min(Math.abs(sunResult - moonResult), Math.abs(sunResult - (moonResult - 360)), Math.abs((sunResult - 360) - moonResult), Math.abs((sunResult - 360) - (moonResult - 360)));
}
exports.calcDiffOfSunAndMoon = calcDiffOfSunAndMoon;
function getTermOnDay(date, coordinate = intl_1.CH_STANDARD_POSITION) {
const dateS = new Date(date.getFullYear(), date.getMonth(), date.getDate());
const dateE = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59);
let eclipticLngS = (0, tool_1.toPrecision)(calcSunEclipticLongitude(dateS, coordinate), 3);
const eclipticLngE = (0, tool_1.toPrecision)(calcSunEclipticLongitude(dateE, coordinate), 3);
let result = null;
let x = Math.floor(eclipticLngE); // An integer;
if (eclipticLngS > eclipticLngE) {
eclipticLngS = eclipticLngS - 360;
}
do {
if (x % 15 === 0 && eclipticLngS <= x && eclipticLngE >= x) {
const index = x / 15 + 1;
if (index >= 1 && index <= 24) {
result = SolarTerm.create(index);
result.date = new lunar_calendar_1.ChineseDate(date);
break;
}
}
x--;
} while (x > eclipticLngS);
return result;
}
exports.getTermOnDay = getTermOnDay;
function countSolarTerms(fromDate, toDate, coordinate = intl_1.CH_STANDARD_POSITION) {
const terms = [];
let startDate;
let endDate;
let target;
if (fromDate.getTime() <= toDate.getTime()) {
startDate = new Date(fromDate.getFullYear(), fromDate.getMonth(), fromDate.getDate());
endDate = new Date(toDate.getFullYear(), toDate.getMonth(), toDate.getDate());
}
else {
startDate = new Date(toDate.getFullYear(), toDate.getMonth(), toDate.getDate());
endDate = new Date(fromDate.getFullYear(), fromDate.getMonth(), fromDate.getDate());
}
do {
target = getTermOnDay(startDate, coordinate);
if (target) {
terms.push(target);
startDate.setDate(startDate.getDate() + 13);
continue;
}
startDate.setDate(startDate.getDate() + 1);
} while (startDate.getTime() <= endDate.getTime());
return terms;
}
exports.countSolarTerms = countSolarTerms;
/**
* This method will countSolarTerms with params that are the first date and the latest date of the year.
*/
function getTermsOnYear(year, coordinate = intl_1.CH_STANDARD_POSITION) {
return countSolarTerms(new Date(year, 0, 1, 0, 0, 0, 0), new Date(year, 11, 31, 23, 59, 59, 999), coordinate);
}
exports.getTermsOnYear = getTermsOnYear;
});