package com.watsons.onstore.user.api.utils;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;/*** 获取输入公历日期的生肖、天干地支、农历年、农历月、农历日、公历节日、农历节日、24节气等数据** @author huangJunHao* @date 2022/4/12*/
public class LunarCalendarFestivalUtils {//生肖年private String animal;//干支年private String ganZhiYear;//阴历年private String lunarYear;//阴历月private String lunarMonth;//阴历日private String lunarDay;//阳历节日private String solarFestival;//阴历节日private String lunarFestival;//节气private String lunarTerm;/***   获取查询日期的年份生肖* @return*/public String getAnimal() {return animal;}/***   获取查询日期年份的天干地支* @return*/public String getGanZhiYear() {return ganZhiYear;}/***   获取查询日期的农历年份* @return*/public String getLunarYear() {return lunarYear;}/***   获取查询日期的农历月份* @return*/public String getLunarMonth() {return lunarMonth;}/***   获取查询日期的农历日* @return*/public String getLunarDay() {return lunarDay;}/***  获取查询日期的公历节日(不是节日返回空)* @return*/public String getSolarFestival() {return solarFestival;}/***  获取查询日期的农历节日(不是节日返回空)* @return*/public String getLunarFestival() {return lunarFestival;}/***   获取查询日期的节气数据(不是节气返回空)* @return*/public String getLunarTerm() {return lunarTerm;}final static long[] lunarInfo = new long[] {0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2,0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977,0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950,0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557,0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0,0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0,0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6,0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570,0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5,0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930,0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530,0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45,0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0};//阳历天数final static  int[] solarMonths = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};//生肖final static  String[] animals = new String[]{"鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"};//天干final static String[] tGan = new String[] { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" };//地支final static String[] dZhi = new String[] { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" };//二十四节气final static  String[] solarTerms = new String[]{"小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏","小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"};//二十四节气日期偏移度private static final  double D = 0.2422;//特殊年份节气日期偏移private final static Map<Integer,Integer[]> INCREASE_OFFSETMAP = new HashMap<Integer, Integer[]>();//+1偏移private final static Map<Integer,Integer[]> DECREASE_OFFSETMAP = new HashMap<Integer, Integer[]>();//-1偏移static {INCREASE_OFFSETMAP.put(0, new Integer[]{1982});//小寒DECREASE_OFFSETMAP.put(0, new Integer[]{2019});//小寒INCREASE_OFFSETMAP.put(1, new Integer[]{2082});//大寒DECREASE_OFFSETMAP.put(3, new Integer[]{2026});//雨水INCREASE_OFFSETMAP.put(5, new Integer[]{2084});//春分INCREASE_OFFSETMAP.put(9, new Integer[]{2008});//小满INCREASE_OFFSETMAP.put(10, new Integer[]{1902});//芒种INCREASE_OFFSETMAP.put(11, new Integer[]{1928});//夏至INCREASE_OFFSETMAP.put(12, new Integer[]{1925,2016});//小暑INCREASE_OFFSETMAP.put(13, new Integer[]{1922});//大暑INCREASE_OFFSETMAP.put(14, new Integer[]{2002});//立秋INCREASE_OFFSETMAP.put(16, new Integer[]{1927});//白露INCREASE_OFFSETMAP.put(17, new Integer[]{1942});//秋分INCREASE_OFFSETMAP.put(19, new Integer[]{2089});//霜降INCREASE_OFFSETMAP.put(20, new Integer[]{2089});//立冬INCREASE_OFFSETMAP.put(21, new Integer[]{1978});//小雪INCREASE_OFFSETMAP.put(22, new Integer[]{1954});//大雪DECREASE_OFFSETMAP.put(23, new Integer[]{1918,2021});//冬至}//定义一个二维数组,第一维数组存储的是20世纪的节气C值,第二维数组存储的是21世纪的节气C值,0到23个,依次代表立春、雨水...大寒节气的C值private static final double[][] CENTURY_ARRAY = {{6.11,20.84,4.6295,19.4599,6.3826,21.4155,5.59,20.888,6.318,21.86,6.5,22.2,7.928,23.65,8.35,23.95,8.44,23.822,9.098,24.218,8.218,23.08,7.9,22.6},{5.4055,20.12,3.87,18.73,5.63,20.646,4.81,20.1,5.52,21.04,5.678,21.37,7.108,22.83,7.5,23.13,7.646,23.042,8.318,23.438,7.438,22.36,7.18,21.94}};//农历月份final static String lunarNumber[] = { "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二" };//农历年final static  String[] lunarYears = new String[]{"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};final static  String[] chineseTen = new String[]{"初", "十", "廿", "三"};//农历节日final static String[] lunarHoliday = new String[] {"0101 春节", "0115 元宵节", "0202 龙头节", "0505 端午节", "0707 七夕节", "0715 中元节","0815 中秋节", "0909 重阳节", "1001 寒衣节", "1015 下元节", "1208 腊八节", "1223 小年" };//公立节日final static String[] solarHoliday = new String[] { "0101 元旦", "0214 情人节", "0308 妇女节", "0312 植树节", "0315 消费者权益日","0401 愚人节", "0422 地球日", "0423 读书日", "0501 劳动节", "0504 青年节", "0512 护士节", "0518 博物馆日", "0519 旅游日", "0601 儿童节","0701 建党节", "0801 建军节", "0910 教师节","1001 国庆节", "1024 联合国日", "1204 宪法日", "1224 平安夜", "1225 圣诞节"};//格式化日期static SimpleDateFormat chineseDateFormat = new SimpleDateFormat("yyyy年MM月dd日", Locale.CHINA);static SimpleDateFormat solarDateFormat = new SimpleDateFormat("yyyy-MM-dd");/***   返回农历y年的总天数* @param y* @return*/private int lunarYearDays(int y) {int i, sum = 348;for (i = 0x8000; i > 0x8; i >>= 1) {sum += ((lunarInfo[y - 1900] & i) != 0 ? 1 : 0);}return (sum + leapDays(y));}/***  返回农历y年闰月的天数*/private int leapDays(int y) {if (leapMonth(y) != 0) {return ((lunarInfo[y - 1900] & 0x10000) != 0 ? 30 : 29 );} elsereturn 0;}/***  判断y年的农历中那个月是闰月,不是闰月返回0* @param y* @return*/private int leapMonth(int y) {return  (int) (lunarInfo[y - 1900] & 0xf);}/***  返回农历y年m月的总天数* @param y* @param m* @return*/private int monthDays(int y, int m) {return ((lunarInfo[y - 1900] & (0x10000 >> m))!=0 ? 30 : 29);}/***  获取阴历年* @param year* @return*/private String getLunarYearString(String year) {int y1 = Integer.parseInt(year.charAt(0)+"");int y2 = Integer.parseInt(year.charAt(1)+"");int y3 = Integer.parseInt(year.charAt(2)+"");int y4 = Integer.parseInt(year.charAt(3)+"");return lunarYears[y1]+lunarYears[y2]+lunarYears[y3]+lunarYears[y4];}/***   获取阴历日*/private String getLunarDayString(int day) {int n = day % 10 == 0 ? 9 : day % 10 - 1;if (day > 30)return "";if (day == 10)return "初十";elsereturn chineseTen[day / 10] + lunarNumber[n];}/***  特例,特殊的年分的节气偏移量,由于公式并不完善,所以算出的个别节气的第几天数并不准确,在此返回其偏移量* @param year 年份* @param n 节气编号* @return 返回其偏移量*/private int specialYearOffset(int year,int n) {int offset = 0;offset += getOffset(DECREASE_OFFSETMAP,year,n,-1);offset += getOffset(INCREASE_OFFSETMAP,year,n,1);return offset;}/***  节气偏移量计算* @param map* @param year* @param n* @param offset* @return*/private int getOffset(Map<Integer,Integer[]> map,int year,int n,int offset){int off = 0;Integer[] years = map.get(n);if(null != years){for(int i:years){if(i == year){off = offset;break;}}}return off;}/***   获取某年的第n个节气为几日(从0小寒起算)* @param year* @param n* @return*/private int sTerm(int year, int n) {double centuryValue = 0;//节气的世纪值,每个节气的每个世纪值都不同int centuryIndex = -1;if(year>=1901 && year<=2000){//20世纪centuryIndex = 0;} else if(year>=2001 && year <= 2100){//21世纪centuryIndex = 1;} else {throw new RuntimeException("不支持此年份:"+year+",目前只支持1901年到2100年的时间范围");}centuryValue = CENTURY_ARRAY[centuryIndex][n];int dateNum = 0;int y = year%100;//步骤1:取年分的后两位数if(year%4 == 0 && year%100 !=0 || year%400 ==0){//闰年if(n == 0 || n == 1 || n == 2 || n == 3){//注意:凡闰年3月1日前闰年数要减一,即:L=[(Y-1)/4],因为小寒、大寒、立春、雨水这两个节气都小于3月1日,所以 y = y-1y = y-1;//步骤2}}dateNum = (int)(y*D+centuryValue)-(int)(y/4);//步骤3,使用公式[Y*D+C]-L计算dateNum += specialYearOffset(year,n);//步骤4,加上特殊的年分的节气偏移量return dateNum;}/***   母亲节和父亲节* @param year* @param month* @param day* @return*/private  String getMotherOrFatherDay(int year, int month, int day) {if (month != 5 && month != 6) return null;if ((month == 5 && (day < 8 || day > 14)) || (month == 6 && (day < 15 || day > 21))) return null;Calendar calendar = Calendar.getInstance();calendar.set(year, month - 1, 1);int weekDate = calendar.get(Calendar.DAY_OF_WEEK);weekDate = (weekDate == 1) ? 7 : weekDate - 1;switch (month) {case 5:if (day == 15 - weekDate) {return "母亲节";}break;case 6:if (day == 22 - weekDate) {return "父亲节";}break;}return null;}/***   感恩节* @param year* @param month* @param day* @return*/private String thanksgiving(int year, int month, int day) {if (month != 11) return null;if ((month == 11 && (day < 19 || day > 28))) return null;Calendar calendar = Calendar.getInstance();calendar.set(year, month - 1, 1);int weekDate = calendar.get(Calendar.DAY_OF_WEEK);weekDate = (weekDate == 1) ? 7 : weekDate - 1;switch (month) {case 11:if (day == 29 - weekDate + 4) {return "感恩节";}break;}return null;}/***  获取复活节* @param year* @param month* @param day* @return*/private String getEasterDay(int year, int month, int day) {int n = year - 1900;int a = n % 19;int q = n / 4;int b = (7 * a + 1) / 19;int m = (11 * a + 4 - b) % 29;int w = (n + q + 31 - m) % 7;int answer = 25 - m - w;String easterDay = "";if (answer > 0) {easterDay = year+"-"+4+"-"+answer;} else {easterDay = year+"-"+3+"-"+(31 + answer);}String searchDay = year+"-"+month+"-"+day;if(searchDay.equals(easterDay)) {return "复活节";}return null;}/***  输入公历日期初始化当前日期的生肖、天干地支、农历年、农历月、农历日、公历节日、农历节日、24节气*  输入日期的格式为(YYYY-MM-DD)* @param currentDate*/public void initLunarCalendarInfo(String currentDate){String[] splitDate = currentDate.split("-");//设置生肖int year = Integer.parseInt(splitDate[0]);this.animal=animals[(year - 4) % 12];//设置天干地支int num = year - 1900 + 36;this.ganZhiYear =  (tGan[num % 10] + dZhi[num % 12]);///设置阴历///基准日期Date baseDate = null;//当前日期Date nowaday = null;try {baseDate = chineseDateFormat.parse("1900年1月31日");nowaday = solarDateFormat.parse(currentDate);} catch (ParseException e) {e.printStackTrace();}// 获取当前日期与1900年1月31日相差的天数int offset = (int) ((nowaday.getTime() - baseDate.getTime()) / 86400000L);//用offset减去每农历年的天数,计算当天是农历第几天 iYear最终结果是农历的年份int iYear, daysOfYear = 0;for (iYear = 1900; iYear < 10000 && offset > 0; iYear++) {daysOfYear = lunarYearDays(iYear);offset -= daysOfYear;}if (offset < 0) {offset += daysOfYear;iYear--;}this.lunarYear = getLunarYearString(iYear+"");int leapMonth = leapMonth(iYear); // 闰哪个月,1-12boolean leap = false;// 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天int iMonth, daysOfMonth = 0;for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) {// 闰月if (leapMonth > 0 && iMonth == (leapMonth + 1) && !leap) {--iMonth;leap = true;daysOfMonth = leapDays(iYear);} elsedaysOfMonth = monthDays(iYear, iMonth);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;}}// offset小于0时,也要校正if (offset < 0) {offset += daysOfMonth;--iMonth;}// 设置对应的阴历月份this.lunarMonth = lunarNumber[iMonth - 1] ;if("一".equals(this.lunarMonth)){this.lunarMonth ="正";}if("十二".equals(this.lunarMonth)){this.lunarMonth ="腊";}if(leap){this.lunarMonth ="闰"+this.lunarMonth;}//设置阴历日int iDay = offset + 1;this.lunarDay = getLunarDayString(iDay);//设置节气int month=Integer.parseInt(splitDate[1]);int day=Integer.parseInt(splitDate[2]);if (day == sTerm(year, (month - 1) * 2)){this.lunarTerm = solarTerms[(month - 1) * 2];}else if (day == sTerm(year, (month - 1) * 2 + 1)){this.lunarTerm = solarTerms[(month - 1) * 2 + 1];}else{this.lunarTerm = "";}//设置阳历节日String solarFestival="";for (int i = 0; i < solarHoliday.length; i++) {// 返回公历节假日名称String sd = solarHoliday[i].split(" ")[0]; // 节假日的日期String sdv = solarHoliday[i].split(" ")[1]; // 节假日的名称String smonth_v = splitDate[1];String sday_v = splitDate[2];String smd = smonth_v + sday_v;if (sd.trim().equals(smd.trim())) {solarFestival =  sdv;break;}}//判断节日是否是父亲节或母亲节String motherOrFatherDay = getMotherOrFatherDay(year, month, day);if(motherOrFatherDay != null ){solarFestival = motherOrFatherDay;}//判断节日是否是复活节String easterDay = getEasterDay(year, month, day);if(easterDay != null ){solarFestival = easterDay;}//判断节日是否是感恩节String thanksgiving = thanksgiving(year, month, day);if(thanksgiving != null ){solarFestival = thanksgiving;}this.solarFestival = solarFestival;//设置阴历节日String lunarFestival="";for (int i = 0; i < lunarHoliday.length; i++) {//阴历闰月节日if(leap){break;}// 返回农历节假日名称String ld = lunarHoliday[i].split(" ")[0]; // 节假日的日期String ldv = lunarHoliday[i].split(" ")[1]; // 节假日的名称String lmonth_v = iMonth + "";String lday_v = iDay + "";String lmd = "";if (iMonth < 10) {lmonth_v = "0" + iMonth;}if (iDay < 10) {lday_v = "0" + iDay;}lmd = lmonth_v + lday_v;if ("12".equals(lmonth_v)) { // 除夕夜需要特殊处理if ((daysOfMonth == 29 && iDay == 29) || (daysOfMonth == 30 && iDay == 30)) {lunarFestival = "除夕";break;}}if (ld.trim().equals(lmd.trim())) {lunarFestival = ldv;break;}}if("清明".equals(this.lunarTerm)){lunarFestival = "清明节";}this.lunarFestival = lunarFestival;}/***  测试方法* @param args*/public static void main(String[] args) {LunarCalendarFestivalUtils festival = new LunarCalendarFestivalUtils();festival.initLunarCalendarInfo("2021-06-25");System.out.println("农历"+festival.getLunarYear()+"年"+festival.getLunarMonth()+"月"+festival.getLunarDay()+"日");System.out.println(festival.getGanZhiYear()+"【"+festival.getAnimal()+"】年");System.out.println(festival.getLunarTerm());System.out.println(festival.getLunarFestival();   );System.out.println(festival.getLunarFestival());}
}

