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 fromBaZi(String yearGanZhi,String monthGanZhi,String dayGanZhi,String timeGanZhi){ List l = new ArrayList(); 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=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 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 getFestivals(){ List l = new ArrayList(); //获取几月几日对应的节日 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 getOtherFestivals(){ List l = new ArrayList(); List 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); } }