mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix bug
This commit is contained in:
parent
f8988acc88
commit
4f683f6445
@ -3,7 +3,7 @@
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# 5.7.18 (2021-12-24)
|
||||
# 5.7.18 (2021-12-25)
|
||||
|
||||
### 🐣新特性
|
||||
* 【core 】 新增CollStreamUtil.groupKeyValue(pr#479@Gitee)
|
||||
@ -27,6 +27,7 @@
|
||||
* 【core 】 修复UserAgentUtil解析EdgA无法识别问题(issue#I4MCBP@Gitee)
|
||||
* 【extra 】 修复Archiver路径前带/问题(issue#I4NS0F@Gitee)
|
||||
* 【extra 】 修复getMainColor方法中参数rgbFilters无效问题(pr#2034@Github)
|
||||
* 【core 】 修复ChineseDate无法区分闰月问题(issue#I4NQQW@Gitee)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
# 5.7.17 (2021-12-09)
|
||||
|
@ -13,7 +13,7 @@ import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 农历日期工具,最大支持到2055年,支持:
|
||||
* 农历日期工具,最大支持到2099年,支持:
|
||||
*
|
||||
* <ul>
|
||||
* <li>通过公历日期构造获取对应农历</li>
|
||||
@ -27,34 +27,39 @@ public class ChineseDate {
|
||||
|
||||
//农历年
|
||||
private final int year;
|
||||
//农历月
|
||||
//农历月,润N月这个值就是N+1,其他月按照显示月份赋值
|
||||
private final int month;
|
||||
// 当前月份是否闰月
|
||||
private final boolean isLeapMonth;
|
||||
//农历日
|
||||
private final int day;
|
||||
|
||||
//公历年
|
||||
private final int gyear;
|
||||
//公历月
|
||||
private final int gmonth;
|
||||
//公历月,从1开始计数
|
||||
private final int gmonthBase1;
|
||||
//公历日
|
||||
private final int gday;
|
||||
|
||||
//是否闰年
|
||||
private boolean leap;
|
||||
|
||||
/**
|
||||
* 通过公历日期构造
|
||||
*
|
||||
* @param date 公历日期
|
||||
*/
|
||||
public ChineseDate(Date date) {
|
||||
// 公历
|
||||
final DateTime dt = DateUtil.beginOfDay(date);
|
||||
gyear = dt.year();
|
||||
gmonthBase1 = dt.month() + 1;
|
||||
gday = dt.dayOfMonth();
|
||||
|
||||
// 求出和1900年1月31日相差的天数
|
||||
int offset = (int) ((DateUtil.beginOfDay(date).getTime() / DateUnit.DAY.getMillis()) - LunarInfo.BASE_DAY);
|
||||
int offset = (int) ((dt.getTime() / DateUnit.DAY.getMillis()) - LunarInfo.BASE_DAY);
|
||||
// 计算农历年份
|
||||
// 用offset减去每农历年的天数,计算当天是农历第几天,offset是当年的第几天
|
||||
int daysOfYear;
|
||||
int iYear = LunarInfo.BASE_YEAR;
|
||||
for (; iYear <= LunarInfo.MAX_YEAR; iYear++) {
|
||||
int iYear;
|
||||
for (iYear = LunarInfo.BASE_YEAR; iYear <= LunarInfo.MAX_YEAR; iYear++) {
|
||||
daysOfYear = LunarInfo.yearDays(iYear);
|
||||
if (offset < daysOfYear) {
|
||||
break;
|
||||
@ -66,48 +71,34 @@ public class ChineseDate {
|
||||
// 计算农历月份
|
||||
int leapMonth = LunarInfo.leapMonth(iYear); // 闰哪个月,1-12
|
||||
// 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天
|
||||
int iMonth;
|
||||
int daysOfMonth = 0;
|
||||
for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) {
|
||||
// 闰月
|
||||
if (leapMonth > 0 && iMonth == (leapMonth + 1) && false == leap) {
|
||||
--iMonth;
|
||||
leap = true;
|
||||
int month;
|
||||
int daysOfMonth;
|
||||
boolean hasLeapMonth = false;
|
||||
for (month = 1; month < 13; month++) {
|
||||
// 闰月,如润的是五月,则5表示五月,6表示润五月
|
||||
if (leapMonth > 0 && month == (leapMonth + 1)) {
|
||||
daysOfMonth = LunarInfo.leapDays(year);
|
||||
hasLeapMonth = true;
|
||||
} else {
|
||||
daysOfMonth = LunarInfo.monthDays(year, iMonth);
|
||||
// 普通月,当前面的月份存在闰月时,普通月份要-1,递补闰月的数字
|
||||
// 如2月是闰月,此时3月实际是第四个月
|
||||
daysOfMonth = LunarInfo.monthDays(year, hasLeapMonth ? month - 1 : month);
|
||||
}
|
||||
|
||||
if (offset < daysOfMonth) {
|
||||
// offset不足月,结束
|
||||
break;
|
||||
}
|
||||
offset -= daysOfMonth;
|
||||
// 解除闰月
|
||||
if (leap && iMonth == (leapMonth + 1)) {
|
||||
leap = false;
|
||||
}
|
||||
}
|
||||
|
||||
// offset为0时,并且刚才计算的月份是闰月,要校正
|
||||
if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {
|
||||
if (leap) {
|
||||
leap = false;
|
||||
} else {
|
||||
leap = true;
|
||||
--iMonth;
|
||||
this.isLeapMonth = month == (leapMonth + 1);
|
||||
if (hasLeapMonth && false == this.isLeapMonth) {
|
||||
// 当前月份前有闰月,则月份显示要-1,除非当前月份就是润月
|
||||
month--;
|
||||
}
|
||||
}
|
||||
// offset小于0时,也要校正
|
||||
if (offset < 0) {
|
||||
offset += daysOfMonth;
|
||||
--iMonth;
|
||||
}
|
||||
|
||||
month = iMonth;
|
||||
day = offset + 1;
|
||||
|
||||
// 公历
|
||||
final DateTime dt = DateUtil.date(date);
|
||||
gyear = dt.year();
|
||||
gmonth = dt.month() + 1;
|
||||
gday = dt.dayOfMonth();
|
||||
this.month = month;
|
||||
this.day = offset + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,10 +110,24 @@ public class ChineseDate {
|
||||
* @since 5.2.4
|
||||
*/
|
||||
public ChineseDate(int chineseYear, int chineseMonth, int chineseDay) {
|
||||
this(chineseYear, chineseMonth, chineseDay, chineseMonth == LunarInfo.leapMonth(chineseYear) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造方法传入日期
|
||||
*
|
||||
* @param chineseYear 农历年
|
||||
* @param chineseMonth 农历月,1表示一月(正月)
|
||||
* @param chineseDay 农历日,1表示初一
|
||||
* @param isLeapMonth 当前月份是否闰月
|
||||
* @since 5.7.18
|
||||
*/
|
||||
public ChineseDate(int chineseYear, int chineseMonth, int chineseDay, boolean isLeapMonth) {
|
||||
this.day = chineseDay;
|
||||
this.month = chineseMonth;
|
||||
// 当月是闰月的后边的月定义为闰月,如润的是五月,则5表示五月,6表示润五月
|
||||
this.isLeapMonth = isLeapMonth;
|
||||
this.year = chineseYear;
|
||||
this.leap = DateUtil.isLeapYear(chineseYear);
|
||||
//先判断传入的月份是不是闰月
|
||||
int leapMonth = LunarInfo.leapMonth(chineseYear);
|
||||
|
||||
@ -131,14 +136,14 @@ public class ChineseDate {
|
||||
//初始化公历年
|
||||
this.gday = dateTime.dayOfMonth();
|
||||
//初始化公历月
|
||||
this.gmonth = dateTime.month() + 1;
|
||||
this.gmonthBase1 = dateTime.month() + 1;
|
||||
//初始化公历日
|
||||
this.gyear = dateTime.year();
|
||||
} else {
|
||||
//初始化公历年
|
||||
this.gday = -1;
|
||||
//初始化公历月
|
||||
this.gmonth = -1;
|
||||
this.gmonthBase1 = -1;
|
||||
//初始化公历日
|
||||
this.gyear = -1;
|
||||
}
|
||||
@ -159,12 +164,13 @@ public class ChineseDate {
|
||||
* @return 公历年
|
||||
* @since 5.6.1
|
||||
*/
|
||||
public int getGregorianYear(){
|
||||
public int getGregorianYear() {
|
||||
return this.gyear;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取农历的月,从1开始计数
|
||||
* 获取农历的月,从1开始计数<br>
|
||||
* 此方法返回实际的月序号,如一月是闰月,则一月返回1,润一月返回2
|
||||
*
|
||||
* @return 农历的月
|
||||
* @since 5.2.4
|
||||
@ -179,8 +185,8 @@ public class ChineseDate {
|
||||
* @return 公历月
|
||||
* @since 5.6.1
|
||||
*/
|
||||
public int getGregorianMonthBase1(){
|
||||
return this.gmonth;
|
||||
public int getGregorianMonthBase1() {
|
||||
return this.gmonthBase1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,8 +195,8 @@ public class ChineseDate {
|
||||
* @return 公历月
|
||||
* @since 5.6.1
|
||||
*/
|
||||
public int getGregorianMonth(){
|
||||
return this.gmonth -1;
|
||||
public int getGregorianMonth() {
|
||||
return this.gmonthBase1 - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,7 +206,7 @@ public class ChineseDate {
|
||||
* @since 5.4.2
|
||||
*/
|
||||
public boolean isLeapMonth() {
|
||||
return ChineseMonth.isLeapMonth(this.year, this.month);
|
||||
return this.isLeapMonth;
|
||||
}
|
||||
|
||||
|
||||
@ -210,7 +216,7 @@ public class ChineseDate {
|
||||
* @return 返回农历月份
|
||||
*/
|
||||
public String getChineseMonth() {
|
||||
return ChineseMonth.getChineseMonthName(isLeapMonth(), this.month, false);
|
||||
return getChineseMonth(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -219,7 +225,19 @@ public class ChineseDate {
|
||||
* @return 返回农历月份称呼
|
||||
*/
|
||||
public String getChineseMonthName() {
|
||||
return ChineseMonth.getChineseMonthName(isLeapMonth(), this.month, true);
|
||||
return getChineseMonth(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得农历月份(中文,例如二月,十二月,或者润一月)
|
||||
*
|
||||
* @param isTraditional 是否传统表示,例如一月传统表示为正月
|
||||
* @return 返回农历月份
|
||||
* @since 5.7.18
|
||||
*/
|
||||
public String getChineseMonth(boolean isTraditional) {
|
||||
return ChineseMonth.getChineseMonthName(isLeapMonth(),
|
||||
isLeapMonth() ? this.month - 1 : this.month, isTraditional);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -238,7 +256,7 @@ public class ChineseDate {
|
||||
* @return 公历日
|
||||
* @since 5.6.1
|
||||
*/
|
||||
public int getGregorianDay(){
|
||||
public int getGregorianDay() {
|
||||
return this.gday;
|
||||
}
|
||||
|
||||
@ -271,7 +289,7 @@ public class ChineseDate {
|
||||
* @return 公历Date
|
||||
* @since 5.6.1
|
||||
*/
|
||||
public Date getGregorianDate(){
|
||||
public Date getGregorianDate() {
|
||||
return DateUtil.date(getGregorianCalendar());
|
||||
}
|
||||
|
||||
@ -281,7 +299,7 @@ public class ChineseDate {
|
||||
* @return 公历Calendar
|
||||
* @since 5.6.1
|
||||
*/
|
||||
public Calendar getGregorianCalendar(){
|
||||
public Calendar getGregorianCalendar() {
|
||||
final Calendar calendar = CalendarUtil.calendar();
|
||||
//noinspection MagicConstant
|
||||
calendar.set(this.gyear, getGregorianMonth(), this.gday, 0, 0, 0);
|
||||
@ -289,7 +307,7 @@ public class ChineseDate {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得节日
|
||||
* 获得节日,闰月不计入节日中
|
||||
*
|
||||
* @return 获得农历节日
|
||||
*/
|
||||
@ -322,8 +340,8 @@ public class ChineseDate {
|
||||
* @return 获得天干地支的年月日信息
|
||||
*/
|
||||
public String getCyclicalYMD() {
|
||||
if (gyear >= LunarInfo.BASE_YEAR && gmonth > 0 && gday > 0) {
|
||||
return cyclicalm(gyear, gmonth, gday);
|
||||
if (gyear >= LunarInfo.BASE_YEAR && gmonthBase1 > 0 && gday > 0) {
|
||||
return cyclicalm(gyear, gmonthBase1, gday);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -331,21 +349,24 @@ public class ChineseDate {
|
||||
|
||||
/**
|
||||
* 获得节气
|
||||
*
|
||||
* @return 获得节气
|
||||
* @since 5.6.3
|
||||
*/
|
||||
public String getTerm() {
|
||||
return SolarTerms.getTerm(gyear, gmonth, gday);
|
||||
return SolarTerms.getTerm(gyear, gmonthBase1, gday);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为标准的日期格式来表示农历日期,例如2020-01-13
|
||||
* 转换为标准的日期格式来表示农历日期,例如2020-01-13<br>
|
||||
* 如果存在闰月,显示闰月月份,如润二月显示2
|
||||
*
|
||||
* @return 标准的日期格式
|
||||
* @since 5.2.4
|
||||
*/
|
||||
public String toStringNormal() {
|
||||
return String.format("%04d-%02d-%02d", this.year, this.month, this.day);
|
||||
return String.format("%04d-%02d-%02d", this.year,
|
||||
isLeapMonth() ? this.month - 1 : this.month, this.day);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,7 +29,7 @@ public class ChineseMonth {
|
||||
* 当为非传统表示时,二月,十二月,或者润一月等
|
||||
*
|
||||
* @param isLeapMonth 是否闰月
|
||||
* @param month 月份,从1开始
|
||||
* @param month 月份,从1开始,如果是闰月,应传入需要显示的月份
|
||||
* @param isTraditional 是否传统表示,例如一月传统表示为正月
|
||||
* @return 返回农历月份称呼
|
||||
*/
|
||||
|
@ -66,9 +66,9 @@ public class LunarInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* 传回农历 y年闰月的天数
|
||||
* 传回农历 y年闰月的天数,如果本年无闰月,返回0,区分大小月
|
||||
*
|
||||
* @param y 年
|
||||
* @param y 农历年
|
||||
* @return 闰月的天数
|
||||
*/
|
||||
public static int leapDays(int y) {
|
||||
@ -80,7 +80,7 @@ public class LunarInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* 传回农历 y年m月的总天数
|
||||
* 传回农历 y年m月的总天数,区分大小月
|
||||
*
|
||||
* @param y 年
|
||||
* @param m 月
|
||||
@ -91,7 +91,8 @@ public class LunarInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* 传回农历 y年闰哪个月 1-12 , 没闰传回 0
|
||||
* 传回农历 y年闰哪个月 1-12 , 没闰传回 0<br>
|
||||
* 此方法会返回润N月中的N,如二月、闰二月都返回2
|
||||
*
|
||||
* @param y 年
|
||||
* @return 润的月, 没闰传回 0
|
||||
|
@ -55,6 +55,9 @@ public class ChineseDateTest {
|
||||
Assert.assertEquals("六月", chineseDate.getChineseMonth());
|
||||
|
||||
chineseDate = new ChineseDate(2020,4,15);
|
||||
Assert.assertEquals("四月", chineseDate.getChineseMonth());
|
||||
|
||||
chineseDate = new ChineseDate(2020,5,15);
|
||||
Assert.assertEquals("闰四月", chineseDate.getChineseMonth());
|
||||
}
|
||||
|
||||
@ -77,7 +80,29 @@ public class ChineseDateTest {
|
||||
|
||||
@Test
|
||||
public void dateTest2(){
|
||||
ChineseDate date = new ChineseDate(DateUtil.parse("2020-10-19 11:12:23"));
|
||||
ChineseDate date = new ChineseDate(DateUtil.parse("2020-10-19"));
|
||||
Assert.assertEquals("庚子鼠年 九月初三", date.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dateTest2_2(){
|
||||
ChineseDate date = new ChineseDate(DateUtil.parse("2020-07-20"));
|
||||
Assert.assertEquals("庚子鼠年 五月三十", date.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dateTest3(){
|
||||
// 初一,offset为0测试
|
||||
ChineseDate date = new ChineseDate(DateUtil.parse("2099-03-22"));
|
||||
Assert.assertEquals("己未羊年 闰二月初一", date.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void leapMonthTest(){
|
||||
final ChineseDate c1 = new ChineseDate(DateUtil.parse("2028-05-28"));
|
||||
final ChineseDate c2 = new ChineseDate(DateUtil.parse("2028-06-27"));
|
||||
|
||||
Assert.assertEquals("戊申猴年 五月初五", c1.toString());
|
||||
Assert.assertEquals("戊申猴年 闰五月初五", c2.toString());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user