1
0
mirror of synced 2026-04-15 21:08:40 +08:00

Compare commits

..

4 Commits

6 changed files with 239 additions and 91 deletions

View File

@@ -177,3 +177,7 @@ test('test11', () => {
expect(eightChar.getDay()).toBe('庚子');
expect(eightChar.getTime()).toBe('戊子');
});
test('test12', () => {
expect(Solar.fromYmdHms('1999', '06', '07', '09', '11', '00').getLunar().getEightChar().toString()).toBe('己卯 庚午 庚寅 辛巳');
});

View File

@@ -590,3 +590,53 @@ test('test058', () => {
const lunar = Lunar.fromYmd(1582, 9, 19);
expect(lunar.getSolar().toString()).toBe('1582-10-15');
});
test('test059', () => {
const lunar = Lunar.fromYmd(1518, 1, 1);
expect(lunar.getSolar().toString()).toBe('1518-02-10');
});
test('test060', () => {
const lunar = Lunar.fromYmd(793, 1, 1);
expect(lunar.getSolar().toString()).toBe('0793-02-15');
});
test('test061', () => {
const lunar = Lunar.fromYmd(2025, -6, 1);
expect(lunar.getSolar().toString()).toBe('2025-07-25');
});
test('test062', () => {
const lunar = Lunar.fromYmd(2025, 6, 1);
expect(lunar.getSolar().toString()).toBe('2025-06-25');
});
test('test063', () => {
const lunar = Lunar.fromYmd(193, 1, 1);
expect(lunar.getSolar().toString()).toBe('0193-02-19');
});
test('test064', () => {
const lunar = Lunar.fromYmd(288, 1, 1);
expect(lunar.getSolar().toString()).toBe('0288-02-19');
});
test('test065', () => {
const lunar = Lunar.fromYmd(755, 1, 1);
expect(lunar.getSolar().toString()).toBe('0755-02-16');
});
test('test066', () => {
const lunar = Lunar.fromYmd(41, 1, 1);
expect(lunar.getSolar().toString()).toBe('0041-02-20');
});
test('test067', () => {
const lunar = Lunar.fromYmd(57, 1, 1);
expect(lunar.getSolar().toString()).toBe('0057-02-23');
});
test('test068', () => {
const lunar = Lunar.fromYmd(345, 1, 1);
expect(lunar.getSolar().toString()).toBe('0345-02-18');
});

View File

@@ -92,3 +92,18 @@ test('test18', () => {
const year = LunarYear.fromYear(2022);
expect(year.getJieQiJulianDays()).toStrictEqual([2459555.7478605337, 2459570.499405936, 2459585.217980813, 2459599.9437018055, 2459614.7018054826, 2459629.5297495862, 2459644.446920318, 2459659.4814200983, 2459674.6389274267, 2459689.9334118855, 2459705.3512322665, 2459720.890569021, 2459736.517794922, 2459752.2178259823, 2459767.9429320656, 2459783.6713957503, 2459799.3534378354, 2459814.969435438, 2459830.480632029, 2459845.8774438635, 2459861.140466851, 2459876.2746654437, 2459891.281458942, 2459906.1807667296, 2459920.9903281447, 2459935.741672728, 2459950.461561025, 2459965.187040542, 2459979.9460747372, 2459994.7736723446, 2460009.6916930582]);
});
test('test19', () => {
const year = LunarYear.fromYear(2021);
expect(year.getDayCount()).toBe(354);
});
test('test20', () => {
const year = LunarYear.fromYear(2023);
expect(year.getDayCount()).toBe(384);
});
test('test21', () => {
const year = LunarYear.fromYear(1517);
expect(year.getDayCount()).toBe(384);
});

View File