根据日期获取农历节日相关推荐

  1. php自动获取节气对应的年月日_php如何通过日期获取农历、节日、节气?

    php如何通过日期获取农历.节日.节气? 发布时间:2020-05-21 11:57:28 来源:亿速云 阅读:229 作者:Leah php如何通过日期获取农历.节日.节气?这篇文章运用了实例代码展 ...

  2. IOS获取农历节日.节气

    获取农历节日的算法: +(NSString *)getLunarHoliDayDate:(NSDate *)date{ NSTimeInterval timeInterval_day = float( ...

  3. IOS 获取农历节日 节气

    扩展了前一篇农历的内容 转载请标明来自:http://blog.csdn.net/zhao_yin/ 获取农历节日的算法: [cpp]view plaincopyprint? +(NSString * ...

  4. 获取农历节日、节气方法

    扩展了前一篇农历的内容 转载请标明来自:http://blog.csdn.net/zhao_yin/ 获取农历节日的算法: [cpp]  view plain copy print ? +(NSStr ...

  5. 获取农历节日的公共方法

    下载地址:https://download.csdn.net/download/biubiubiuPlus/13187048

  6. NSDate 农历节日

    扩展了前一篇农历的内容 转载请标明来自:http://blog.csdn.net/zhao_yin/ 获取农历节日的算法: [cpp] view plaincopyprint? +(NSString  ...

  7. php获取农历日期节日

    $c = new DayService();$today=$c->convertSolarToLunar(date('Y'),date('m'),date('d'));$time =" ...

  8. LocalDateTime工具类:根据当前、周、月、季度、半年、年等维度获取时间hutool工具包获取农历日期,生肖,传统节日

    1. 简介 Java8提供了全新的日期处理包(java.time.*),根据Java8日期新特性封装日期时间工具类LocalDateTimeUtils. 2. 工具类方法目录 说明 方法名称 当前时间 ...

  9. mysql 获取农历年份_php获取农历(阴历)、节日、节气的类的方法以及用法

    这篇文章主要介绍了php实现获取农历(阴历).节日.节气的类与用法,结合实例形式分析了php日期工具类Lunar的具体定义与获取农历日期.节气等相关操作技巧,需要的朋友可以参考下 具体如下: /* * ...

最新文章

  1. 点分治问题 ----------- P2993 [FJOI2014]最短路径树问题 [最短路径树+点分治+采坑]
  2. 【聚能聊有奖话题】今日头条公布算法原理,你认可他们的理念吗?
  3. 新农人谋定新理念-农业大健康·李孟:“玩”出农业新花样
  4. boost::multiprecision模块complex128相关的测试程序
  5. python处理行情数据_请教 Python 如何解析 DBF 文件, SJSHQ.dbf 上交所行情文件,数据来源于巨灵数据。...
  6. kibana 查询_干货 | Elasticsearch、Kibana数据导出实战
  7. Tablestore Timestream:为海量时序数据存储设计的全新数据模型...
  8. 正反观点验证2010年10大安全挑战
  9. VPP 助你创新更高效、更灵活的报文处理方案
  10. 隐秘?混乱?商业化?记者深入总部,探寻OpenAI“拯救世界”背后的真相
  11. 游戏产业链:客户端游戏/网页游戏
  12. Vue源码剖析——render、patch、updata、vnode
  13. (2019.07) BSV 链上运算模型
  14. 从充电宝到换电站,数字孪生原来可以这样用
  15. 学习正则表达式 - 18位身份证号
  16. 如何检测计算机主板的好坏,主机电源怎么测试好坏
  17. 自定义View-波浪动效
  18. selenium优缺点_Selenium测试自动化工具的优缺点
  19. Java面试题:GC 是什么? 为什么要有GC?
  20. 百度地图 - 绘制驾车路线图

热门文章

  1. ❤echarts 南丁格尔玫瑰图的使用以及南丁格尔玫瑰图详细配置
  2. 用turtle画各种各样的数学图形
  3. rx6600怎么样 rx6600显卡相当于什么n卡
  4. FLOJET NEMP50/7泵
  5. oracle 发的邮件qq,python基于SMTP发送QQ邮件
  6. mouseover,mouseout,mouseenter,mouseleave,hover
  7. 测试的发展前景怎么样?
  8. python中绘制柱形图、饼形图等
  9. python链家数据分析统计服_链家二手房成交——Python数据分析
  10. 为程序员更新了Joel测试