返回
Android开发之春节节气以及各类历法日期转换工具
Android
2024-01-12 04:19:25
一、前言
农历、阴历、阳历都是时间系统的两种表达方式,而春节和节气是基于时间系统而产生的节日和时间节点。
本工具能实现将阳历日期转换成农历日期和阴历日期,也能将农历日期、阴历日期转换成阳历日期。
二、工具原理
阳历日期转换农历日期或阴历日期,实质上是将阳历日期转换成农历或阴历的年、月、日。
首先将阳历日期转换为距1900年1月1日经过的天数,然后利用【中国农历工具网站】提供的【农历查询】获取这一天是农历或阴历的哪一年、哪一月、哪一日。
三、工具类
public class LunarCalendar {
private int year;
private int month;
private int day;
private boolean leap;
/**
* 将阳历日期转换成农历日期
*
* @param solarYear 阳历年
* @param solarMonth 阳历月
* @param solarDay 阳历日
*/
public LunarCalendar(int solarYear, int solarMonth, int solarDay) {
// 将阳历日期转换为距1900年1月1日经过的天数
int daysSince1900 = solarToDays(solarYear, solarMonth, solarDay);
// 获取农历年份
year = 1900 + daysSince1900 / 365;
// 获取农历月份
int daysInLunarYear = 365 * (year - 1900) + daysSince1900 % 365;
month = 1;
while (daysInLunarYear > getDaysInLunarMonth(year, month)) {
daysInLunarYear -= getDaysInLunarMonth(year, month);
month++;
}
// 获取农历日子
day = daysInLunarYear;
// 判断农历年份是否为闰年
leap = isLunarLeapYear(year);
}
/**
* 将阳历日期转换成农历日期
*
* @param date 阳历日期,格式为"yyyy-MM-dd"
*/
public LunarCalendar(String date) {
String[] parts = date.split("-");
int year = Integer.parseInt(parts[0]);
int month = Integer.parseInt(parts[1]);
int day = Integer.parseInt(parts[2]);
this(year, month, day);
}
/**
* 将阳历日期转换成距1900年1月1日经过的天数
*
* @param year 阳历年
* @param month 阳历月
* @param day 阳历日
* @return 距1900年1月1日经过的天数
*/
private int solarToDays(int year, int month, int day) {
int days = 0;
// 计算从1900年1月1日到year年1月1日经过的天数
for (int i = 1900; i < year; i++) {
days += 365 + isSolarLeapYear(i);
}
// 计算从year年1月1日到year年month月day日经过的天数
for (int i = 1; i < month; i++) {
days += getDaysInSolarMonth(year, i);
}
// 计算year年month月day日当天经过的天数
days += day;
return days;
}
/**
* 判断阳历年是否为闰年
*
* @param year 阳历年
* @return true if year is a leap year, false otherwise
*/
private boolean isSolarLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
/**
* 获取阳历年中某个月的天数
*
* @param year 阳历年
* @param month 阳历月
* @return 阳历年中某个月的天数
*/
private int getDaysInSolarMonth(int year, int month) {
int[] daysInMonths = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (month == 2 && isSolarLeapYear(year)) {
return 29;
} else {
return daysInMonths[month - 1];
}
}
/**
* 获取农历年中某个月的天数
*
* @param year 农历年
* @param month 农历月
* @return 农历年中某个月的天数
*/
private int getDaysInLunarMonth(int year, int month) {
int[] daysInLunarMonths = {29, 30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30};
if (isLunarLeapYear(year) && month == 13) {
return 29;
} else {
return daysInLunarMonths[month - 1];
}
}
/**
* 判断农历年是否为闰年
*
* @param year 农历年
* @return true if year is a leap year, false otherwise
*/
private boolean isLunarLeapYear(int year) {
return ((year - 4) % 19) == 0;
}
/**
* 获取农历年份
*
* @return 农历年份
*/
public int getYear() {
return year;
}
/**
* 获取农历月份
*
* @return 农历月份
*/
public int getMonth() {
return month;
}
/**
* 获取农历日子
*
* @return 农历日子
*/
public int getDay() {
return day;
}
/**
* 判断农历年份是否为闰年
*
* @return true if year is a leap year, false otherwise
*/
public boolean isLeap() {
return leap;
}
/**
* 将农历日期转换成阳历日期
*
* @return 阳历日期,格式为"yyyy-MM-dd"
*/
public String toSolarString() {
int daysSince1900 = lunarToDays(year, month, day);
int solarYear = 1900 + daysSince1900 / 365;
int solarMonth = 1;
while (daysSince1900 > getDaysInSolarMonth(solarYear, solarMonth)) {
daysSince1900 -= getDaysInSolarMonth(solarYear, solarMonth);
solarMonth++;
}
int solarDay = daysSince1900;
return String.format("%04d-%02d-%02d", solarYear, solarMonth, solarDay);
}
/**
* 将农历日期转换成距1900年1月1日经过的天数
*
* @param year 农历年
* @param month 农历月
* @param day 农历日
* @return 距1900年1月1日经过的天数
*/
private int lunarToDays(int year, int month, int day) {
int days = 0;
// 计算从1900年1月1日到year年1月1日经过的天数
for (int i = 1900; i < year; i++) {
days += 365 + isLunarLeapYear(i);
}
// 计算从year年1月1日到year年month月day日经过的天数
for (int i = 1; i < month; i