1
0
mirror of synced 2026-10-23 06:56:11 +08:00

Compare commits

...

2 Commits

Author SHA1 Message Date
6tail
1c3ff0cbc5 v1.3.12 八字转阳历结果按时间先后排序,转换速度大幅提升。 2024-02-06 17:40:46 +08:00
6tail
e15a916e55 v1.3.11 修复命宫、身宫的错误。 2024-01-30 21:00:30 +08:00
8 changed files with 153 additions and 110 deletions

5
CHANGELOG.md Normal file
View File

@@ -0,0 +1,5 @@
# Changelog
## [1.3.12] - 2024-02-06
1. 八字转阳历结果按时间先后排序,转换速度大幅提升。

View File

@@ -16,7 +16,7 @@ lunar是一款无第三方依赖的公历(阳历)、农历(阴历、老黄历)
<dependency> <dependency>
<groupId>cn.6tail</groupId> <groupId>cn.6tail</groupId>
<artifactId>lunar</artifactId> <artifactId>lunar</artifactId>
<version>1.3.10</version> <version>1.3.12</version>
</dependency> </dependency>
``` ```

View File

@@ -12,7 +12,7 @@ lunar is a calendar library for Solar and Chinese Lunar.
<dependency> <dependency>
<groupId>cn.6tail</groupId> <groupId>cn.6tail</groupId>
<artifactId>lunar</artifactId> <artifactId>lunar</artifactId>
<version>1.3.10</version> <version>1.3.12</version>
</dependency> </dependency>
``` ```

View File

@@ -7,7 +7,7 @@
<groupId>cn.6tail</groupId> <groupId>cn.6tail</groupId>
<artifactId>lunar</artifactId> <artifactId>lunar</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
<version>1.3.10</version> <version>1.3.12</version>
<name>${project.groupId}:${project.artifactId}</name> <name>${project.groupId}:${project.artifactId}</name>
<url>https://github.com/6tail/lunar-java</url> <url>https://github.com/6tail/lunar-java</url>
<description>a calendar library for Solar and Chinese Lunar</description> <description>a calendar library for Solar and Chinese Lunar</description>

View File