@@ -92,3 +92,45 @@ test('19', () => {
})
expect(timeList).toStrictEqual(['2020-07-21 22:00:00', '1960-08-05 22:00:00']);
});
test('20', () => {
const solar = Solar.fromYmd(1582, 10, 4);
expect(solar.nextDay(1).toYmd()).toBe('1582-10-15');
});
test('21', () => {
const solar = Solar.fromYmd(1582, 10, 15);
expect(solar.nextDay(-1).toYmd()).toBe('1582-10-04');
});
test('22', () => {
const solar = Solar.fromYmd(1582, 10, 15);
expect(solar.nextDay(-5).toYmd()).toBe('1582-09-30');
});
test('23', () => {
const solarList = Solar.fromBaZi('癸卯', '甲寅', '癸丑', '甲子', 2, 1843);
const timeList = [];
solarList.forEach(solar => {
timeList.push(solar.toYmdHms());
})
expect(timeList).toStrictEqual(['2023-02-24 23:00:00', '1843-02-08 23:00:00']);
});
test('24', () => {
const solarList = Solar.fromBaZi('己亥', '丁丑', '壬寅', '戊申');
const timeList = [];
solarList.forEach(solar => {
timeList.push(solar.toYmdHms());
})
expect(timeList).toStrictEqual(['1960-01-15 16:00:00', '1900-01-29 16:00:00']);
});
test('25', () => {
const solarList = Solar.fromBaZi('己亥', '丙子', '癸酉', '庚申');
const timeList = [];
solarList.forEach(solar => {
timeList.push(solar.toYmdHms());
})
expect(timeList).toStrictEqual(['1959-12-17 16:00:00']);
});

217
lunar.js
View File

