1
0
mirror of synced 2025-12-25 06:47:59 +08:00
Files
lunar-java/src/main/java/com/nlf/calendar/Solar.java

539 lines
12 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.nlf.calendar;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import com.nlf.calendar.util.LunarUtil;
import com.nlf.calendar.util.SolarUtil;
/**
* 阳历日期
*
* @author 6tail
*
*/
public class Solar{
/** 2000年儒略日数(2000-1-1 12:00:00 UTC) */
public static final double J2000 = 2451545;
/** 年 */
private int year;
/** 月 */
private int month;
/** 日 */
private int day;
/** 时 */
private int hour;
/** 分 */
private int minute;
/** 秒 */
private int second;
/** 日历 */
private Calendar calendar;
/**
* 默认使用当前日期初始化
*/
public Solar(){
this(new Date());
}
/**
* 通过年月日初始化
*
* @param year 年
* @param month 月1到12
* @param day 日1到31
*/
public Solar(int year,int month,int day){
this(year,month,day,0,0,0);
}
/**
* 通过年月日初始化
*
* @param year 年
* @param month 月1到12
* @param day 日1到31
* @param hour 小时0到23
* @param minute 分钟0到59
* @param second 秒钟0到59
*/
public Solar(int year,int month,int day,int hour,int minute,int second){
calendar = Calendar.getInstance();
calendar.set(year,month-1,day,hour,minute,second);
this.year = year;
this.month = month;
this.day = day;
this.hour = hour;
this.minute = minute;
this.second = second;
}
/**
* 通过日期初始化
*
* @param date 日期
*/
public Solar(Date date){
calendar = Calendar.getInstance();
calendar.setTime(date);
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH)+1;
day = calendar.get(Calendar.DATE);
hour = calendar.get(Calendar.HOUR_OF_DAY);
minute = calendar.get(Calendar.MINUTE);
second = calendar.get(Calendar.SECOND);
}
/**
* 通过日历初始化
*
* @param calendar 日历
*/
public Solar(Calendar calendar){
this.calendar = calendar;
year = calendar.get(Calendar.YEAR);
month = calendar.get(Calendar.MONTH)+1;
day = calendar.get(Calendar.DATE);
hour = calendar.get(Calendar.HOUR_OF_DAY);
minute = calendar.get(Calendar.MINUTE);
second = calendar.get(Calendar.SECOND);
}
/**
* 通过儒略日初始化
* @param julianDay 儒略日
*/
public Solar(double julianDay){
int d = (int)(julianDay + 0.5);
double f = julianDay + 0.5 - d;
int c;
if (d >= 2299161) {
c = (int)((d - 1867216.25) / 36524.25);
d += 1 + c - (int)(c * 1D / 4);
}
d += 1524;
int year = (int)((d - 122.1) / 365.25);
d -= (int)(365.25 * year);
int month = (int)(d * 1D / 30.601);
d -= (int)(30.601 * month);
int day = d;
if (month > 13) {
month -= 13;
year -= 4715;
} else {
month -= 1;
year -= 4716;
}
f *= 24;
int hour = (int)f;
f -= hour;
f *= 60;
int minute = (int)f;
f -= minute;
f *= 60;
int second = (int)Math.round(f);
calendar = Calendar.getInstance();
calendar.set(year,month-1,day,hour,minute,second);
this.year = year;
this.month = month;
this.day = day;
this.hour = hour;
this.minute = minute;
this.second = second;
}
/**
* 通过指定日期获取阳历
*
* @param date 日期
* @return 阳历
*/
public static Solar fromDate(Date date){
return new Solar(date);
}
/**
* 通过指定日历获取阳历
*
* @param calendar 日历
* @return 阳历
*/
public static Solar fromCalendar(Calendar calendar){
return new Solar(calendar);
}
/**
* 通过指定儒略日获取阳历
*
* @param julianDay 儒略日
* @return 阳历
*/
public static Solar fromJulianDay(double julianDay){
return new Solar(julianDay);
}
/**
* 通过指定年月日获取阳历
*
* @param year 年
* @param month 月1到12
* @param day 日1到31
* @return 阳历
*/
public static Solar fromYmd(int year,int month,int day){
return new Solar(year,month,day);
}
/**
* 通过指定年月日时分获取阳历
*
* @param year 年
* @param month 月1到12
* @param day 日1到31
* @param hour 小时0到23
* @param minute 分钟0到59
* @param second 秒钟0到59
* @return 阳历
*/
public static Solar fromYmdHms(int year,int month,int day,int hour,int minute,int second){
return new Solar(year,month,day,hour,minute,second);
}
/**
* 通过八字获取阳历列表
* @param yearGanZhi 年柱
* @param monthGanZhi 月柱
* @param dayGanZhi 日柱
* @param timeGanZhi 时柱
* @return 符合的阳历列表
*/
public static List<Solar> fromBaZi(String yearGanZhi,String monthGanZhi,String dayGanZhi,String timeGanZhi){
List<Solar> l = new ArrayList<Solar>();
Solar today = new Solar();
Lunar lunar = today.getLunar();
int offsetYear = LunarUtil.getJiaZiIndex(lunar.getYearInGanZhiExact())-LunarUtil.getJiaZiIndex(yearGanZhi);
if (offsetYear<0){
offsetYear = offsetYear+60;
}
int startYear = today.getYear() - offsetYear;
int hour = 0;
String timeZhi = timeGanZhi.substring(1);
for(int i=0,j=LunarUtil.ZHI.length;i<j;i++){
if(LunarUtil.ZHI[i].equals(timeZhi)){
hour = (i-1)*2;
}
}
int year = startYear-1;
while(year>=SolarUtil.BASE_YEAR) {
int counter = 0;
int month = 12;
int day;
boolean found = false;
while (counter < 15) {
day = 1;
if(year==SolarUtil.BASE_YEAR){
if(month<SolarUtil.BASE_MONTH){
continue;
}else if(month==SolarUtil.BASE_MONTH){
day = SolarUtil.BASE_DAY;
}
}
Solar solar = new Solar(year, month, day, hour, 0, 0);
lunar = solar.getLunar();
if (lunar.getYearInGanZhiExact().equals(yearGanZhi) && lunar.getMonthInGanZhiExact().equals(monthGanZhi)) {
found = true;
break;
}
month++;
if (month > 12) {
month = 1;
year++;
}
counter++;
}
if (found) {
counter = 0;
Solar solar = new Solar(year, month-1, 1, hour, 0, 0);
while (counter < 61) {
lunar = solar.getLunar();
if (lunar.getYearInGanZhiExact().equals(yearGanZhi) && lunar.getMonthInGanZhiExact().equals(monthGanZhi) && lunar.getDayInGanZhiExact().equals(dayGanZhi) && lunar.getTimeInGanZhi().equals(timeGanZhi)) {
l.add(solar);
break;
}
solar = solar.next(1);
counter++;
}
}
year -= 61;
}
return l;
}
/**
* 是否闰年
*
* @return true/false 闰年/非闰年
*/
public boolean isLeapYear(){
return SolarUtil.isLeapYear(year);
}
/**
* 获取星期0代表周日1代表周一
*
* @return 0123456
*/
public int getWeek(){
return calendar.get(Calendar.DAY_OF_WEEK)-1;
}
/**
* 获取星期的中文
*
* @return 日一二三四五六
*/
public String getWeekInChinese(){
return SolarUtil.WEEK[getWeek()];
}
/**
* 获取节日,有可能一天会有多个节日
*
* @return 劳动节等
*/
public List<String> getFestivals(){
List<String> l = new ArrayList<String>();
//获取几月几日对应的节日
String f = SolarUtil.FESTIVAL.get(month+"-"+day);
if(null!=f){
l.add(f);
}
//计算几月第几个星期几对应的节日
//第几周
int weekInMonth = calendar.get(Calendar.WEEK_OF_MONTH);
//星期几0代表星期天
int week = getWeek();
//星期天很奇葩,会多算一周,需要减掉
if(0==week){
weekInMonth--;
}
f = SolarUtil.WEEK_FESTIVAL.get(month+"-"+weekInMonth+"-"+week);
if(null!=f){
l.add(f);
}
return l;
}
/**
* 获取非正式的节日,有可能一天会有多个节日
*
* @return 非正式的节日列表,如中元节
*/
public List<String> getOtherFestivals(){
List<String> l = new ArrayList<String>();
List<String> fs = SolarUtil.OTHER_FESTIVAL.get(month+"-"+day);
if(null!=fs){
l.addAll(fs);
}
return l;
}
/**
* 获取星座
*
* @return 星座
* @deprecated 使用getXingZuo
*/
public String getXingzuo(){
return getXingZuo();
}
/**
* 获取星座
*
* @return 星座
*/
public String getXingZuo(){
int index = 11,m = month,d = day;
int y = m*100+d;
if(y>=321&&y<=419){
index = 0;
}else if(y>=420&&y<=520){
index = 1;
}else if(y>=521&&y<=620){
index = 2;
}else if(y>=621&&y<=722){
index = 3;
}else if(y>=723&&y<=822){
index = 4;
}else if(y>=823&&y<=922){
index = 5;
}else if(y>=923&&y<=1022){
index = 6;
}else if(y>=1023&&y<=1121){
index = 7;
}else if(y>=1122&&y<=1221){
index = 8;
}else if(y>=1222||y<=119){
index = 9;
}else if(y<=218){
index = 10;
}
return SolarUtil.XINGZUO[index];
}
/**
* 获取年份
*
* @return 如2015
*/
public int getYear(){
return year;
}
/**
* 获取月份
*
* @return 1到12
*/
public int getMonth(){
return month;
}
/**
* 获取日期
*
* @return 1到31之间的数字
*/
public int getDay(){
return day;
}
/**
* 获取小时
*
* @return 0到23之间的数字
*/
public int getHour(){
return hour;
}
/**
* 获取分钟
*
* @return 0到59之间的数字
*/
public int getMinute(){
return minute;
}
/**
* 获取秒钟
*
* @return 0到59之间的数字
*/
public int getSecond(){
return second;
}
/**
* 获取农历
* @return 农历
*/
public Lunar getLunar(){
return new Lunar(calendar.getTime());
}
/**
* 获取儒略日
* @return 儒略日
*/
public double getJulianDay(){
int y = this.year;
int m = this.month;
double d = this.day + ((this.second *1D / 60 + this.minute) / 60 + this.hour) / 24;
int n = 0;
boolean g = false;
if (y * 372 + m * 31 + (int)d >= 588829) {
g = true;
}
if (m <= 2) {
m += 12;
y--;
}
if (g) {
n = (int)(y * 1D / 100);
n = 2 - n + (int)(n * 1D / 4);
}
return (int)(365.25 * (y + 4716)) + (int)(30.6001 * (m + 1)) + d + n - 1524.5;
}
/**
* 获取日历
*
* @return 日历
*/
public Calendar getCalendar(){
return calendar;
}
@Override
public String toString(){
return toYmd();
}
public String toYmd(){
return year+"-"+(month<10?"0":"")+month+"-"+(day<10?"0":"")+day;
}
public String toYmdHms(){
return toYmd()+" "+(hour<10?"0":"")+hour+":"+(minute<10?"0":"")+minute+":"+(second<10?"0":"")+second;
}
public String toFullString(){
StringBuilder s = new StringBuilder();
s.append(toYmdHms());
if(isLeapYear()){
s.append(" ");
s.append("闰年");
}
s.append(" ");
s.append("星期");
s.append(getWeekInChinese());
for(String f:getFestivals()){
s.append(" (");
s.append(f);
s.append(")");
}
for(String f:getOtherFestivals()){
s.append(" (");
s.append(f);
s.append(")");
}
s.append(" ");
s.append(getXingZuo());
s.append("");
return s.toString();
}
/**
* 获取往后推几天的阳历日期,如果要往前推,则天数用负数
* @param days 天数
* @return 阳历日期
*/
public Solar next(int days){
Calendar c = Calendar.getInstance();
c.set(year,month-1,day,hour,minute,second);
c.add(Calendar.DATE,days);
return new Solar(c);
}
}