@@ -499,29 +499,15 @@ public class EightChar {
* @return 命宫 * @return 命宫
*/ */
public String getMingGong() { public String getMingGong() {
int monthZhiIndex = 0; int monthZhiIndex = LunarUtil.find(getMonthZhi(), MONTH_ZHI, 0);
int timeZhiIndex = 0; int timeZhiIndex = LunarUtil.find(getTimeZhi(), MONTH_ZHI, 0);
for (int i = 0, j = MONTH_ZHI.length; i < j; i++) { int offset = monthZhiIndex + timeZhiIndex;
String zhi = MONTH_ZHI[i]; offset = (offset >= 14 ? 26 : 14) - offset;
if (lunar.getMonthZhiExact().equals(zhi)) { int ganIndex = (lunar.getYearGanIndexExact() + 1) * 2 + offset;
monthZhiIndex = i; while (ganIndex > 10) {
} ganIndex -= 10;
if (lunar.getTimeZhi().equals(zhi)) {
timeZhiIndex = i;
}
} }
int zhiIndex = 26 - (monthZhiIndex + timeZhiIndex); return LunarUtil.GAN[ganIndex] + MONTH_ZHI[offset];
if (zhiIndex > 12) {
zhiIndex -= 12;
}
int jiaZiIndex = LunarUtil.getJiaZiIndex(lunar.getMonthInGanZhiExact()) - (monthZhiIndex - zhiIndex);
if (jiaZiIndex >= 60) {
jiaZiIndex -= 60;
}
if (jiaZiIndex < 0) {
jiaZiIndex += 60;
}
return LunarUtil.JIA_ZI[jiaZiIndex];
} }
/** /**
@@ -539,29 +525,17 @@ public class EightChar {
* @return 身宫 * @return 身宫
*/ */
public String getShenGong() { public String getShenGong() {
int monthZhiIndex = 0; int monthZhiIndex = LunarUtil.find(getMonthZhi(), MONTH_ZHI, 0);
int timeZhiIndex = 0; int timeZhiIndex = LunarUtil.find(getTimeZhi(), LunarUtil.ZHI, 0);
for (int i = 0, j = MONTH_ZHI.length; i < j; i++) { int offset = monthZhiIndex + timeZhiIndex;
String zhi = MONTH_ZHI[i]; while (offset > 12) {
if (lunar.getMonthZhiExact().equals(zhi)) { offset -= 12;
monthZhiIndex = i;
}
if (lunar.getTimeZhi().equals(zhi)) {
timeZhiIndex = i;
}
} }
int zhiIndex = 2 + monthZhiIndex + timeZhiIndex; int ganIndex = (lunar.getYearGanIndexExact() + 1) * 2 + (offset % 12);
if (zhiIndex > 12) { while (ganIndex > 10) {
zhiIndex -= 12; ganIndex -= 10;
} }
int jiaZiIndex = LunarUtil.getJiaZiIndex(lunar.getMonthInGanZhiExact()) - (monthZhiIndex - zhiIndex); return LunarUtil.GAN[ganIndex] + MONTH_ZHI[offset];
if (jiaZiIndex >= 60) {
jiaZiIndex -= 60;
}
if (jiaZiIndex < 0) {
jiaZiIndex += 60;
}
return LunarUtil.JIA_ZI[jiaZiIndex];
} }
/** /**

View File

@@ -296,49 +296,67 @@ public class Solar {
public static List<Solar> fromBaZi(String yearGanZhi, String monthGanZhi, String dayGanZhi, String timeGanZhi, int sect, int baseYear) { public static List<Solar> fromBaZi(String yearGanZhi, String monthGanZhi, String dayGanZhi, String timeGanZhi, int sect, int baseYear) {
sect = (1 == sect) ? 1 : 2; sect = (1 == sect) ? 1 : 2;
List<Solar> l = new ArrayList<Solar>(); List<Solar> l = new ArrayList<Solar>();
List<Integer> years = new ArrayList<Integer>(); // 月地支距寅月的偏移值
Solar today = fromDate(new Date()); int m = LunarUtil.find(monthGanZhi.substring(1), LunarUtil.ZHI, -1) - 2;
int offsetYear = (today.getYear() - 4) % 60 - LunarUtil.getJiaZiIndex(yearGanZhi); if (m < 0) {
if(offsetYear < 0){ m += 12;
offsetYear += 60;
} }
int startYear = today.getYear() - offsetYear - 1; // 月天干要一致
int minYear = baseYear - 2; if (((LunarUtil.find(yearGanZhi.substring(0, 1), LunarUtil.GAN, -1) + 1) * 2 + m) % 10 != LunarUtil.find(monthGanZhi.substring(0,1), LunarUtil.GAN, -1)) {
while (startYear >= minYear) { return l;
years.add(startYear);
startYear -= 60;
} }
List<Integer> hours = new ArrayList<Integer>(2); // 1年的立春是辛酉,序号57
String timeZhi = timeGanZhi.substring(1); int y = LunarUtil.getJiaZiIndex(yearGanZhi) - 57;
for(int i = 1, j = LunarUtil.ZHI.length; i < j; i++){ if (y < 0) {
if(LunarUtil.ZHI[i].equals(timeZhi)){ y += 60;
hours.add((i - 1) * 2);
break;
}
} }
if ("子".equals(timeZhi)) { y++;
hours.add(23); // 节令偏移值
} m *= 2;
for (int hour: hours) { // 时辰地支转时刻,子时按零点算
for (Integer y : years) { int h = LunarUtil.find(timeGanZhi.substring(1), LunarUtil.ZHI, -1) * 2;
int maxYear = y + 3; int startYear = baseYear - 1;
int year = y;
int month = 11; // 结束年
if (year < baseYear) { Calendar c = Calendar.getInstance(TIME_ZONE);
year = baseYear; c.setTime(new Date());
month = 1; c.set(Calendar.MILLISECOND, 0);
} int endYear = c.get(Calendar.YEAR);
Solar solar = fromYmdHms(year, month, 1, hour, 0, 0);
while (solar.getYear() <= maxYear) { while (y <= endYear) {
Lunar lunar = solar.getLunar(); if (y >= startYear) {
// 立春为寅月的开始
List<Solar> jieQiList = new ArrayList<Solar>(Lunar.fromYmd(y, 1, 1).getJieQiTable().values());
// 节令推移,年干支和月干支就都匹配上了
Solar solarTime = jieQiList.get(4 + m);
if (solarTime.getYear() >= baseYear) {
int mi = 0;
int s = 0;
// 日干支和节令干支的偏移值
Lunar lunar = solarTime.getLunar();
String dgz = (2 == sect) ? lunar.getDayInGanZhiExact2() : lunar.getDayInGanZhiExact(); String dgz = (2 == sect) ? lunar.getDayInGanZhiExact2() : lunar.getDayInGanZhiExact();
int d = LunarUtil.getJiaZiIndex(dayGanZhi) - LunarUtil.getJiaZiIndex(dgz);
if (d < 0) {
d += 60;
}
if (d > 0) {
// 从节令推移天数
solarTime = solarTime.next(d);
} else if (h == solarTime.getHour()) {
// 如果正好是节令当天,且小时和节令的小时数相等的极端情况,把分钟和秒钟带上
mi = solarTime.getMinute();
s = solarTime.getSecond();
}
// 验证一下
Solar solar = Solar.fromYmdHms(solarTime.getYear(), solarTime.getMonth(), solarTime.getDay(), h, mi, s);
lunar = solar.getLunar();
dgz = (2 == sect) ? lunar.getDayInGanZhiExact2() : lunar.getDayInGanZhiExact();
if (lunar.getYearInGanZhiExact().equals(yearGanZhi) && lunar.getMonthInGanZhiExact().equals(monthGanZhi) && dgz.equals(dayGanZhi) && lunar.getTimeInGanZhi().equals(timeGanZhi)) { if (lunar.getYearInGanZhiExact().equals(yearGanZhi) && lunar.getMonthInGanZhiExact().equals(monthGanZhi) && dgz.equals(dayGanZhi) && lunar.getTimeInGanZhi().equals(timeGanZhi)) {
l.add(solar); l.add(solar);
break;
} }
solar = solar.next(1);
} }
} }
y += 60;
} }
return l; return l;
} }

View File

@@ -809,9 +809,13 @@ public class LunarUtil{
* @return 甲子序号 * @return 甲子序号
*/ */
public static int getJiaZiIndex(String ganZhi){ public static int getJiaZiIndex(String ganZhi){
for(int i=0,j=LunarUtil.JIA_ZI.length;i<j;i++){ return find(ganZhi, JIA_ZI, 0);
if(LunarUtil.JIA_ZI[i].equals(ganZhi)){ }
return i;
public static int find(String name, String[] names, int offset) {
for(int i=0,j=names.length;i<j;i++){
if(names[i].equals(name)){
return i + offset;
} }
} }
return -1; return -1;
@@ -1020,22 +1024,8 @@ public class LunarUtil{
* @return 旬下标,0-5 * @return 旬下标,0-5
*/ */
protected static int getXunIndex(String ganZhi){ protected static int getXunIndex(String ganZhi){
String gan = ganZhi.substring(0,1); int ganIndex = find(ganZhi.substring(0, 1), GAN, 0);
String zhi = ganZhi.substring(1); int zhiIndex = find(ganZhi.substring(1), ZHI, 0);
int ganIndex = 0;
int zhiIndex = 0;
for(int i=0,j=GAN.length;i<j;i++){
if(GAN[i].equals(gan)){
ganIndex = i;
break;
}
}
for(int i=0,j=ZHI.length;i<j;i++){
if(ZHI[i].equals(zhi)){
zhiIndex = i;
break;
}
}
int diff = ganIndex - zhiIndex; int diff = ganIndex - zhiIndex;
if(diff<0){ if(diff<0){
diff += 12; diff += 12;

View File

@@ -234,7 +234,7 @@ public class BaZiTest {
@Test @Test
public void testShenGong1() { public void testShenGong1() {
Lunar lunar = new Solar(1994, 12, 6, 2, 0, 0).getLunar(); Lunar lunar = new Solar(1994, 12, 6, 2, 0, 0).getLunar();
Assert.assertEquals("身宫", "丁丑", lunar.getEightChar().getShenGong()); Assert.assertEquals("身宫", "乙丑", lunar.getEightChar().getShenGong());
} }
@Test @Test
@@ -258,8 +258,8 @@ public class BaZiTest {
} }
List<String> expected = new ArrayList<String>(); List<String> expected = new ArrayList<String>();
expected.add("1976-09-21 12:00:00");
expected.add("1916-10-06 12:00:00"); expected.add("1916-10-06 12:00:00");
expected.add("1976-09-21 12:00:00");
Assert.assertEquals(expected, actual); Assert.assertEquals(expected, actual);
} }
@@ -285,8 +285,8 @@ public class BaZiTest {
} }
List<String> expected = new ArrayList<String>(); List<String> expected = new ArrayList<String>();
expected.add("1999-07-21 16:00:00");
expected.add("1939-08-05 16:00:00"); expected.add("1939-08-05 16:00:00");
expected.add("1999-07-21 16:00:00");
Assert.assertEquals(expected, actual); Assert.assertEquals(expected, actual);
} }
@@ -299,8 +299,8 @@ public class BaZiTest {
} }
List<String> expected = new ArrayList<String>(); List<String> expected = new ArrayList<String>();
expected.add("1960-12-17 12:00:00");
expected.add("1901-01-01 12:00:00"); expected.add("1901-01-01 12:00:00");
expected.add("1960-12-17 12:00:00");
Assert.assertEquals(expected, actual); Assert.assertEquals(expected, actual);
} }
@@ -313,8 +313,8 @@ public class BaZiTest {
} }
List<String> expected = new ArrayList<String>(); List<String> expected = new ArrayList<String>();
expected.add("2020-07-21 22:00:00");
expected.add("1960-08-05 22:00:00"); expected.add("1960-08-05 22:00:00");
expected.add("2020-07-21 22:00:00");
Assert.assertEquals(expected, actual); Assert.assertEquals(expected, actual);
} }
@@ -368,15 +368,15 @@ public class BaZiTest {
@Test @Test
public void test14() { public void test14() {
List<Solar> l = Solar.fromBaZi("癸卯","甲寅","癸丑","甲子", 2, 1843); List<Solar> l = Solar.fromBaZi("癸卯","甲寅","甲寅","甲子", 2, 1843);
List<String> actual = new ArrayList<String>(); List<String> actual = new ArrayList<String>();
for (Solar solar : l) { for (Solar solar : l) {
actual.add(solar.toYmdHms()); actual.add(solar.toYmdHms());
} }
List<String> expected = new ArrayList<String>(); List<String> expected = new ArrayList<String>();
expected.add("2023-02-24 23:00:00"); expected.add("1843-02-09 00:00:00");
expected.add("1843-02-08 23:00:00"); expected.add("2023-02-25 00:00:00");
Assert.assertEquals(expected, actual); Assert.assertEquals(expected, actual);
} }
@@ -389,8 +389,8 @@ public class BaZiTest {
} }
List<String> expected = new ArrayList<String>(); List<String> expected = new ArrayList<String>();
expected.add("1960-01-15 16:00:00");
expected.add("1900-01-29 16:00:00"); expected.add("1900-01-29 16:00:00");
expected.add("1960-01-15 16:00:00");
Assert.assertEquals(expected, actual); Assert.assertEquals(expected, actual);
} }
@@ -412,7 +412,7 @@ public class BaZiTest {
Solar solar = new Solar(1986, 5, 29, 13, 37, 0); Solar solar = new Solar(1986, 5, 29, 13, 37, 0);
Lunar lunar = solar.getLunar(); Lunar lunar = solar.getLunar();
EightChar eightChar = lunar.getEightChar(); EightChar eightChar = lunar.getEightChar();
Assert.assertEquals("辛丑", eightChar.getShenGong()); Assert.assertEquals("己丑", eightChar.getShenGong());
} }
@Test @Test
@@ -432,9 +432,65 @@ public class BaZiTest {
} }
List<String> expected = new ArrayList<String>(); List<String> expected = new ArrayList<String>();
expected.add("1997-03-12 18:00:00");
expected.add("1937-03-27 18:00:00"); expected.add("1937-03-27 18:00:00");
expected.add("1997-03-12 18:00:00");
Assert.assertEquals(expected, actual); Assert.assertEquals(expected, actual);
} }
@Test
public void test20() {
List<Solar> l = Solar.fromBaZi("乙未","己卯","丁丑","甲辰");
List<String> actual = new ArrayList<String>();
for (Solar solar : l) {
actual.add(solar.toYmdHms());
}
List<String> expected = new ArrayList<String>();
expected.add("1955-03-17 08:00:00");
Assert.assertEquals(expected, actual);
}
@Test
public void test21() {
Lunar lunar = Solar.fromYmdHms(2024, 1, 29, 9, 30, 0).getLunar();
EightChar eightChar = lunar.getEightChar();
Assert.assertEquals("命宫", "癸亥", eightChar.getMingGong());
Assert.assertEquals("身宫", "己未", eightChar.getShenGong());
}
@Test
public void test22() {
Assert.assertEquals("身宫", "丙寅", Solar.fromYmdHms(1990, 1, 27, 0, 0, 0).getLunar().getEightChar().getShenGong());
}
@Test
public void test23() {
Assert.assertEquals("甲戌", Solar.fromYmdHms(2019, 3, 7, 8, 0, 0).getLunar().getEightChar().getMingGong());
}
@Test
public void test24() {
Assert.assertEquals("丁丑", Solar.fromYmdHms(2019, 3, 27, 2, 0, 0).getLunar().getEightChar().getMingGong());
}
@Test
public void test25() {
Assert.assertEquals("丙寅", Lunar.fromYmdHms(1994, 5, 20, 18, 0 ,0).getEightChar().getMingGong());
}
@Test
public void test26() {
Lunar lunar = Solar.fromYmdHms(1986, 2, 16, 8, 0, 0).getLunar();
EightChar eightChar = lunar.getEightChar();
Assert.assertEquals("命宫", "己亥", eightChar.getMingGong());
Assert.assertEquals("身宫", "乙未", eightChar.getShenGong());
}
@Test
public void test27() {
Lunar lunar = Solar.fromYmdHms(1972, 11, 27, 10, 0, 0).getLunar();
EightChar eightChar = lunar.getEightChar();
Assert.assertEquals("身宫", "乙巳", eightChar.getShenGong());
}
} }