@@ -128,27 +128,32 @@
isAfter: function(solar) {
if (this._p.year > solar.getYear()) {
return true;
} else if (this._p.year < solar.getYear()) {
}
if (this._p.year < solar.getYear()) {
return false;
}
if (this._p.month > solar.getMonth()) {
return true;
} else if (this._p.month < solar.getMonth()) {
}
if (this._p.month < solar.getMonth()) {
return false;
}
if (this._p.day > solar.getDay()) {
return true;
} else if (this._p.day < solar.getDay()) {
}
if (this._p.day < solar.getDay()) {
return false;
}
if (this._p.hour > solar.getHour()) {
return true;
} else if (this._p.hour < solar.getHour()) {
}
if (this._p.hour < solar.getHour()) {
return false;
}
if (this._p.minute > solar.getMinute()) {
return true;
} else if (this._p.minute < solar.getMinute()) {
}
if (this._p.minute < solar.getMinute()) {
return false;
}
return this._p.second > solar.getSecond();
@@ -156,27 +161,32 @@
isBefore: function(solar) {
if (this._p.year > solar.getYear()) {
return false;
} else if (this._p.year < solar.getYear()) {
}
if (this._p.year < solar.getYear()) {
return true;
}
if (this._p.month > solar.getMonth()) {
return false;
} else if (this._p.month < solar.getMonth()) {
}
if (this._p.month < solar.getMonth()) {
return true;
}
if (this._p.day > solar.getDay()) {
return false;
} else if (this._p.day < solar.getDay()) {
}
if (this._p.day < solar.getDay()) {
return true;
}
if (this._p.hour > solar.getHour()) {
return false;
} else if (this._p.hour < solar.getHour()) {
}
if (this._p.hour < solar.getHour()) {
return true;
}
if (this._p.minute > solar.getMinute()) {
return false;
} else if (this._p.minute < solar.getMinute()) {
}
if (this._p.minute < solar.getMinute()) {
return true;
}
return this._p.second < solar.getSecond();
@@ -334,12 +344,7 @@
if (2 === m) {
if (d > 28) {
if (!SolarUtil.isLeapYear(y)) {
d -= 28;
m++;
if (m > 12) {
m = 1;
y++;
}
d = 28;
}
}
}
@@ -356,8 +361,7 @@
if (isNaN(months)) {
throw new Error('wrong months ' + om);
}
var month = SolarMonth.fromYm(this._p.year, this._p.month);
month = month.next(months);
var month = SolarMonth.fromYm(this._p.year, this._p.month).next(months);
var y = month.getYear();
var m = month.getMonth();
var d = this._p.day;
@@ -365,12 +369,7 @@
if (2 === m) {
if (d > 28) {
if (!SolarUtil.isLeapYear(y)) {
d -= 28;
m++;
if (m > 12) {
m = 1;
y++;
}
d = 28;
}
}
}
@@ -390,33 +389,36 @@
var y = this._p.year;
var m = this._p.month;
var d = this._p.day;
if (1582 === y && 10 === m) {
if (d > 4) {
d -= 10
}
}
if (days > 0) {
d = this._p.day + days;
d += days;
var daysInMonth = SolarUtil.getDaysOfMonth(y, m);
while (d > daysInMonth) {
d -= daysInMonth;
m++;
if (m > 12) {
m -= 12;
m = 1;
y++;
}
daysInMonth = SolarUtil.getDaysOfMonth(y, m);
}
} else if (days < 0) {
var rest = -days;
while (d <= rest) {
rest -= d;
while (d + days <= 0) {
m--;
if (m < 1) {
m = 12;
y--;
}
d = SolarUtil.getDaysOfMonth(y, m);
d += SolarUtil.getDaysOfMonth(y, m);
}
d -= rest;
d += days;
}
if (1582 === y && 10 === m) {
if (d > 4 && d < 15) {
if (d > 4) {
d += 10;
}
}
@@ -502,10 +504,15 @@
var _fromBaZi=function(yearGanZhi,monthGanZhi,dayGanZhi,timeGanZhi,sect,baseYear){
sect *= 1;
if(isNaN(sect)){
sect=2;
sect = 2;
}
if (1 !== sect) {
sect = 2;
}
baseYear *= 1;
if(isNaN(baseYear)){
baseYear = 1900;
}
sect = (1===sect)?1:2;
baseYear = (undefined===baseYear)?1900:baseYear;
var l = [];
var years = [];
var today = _fromDate(new Date());
@@ -514,27 +521,42 @@
offsetYear += 60;
}
var startYear = today.getYear() - offsetYear - 1;
while (startYear >= baseYear) {
var minYear = baseYear - 2;
while (startYear >= minYear) {
years.push(startYear);
startYear -= 60;
}
var hour = 0;
var hours = [];
var timeZhi = timeGanZhi.substr(1);
for(var i=0,j=LunarUtil.ZHI.length;i<j;i++){
var i = 1;
var j = LunarUtil.ZHI.length;
for(;i<j;i++){
if(LunarUtil.ZHI[i]===timeZhi){
hour = (i-1)*2;
hours.push((i-1)*2);
break;
}
}
for (var i = 0, j = years.length; i < j; i++) {
inner:for (var x = 0; x < 3; x++) {
var year = years[i] + x;
var solar = _fromYmdHms(year, 1, 1, hour, 0, 0);
while (solar.getYear() === year) {
if ('子' === timeZhi) {
hours.push(23);
}
j = years.length;
for (var m = 0, n = hours.length; m < n; m++) {
for (i = 0;i < j; i++) {
var y = years[i];
var maxYear = y + 3;
var year = y;
var month = 11;
if (year < baseYear) {
year = baseYear;
month = 1;
}
var solar = _fromYmdHms(year, month, 1, hours[m], 0, 0);
while (solar.getYear() <= maxYear) {
var lunar = solar.getLunar();
var dgz = (2===sect)?lunar.getDayInGanZhiExact2():lunar.getDayInGanZhiExact();
if (lunar.getYearInGanZhiExact()===yearGanZhi && lunar.getMonthInGanZhiExact()===monthGanZhi && dgz===dayGanZhi && lunar.getTimeInGanZhi()===timeGanZhi) {
var dgz = (2 === sect) ? lunar.getDayInGanZhiExact2() : lunar.getDayInGanZhiExact();
if (lunar.getYearInGanZhiExact() === yearGanZhi && lunar.getMonthInGanZhiExact() === monthGanZhi && dgz === dayGanZhi && lunar.getTimeInGanZhi() === timeGanZhi) {
l.push(solar);
break inner;
break;
}
solar = solar.next(1);
}
@@ -716,9 +738,7 @@
var lms = ly.getMonths();
for (var i = 0, j = lms.length; i < j; i++) {
var m = lms[i];
// 初一
var firstDay = Solar.fromJulianDay(m.getFirstJulianDay());
var days = solar.subtract(firstDay);
var days = solar.subtract(Solar.fromJulianDay(m.getFirstJulianDay()));
if (days < m.getDayCount()) {
lunarYear = m.getYear();
lunarMonth = m.getMonth();
@@ -1826,8 +1846,7 @@
start = this._p.jieQi['冬至'];
startDay = Solar.fromYmd(start.getYear(), start.getMonth(), start.getDay());
}
var endDay = Solar.fromYmd(start.getYear(), start.getMonth(), start.getDay());
endDay = endDay.next(81);
var endDay = Solar.fromYmd(start.getYear(), start.getMonth(), start.getDay()).next(81);
if (currentDay.isBefore(startDay) || (!currentDay.isBefore(endDay))) {
return null;
}
@@ -1908,8 +1927,7 @@
var current = Solar.fromYmd(this._p.solar.getYear(),this._p.solar.getMonth(),this._p.solar.getDay());
var startSolar = jieQi.getSolar();
var start = Solar.fromYmd(startSolar.getYear(),startSolar.getMonth(),startSolar.getDay());
var days = current.subtract(start);
var index = Math.floor(days / 5);
var index = Math.floor(current.subtract(start) / 5);
if (index > 2) {
index = 2;
}
@@ -2004,8 +2022,7 @@
* @return number 周序号从1开始
*/
getIndex:function(){
var firstDayWeek = Solar.fromYmd(this._p.year,this._p.month,1).getWeek();
var offset = firstDayWeek - this._p.start;
var offset = Solar.fromYmd(this._p.year,this._p.month,1).getWeek() - this._p.start;
if(offset < 0) {
offset += 7;
}
@@ -2016,8 +2033,7 @@
* @return number 周序号从1开始
*/
getIndexInYear:function(){
var firstDayWeek = Solar.fromYmd(this._p.year,1,1).getWeek();
var offset = firstDayWeek - this._p.start;
var offset = Solar.fromYmd(this._p.year,1,1).getWeek() - this._p.start;
if(offset < 0) {
offset += 7;
}
@@ -2061,10 +2077,10 @@
week = _fromYmd(solar.getYear(), solar.getMonth(), solar.getDay(), start);
}
} else {
var size = SolarUtil.getWeeksOfMonth(week.getYear(), week.getMonth(), this._p.start);
var size = SolarUtil.getWeeksOfMonth(week.getYear(), week.getMonth(), start);
if (size === index) {
var lastDay = week.getFirstDay().next(6);
week = _fromYmd(lastDay.getYear(), lastDay.getMonth(), lastDay.getDay(), this._p.start);
week = _fromYmd(lastDay.getYear(), lastDay.getMonth(), lastDay.getDay(), start);
weekMonth = week.getMonth();
} else {
solar = Solar.fromYmd(week.getYear(), week.getMonth(), SolarUtil.getDaysOfMonth(week.getYear(), week.getMonth()));
@@ -2295,8 +2311,7 @@
if(isNaN(seasons)){
throw new Error('wrong seasons ' + os);
}
var month = SolarMonth.fromYm(this._p.year, this._p.month);
month = month.next(3 * seasons);
var month = SolarMonth.fromYm(this._p.year, this._p.month).next(3 * seasons);
return _fromYm(month.getYear(), month.getMonth());
},
/**
@@ -2369,8 +2384,7 @@
if(isNaN(halfYears)){
throw new Error('wong halfYears ' + oh);
}
var month = SolarMonth.fromYm(this._p.year, this._p.month);
month = month.next(6 * halfYears);
var month = SolarMonth.fromYm(this._p.year, this._p.month).next(6 * halfYears);
return _fromYm(month.getYear(), month.getMonth());
},
/**
@@ -2499,6 +2513,26 @@
getZhi:function(){return LunarUtil.ZHI[this._p.zhiIndex+1];},
getGanZhi:function(){return this.getGan()+this.getZhi();},
getJieQiJulianDays:function(){return this._p.jieQiJulianDays;},
getDayCount:function(){
var n = 0;
for (var i = 0, j = this._p.months.length; i < j; i++) {
var m = this._p.months[i];
if (m.getYear() === this._p.year) {
n += m.getDayCount();
}
}
return n;
},
getMonthsInYear:function(){
var l = [];
for (var i = 0, j = this._p.months.length; i < j; i++) {
var m = this._p.months[i];
if (m.getYear() === this._p.year) {
l.push(m);
}
}
return l;
},
getMonths:function(){return this._p.months;},
getMonth:function(lunarMonth){
var om = lunarMonth;
@@ -2672,7 +2706,9 @@
// 冬至前的初一
var w = ShouXingUtil.calcShuo(jq[0]);
if (w > jq[0]) {
w -= 29.5306;
if (currentYear !== 41 && currentYear !== 193 && currentYear !== 288 && currentYear !== 345 && currentYear !== 918 && currentYear !== 1013) {
w -= 29.5306;
}
}
// 递推每月初一
for (i = 0; i < 16; i++) {
@@ -2683,39 +2719,40 @@
dayCounts.push(Math.floor(hs[i + 1] - hs[i]));
}
var currentYearLeap = _LEAP['_' + currentYear];
if (!currentYearLeap) {
currentYearLeap = -1;
if (hs[13] <= jq[24]) {
i = 1;
while (hs[i + 1] > jq[2 * i] && i < 13) {
i++;
var prevYear = currentYear - 1;
var leapYear = -1;
var leapIndex = -1;
var leap = _LEAP['_' + currentYear];
if (!leap) {
leap = _LEAP['_' + prevYear];
if (!leap) {
if (hs[13] <= jq[24]) {
i = 1;
while (hs[i + 1] > jq[2 * i] && i < 13) {
i++;
}
leapYear = currentYear;
leapIndex = i;
}
currentYearLeap = i;
} else {
leapYear = prevYear;
leapIndex = leap - 12;
}
} else {
leapYear = currentYear;
leapIndex = leap;
}
var prevYear = currentYear - 1;
var prevYearLeap = _LEAP['_' + prevYear];
prevYearLeap = prevYearLeap ? prevYearLeap - 12 : -1;
var y = this._p.year - 1;
var y = prevYear;
var m = 11;
for (i = 0, j = dayCounts.length; i < j; i++) {
var cm = m;
var isNextLeap = false;
if (y === currentYear && i === currentYearLeap) {
if (y === leapYear && i === leapIndex) {
cm = -cm;
} else if (y === prevYear && i === prevYearLeap) {
cm = -cm;
}
if (y === currentYear && i + 1 === currentYearLeap) {
isNextLeap = true;
} else if (y === prevYear && i + 1 === prevYearLeap) {
isNextLeap = true;
}
this._p.months.push(LunarMonth._(y, cm, dayCounts[i], hs[i] + Solar.J2000));
if (!isNextLeap) {
if (y !== leapYear || i + 1 !== leapIndex) {
m++;
}
if (m === 13) {
@@ -4385,8 +4422,8 @@
toString:function(){return this.getGanZhi();}
};
};
return {
fromYmdHms:function(lunarYear,lunarMonth,lunarDay,hour,minute,second){return _fromYmdHms(lunarYear,lunarMonth,lunarDay,hour,minute,second);},
return {
fromYmdHms:function(lunarYear,lunarMonth,lunarDay,hour,minute,second){return _fromYmdHms(lunarYear,lunarMonth,lunarDay,hour,minute,second);}
};
})();
var FotoUtil = (function(){

View File

@@ -1,6 +1,6 @@
{
"name": "lunar-javascript",
"version": "1.3.0",
"version": "1.3.3",
"description": "lunar is a calendar library for Solar and Chinese Lunar.",
"main": "index.js",
"scripts": {