某一天看日历的时候,突然注意到日历里的干支,了解了一下,感觉很有意思,想搜一下怎么用java实现,发现很多只有计算年干支,没有月日时,于是就写了个工具类,年月时参考了百度百科里的计算方式,日干支的计算公式是使用《高氏日柱公式》

日干支参考高氏日柱公式
年、月、时干支参考百度百科

依赖hutool

        <!-- hutool工具类 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.5.1</version></dependency>

计算年月日时干支工具类

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;import java.util.*;/*** 获取阳历日期的年月日时干支 只支持1900-02-04至2050-01-22 (1900-02-04前按节气划分为1989年,2050-01-22之后为农历二〇五〇年,转阴历用的lunarInfo只到2049年)* 日干支参考: https://zhuanlan.zhihu.com/p/93508430* 年、月、时干支参考百度百科: https://baike.baidu.com/item/%E5%A4%A9%E5%B9%B2%E5%9C%B0%E6%94%AF/278140?fromModule=lemma-qiyi_sense-lemma** @author Administrator*/
public class DateStemBranchUtils {protected static final String[] HEAVENLY_STEM = {"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};protected static final String[] EARTHLY_BRANCHES = {"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};/*** 时辰数组*/protected static final Integer[][] HOUR_ARRAY = {{23, 1}, {1, 3}, {3, 5}, {5, 7}, {7, 9}, {9, 11}, {11, 13}, {13, 15}, {15, 17}, {17, 19}, {19, 21}, {21, 23}};/*** 按照年份计算世纪* 此方法只应用于计算世纪常数,每个00年3月后记为新世纪** @param year* @return*/private static int centuryFromYear(int year, int month) {// 每个00年3月后记为新世纪if (year % 100 == 0 && month < 3) {year = year / 100;} else {year = (year / 100) + 1;}return year;}/*** 计算世纪常数* (ⅰ)每世纪的第一年是从“0”开始的,故整百整千的“世纪年”即为每世纪的第一年。例如:1900年为20世纪的第1年,其公元年份后两位为零,即s=0。* <p>* (ⅱ)世纪常数x每世纪第一年3月1日的的日柱序列数减1。* 例如:21世纪的世纪常数等于2000年3月1日的日柱(戊午)序列数减1,即x=55-1=54,同时也是-6(由于干支序列的60循环特点,而54-60=-6,在干支计算上54与-6是等价的)。** @param year* @return 世纪常数*/private static int getCenturyConstant(int year, int month) {// 世纪数 区分16世纪前后int x = 0;int n = centuryFromYear(year, month);if (n <= 16) {x = 45 * (n - 16) + 22;}if (n > 16) {x = 44 * (n - 17) + (n - 17) / 4 - 3;}return x;}/*** 1582年10月15日—1599年14月29日”期间的日柱时,必须在算式最后再减去10 其他时间无需如此。*/public static int containsSpecialDuration(int year, int month, int day) {int m = month < 3 ? (month + 12) : month;if (year > 1600 || year < 1582) {return 0;}if (year == 1582 && (m * 100 + day) < 1015) {return 0;}if (year == 1599 && (m * 100 + day) > 1429) {return 0;}return 10;}/*** 计算日干支数(干支表顺序)** @param date* @return*/public static int getStemsBranch(Date date) {int monthNum = DateUtil.month(date) + 1;int yearNum = DateUtil.year(date);int mon = monthNum < 3 ? (monthNum + 12) : monthNum;String year = String.valueOf(yearNum);// s:公元年数后两位数, 取整数值,month < 3时,年份-1(当成前一年算)int s;if (monthNum < 3) {if (yearNum % 100 == 0) {s = 99;} else {s = Integer.parseInt(year.substring(2)) - 1;}} else {s = Integer.parseInt(year.substring(2));}int sd4 = s / 4;// u:s除以4的余数int u = s % 4;int cal = (3 * mon - 7) / 5;// m:月数int m = (int) (30 * ((Math.pow(-1, mon) + 1) / 2) + cal);// d:日期数int d = DateUtil.dayOfMonth(date);// x:世纪常数int x = getCenturyConstant(yearNum, monthNum) % 60;// 在计算“1582年10月15日—1599年14月29日”期间的日柱时,必须在算式最后再减去10int specialDuration = containsSpecialDuration(yearNum, monthNum, d);// r 日柱的母数,r 除以60的余数即是日柱的干支序列数 公式:r=s/4×6+5(s/4×3+u)+m+d+xint r = (sd4 * 6) + (5 * (sd4 * 3 + u)) + m + d + x - specialDuration;int res = r % 60;return res == 0 ? 60 : res;}/*** 计算年干支(公元后)* 干:甲=4…… 支:子=4……** @param year 阴历年份* @return 年干支*/public static String calYearStemBranch(int year) {String strYear = String.valueOf(year);int lastDigitOfYear = Integer.parseInt(strYear.substring(strYear.length() - 1));// 按照天干下标从0开始,年份最后一位(<=3时借十取最后一位) - 4lastDigitOfYear = lastDigitOfYear <= 3 ? lastDigitOfYear + 10 - 4 : lastDigitOfYear - 4;String heavenlyStem = HEAVENLY_STEM[lastDigitOfYear];// 按照地支下标从0开始,(年份 + 8) % 12int remainder = (year + 8) % 12;String earthlyBranch = EARTHLY_BRANCHES[remainder];// 生肖String animal = LunarCalendarFestivalUtils.animals[(year - 4) % 12];return heavenlyStem + earthlyBranch + animal + "年";}/*** 计算月干支* 年干:甲乙丙丁……的顺序 1-10 下标0-9* 月支:寅卯……子丑的顺序(就是月份数) 1-12 下标0-11* 月干 = 年干*2+月支 大于十取个位 甲乙丙丁……的顺序 1-10 下标0-9** @param year  阴历年份 年份也是节气划分* @param month 阴历月份 是以节气划分的月份,新年不是从初一开始,从立春开始* @return 月干支*/public static String calMonthStemBranch(int year, int month) {String strYear = String.valueOf(year);// 年干数int lastDigitOfYear = Integer.parseInt(strYear.substring(strYear.length() - 1));lastDigitOfYear = lastDigitOfYear <= 3 ? lastDigitOfYear + 10 - 3 : lastDigitOfYear - 3;// 月干int monthStemNum = lastDigitOfYear * 2 + month;// 月干数最后一位int lastDigitOfMonth = Integer.parseInt(String.valueOf(monthStemNum).substring(String.valueOf(monthStemNum).length() - 1)) - 1;// 月干数组下标,如果最后一位是0 - 1,说明是癸,癸的下标是9,直接取九 否则会数组下标越界lastDigitOfMonth = lastDigitOfMonth < 0 ? 9 : lastDigitOfMonth;// 获取月支数组下标int monthBranchIndex = month >= 11 ? month - 11 : month + 1;return HEAVENLY_STEM[lastDigitOfMonth] + EARTHLY_BRANCHES[monthBranchIndex] + "月";}/*** 计算日干支** @param date 阳历日期* @return 日干支*/public static String calDayStemBranch(String date) {// 获取日干支的干支表顺序int stemBranch = getStemsBranch(DateUtil.parse(date, DatePattern.NORM_DATE_PATTERN));List<String> list = new ArrayList<>();int branchIndex = 0;// 组装干支表for (int i = 0; i < 6; i++) {for (int j = 0; j < HEAVENLY_STEM.length; j++) {if ((i * 10 + j) % 12 == 0) {branchIndex = 0;}list.add(HEAVENLY_STEM[j] + EARTHLY_BRANCHES[branchIndex]);branchIndex++;}}String[] stemBranches = list.toArray(new String[0]);return stemBranches[stemBranch - 1] + "日";}/*** 计算时干支** @param hour    24小时制的小时数* @param dayStem 日干支下标* @return 时干支*/public static String calHourStemBranch(Integer hour, int dayStem) {int branchIndex = 0;// 获取时辰地支 从丑时-亥时,没有筛选到默认为子时for (int i = 1; i < HOUR_ARRAY.length; i++) {if (hour >= HOUR_ARRAY[i][0] && hour < HOUR_ARRAY[i][1]) {branchIndex = i;}}// 子时干支int zeroStemIndex = 0;// 甲己还加甲,乙庚丙作初;丙辛从戊起,丁壬庚子居;戊癸何方发,壬子是真途switch (dayStem) {case 1:case 6:zeroStemIndex = 2;break;case 2:case 7:zeroStemIndex = 4;break;case 3:case 8:zeroStemIndex = 6;break;case 4:case 9:zeroStemIndex = 8;break;default:}// 如果是23时计算为下一天boolean nextDay = hour >= 23;int stemIndex = nextDay ? zeroStemIndex + branchIndex + 2 : zeroStemIndex + branchIndex;// 时干下标stemIndex = stemIndex > 9 ? stemIndex - 10 : stemIndex;return HEAVENLY_STEM[stemIndex] + EARTHLY_BRANCHES[branchIndex] + "时";}/*** 阳历日期计算 年月日时干支* 年用阴历年份算,正月初一为一年开始* 月用节气划分的月算,立春为一年开始* 日用阳历算** @param dateTime yyyy-MM-dd HH:mm:ss* @return 阴历日期 + 年干支 + 生肖 + 月日时干支*/public static String calStemBranch(String dateTime) {DateTime parse = DateUtil.parse(dateTime, DatePattern.NORM_DATETIME_PATTERN);String date = DateUtil.format(parse, DatePattern.NORM_DATE_PATTERN);// 获取阴历日期(yyyy-MM-dd) 阴历会有二月三十,获取不能转阳历格式,用split代替String lunarCalendar = LunarCalendarFestivalUtils.toLunarCalendar(date);// 阴历日期(一九九六年 五月三十)String calendar = LunarCalendarFestivalUtils.getLunarCalendar(date);// 阴历年份int year = Integer.parseInt(lunarCalendar.split("-")[0]);// 年干支String yearStemBranch = calYearStemBranch(year);// 计算干支纪月的年、月按照节气算,立春开始算正月,两个节气一个月int lunarTermYear = LunarCalendarFestivalUtils.getLunarTermYear(date);int lunarTermMonth = LunarCalendarFestivalUtils.getLunarTermMonth(date);// 月干支String monthStemBranch = calMonthStemBranch(lunarTermYear, lunarTermMonth);// 日干支String dayStemBranch = calDayStemBranch(date);// 获取日干下标int dayStem = LunarCalendarFestivalUtils.printArray(HEAVENLY_STEM, dayStemBranch.substring(0, 1));// 计算时干支String hourStemBranch = calHourStemBranch(DateUtil.hour(parse, true), dayStem);return calendar + " " + yearStemBranch + monthStemBranch + dayStemBranch + " " + hourStemBranch;}public static void main(String[] args) {String stemBranch = calStemBranch("2050-01-22 00:00:00");System.out.println(stemBranch);}
}

阳历转阴历工具类

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;/*** 获取输入公历日期的生肖、天干地支、农历年、农历月、农历日、公历节日、农历节日、24节气等数据* DATE 2020.08.13* 转自 https://zhuanlan.zhihu.com/p/293819435* 阴历96年修正参考 https://blog.csdn.net/shuaiziyihao/article/details/46841843*/
public class LunarCalendarFestivalUtils {//生肖年private String animal;//干支年private String ganZhiYear;//阴历年private String lunarYear;private int lunarYearNum;//阴历月private String lunarMonth;private int lunarMonthNum;//阴历日private String lunarDay;private int lunarDayNum;//阳历节日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;}public int getLunarYearNum() {return lunarYearNum;}public int getLunarMonthNum() {return lunarMonthNum;}public int getLunarDayNum() {return lunarDayNum;}// 修正1996 0x055c0 -> 0x059c0final 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, 0x059c0, 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[]{"小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏","小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"};// 划分月份的十二个节气static final String[] terms = 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);} else {return 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 "初十";} else {return chineseTen[day / 10] + lunarNumber[n];}}/*** 特例,特殊的年分的节气偏移量,由于公式并不完善,所以算出的个别节气的第几天数并不准确,在此返回其偏移量** @param year 年份* @param n    节气编号* @return 返回其偏移量*/private static 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 static 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 static int sTerm(int year, int n) {double centuryValue = 0;//节气的世纪值,每个节气的每个世纪值都不同int centuryIndex = -1;if (year >= 1900 && year <= 2000) {//20世纪centuryIndex = 0;} else if (year >= 2001 && year <= 2050) {//21世纪centuryIndex = 1;} else {throw new RuntimeException("不支持此年份:" + year + ",目前只支持1900年2月4日到2050年1月22日期间的计算");}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;}/*** 输入公历日期初始化当前日期的生肖、天干地支、农历年、农历月、农历日、公历节日、农历节日、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 + "");this.lunarYearNum = 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);} else {daysOfMonth = 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];this.lunarMonthNum = iMonth;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);this.lunarDayNum = 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 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 date 阳历 yyyy-MM-dd* @return 阴历 yyyy-MM-dd*/public static String toLunarCalendar(String date) {LunarCalendarFestivalUtils festival = new LunarCalendarFestivalUtils();festival.initLunarCalendarInfo(date);return festival.getLunarYearNum() + "-" + String.format("%02d", festival.getLunarMonthNum()) + "-" + String.format("%02d", festival.getLunarDayNum());}/*** 获取阴历日期* @param date 阳历日期* @return 阴历大写日期*/public static String getLunarCalendar(String date) {LunarCalendarFestivalUtils festival = new LunarCalendarFestivalUtils();festival.initLunarCalendarInfo(date);return festival.getLunarYear() + "年 " + festival.getLunarMonth() + "月" + festival.getLunarDay();}/*** 遍历数组 获取元素在数组的下标* @param array 数组* @param value 元素* @return 下标*/public static int printArray(String[] array, String value) {for (int i = 0; i < array.length; i++) {if (Objects.equals(array[i], value)) {return i;}}return -1;//当if条件不成立时,默认返回一个负数值-1}/*** 获取某年的第n个节气为几日(从0小寒起算)** @param year 年* @param month 月* @param n 节气顺序 从0小寒起算* @return 阳历日期*/private static String getLunarTermDay(int year, int month, int n) {int day = sTerm(year, n);// 拼成节气的阳历日期return year + "-" + String.format("%02d", month) + "-" + String.format("%02d", day);}/*** 按节气划分月份* @param date 阳历日期* @return 干支纪月的月份 (节气划分的月份)*/public static int getLunarTermMonth(String date) {// 获取以节气划分的年份int year = getLunarTermYear(date);// 从2月开始获取本年每月第一个节气、下一年的1月第一个节气,还有下一年的立春日期String[] solarTermDates = new String[13];for (int i = 0; i < terms.length; i++) {String solarTermDate;// 小寒 当年的1月是上一年的小寒,本年的小寒在下一年1月if (i == terms.length - 1) {solarTermDate = getLunarTermDay(year + 1, 1, printArray(solarTerms, terms[i]));} else {// 节气的日期(阳历) 立春-大雪solarTermDate = getLunarTermDay(year, i + 2, printArray(solarTerms, terms[i]));}// 节气日期solarTermDates[i] = solarTermDate;}// 获取下一年的立春日期solarTermDates[12] = getLunarTermDay(year + 1, 2, printArray(solarTerms, terms[0]));// 按节气划分月份String[][] dateScope = new String[12][2];for (int i = 0; i < dateScope.length; i++) {dateScope[i][0] = solarTermDates[i];dateScope[i][1] = solarTermDates[i + 1];}// dateScope 下标+1就是干支纪月的月份for (int i = 0; i < dateScope.length; i++) {// if 日期在某两个节气区间if (DateUtil.isIn(DateUtil.parse(date, DatePattern.NORM_DATE_PATTERN),DateUtil.parse(dateScope[i][0], DatePattern.NORM_DATE_PATTERN),DateUtil.offsetDay(DateUtil.parse(dateScope[i][1], DatePattern.NORM_DATE_PATTERN), -1))) {return i + 1;}}return 0;}/*** 按节气划分年份* @param date 阳历日期* @return 干支纪月的年份 立春前算前一年*/public static int getLunarTermYear(String date) {String[] splitDate = date.split("-");int year = Integer.parseInt(splitDate[0]);// 获取当年立春,确定日期在立春前后,立春前需要按照上一年算, 当前日期 < 立春时,年份-1String currSpringDate = getLunarTermDay(year, 2, printArray(solarTerms, terms[0]));if (DateUtil.compare(DateUtil.parse(date, DatePattern.NORM_DATE_PATTERN), DateUtil.parse(currSpringDate, DatePattern.NORM_DATE_PATTERN)) < 0) {year = year - 1;}return year;}
}

结果示例:

一九九六年 六月初一 丙子鼠年乙未月甲寅日 甲子时

java 阳历日期时间获取年月日时干支相关推荐

  1. 【Java】Date类型获取年月日时分秒的两种方法(12小时制、24小时制)

    Java的Date类型是,提供用来描述日期时间的类,它可以存储时间的年月日.时分秒的信息.但是如何从Date的实例中获取这些信息呢? 以前Date提供了一系列的get方法来获取,但是这些方法现在都被弃 ...

  2. js 日期时间格式化,年月日时分秒

    1. formatDate.js export function formatDate(date, fmt) {var currentDate = new Date(date);var o = {&q ...

  3. JAVA 获取当前时间(年月日时分秒)

    LocalDateTime单独获取年月日和时分秒 LocalDateTime localDateTime = LocalDateTime.now(); localDateTime.format(Dat ...

  4. java Date获取 年月日时分秒

    转载自   java Date获取 年月日时分秒 package com.util;import java.text.DateFormat; import java.util.Calendar; im ...

  5. java去掉date分时秒_java Date获取年月日时分秒的实现方法

    java date获取年月日时分秒的实现方法 package com.util; import java.text.dateformat; import java.util.calendar; imp ...

  6. android获取年月日时分秒毫秒,Android获取两个日期其间间隔的天数

    /** * 获取两个日期之间的间隔天数 * @return */ public static int getGapCount(Date startDate, Date endDate) { Calen ...

  7. java时间格式化取月份_Java格式化时间获取年月日

    Java格式化时间获取年月日 import java.util.Date; class Untitled { public static void main(String[] args) { Date ...

  8. python 获取当前时间(年月日时分秒)

    python 获取当前时间(年月日时分秒) now_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())

  9. JS获取当前时间(年月日时分秒)

    JS获取当前时间(年月日时分秒) JS获取当前时间(年月日时分秒) 代码直接撸: **拿走直接用 `//获取当前时间 getNowTime() { var date = new Date(); //年 ...

  10. js获取年月日 时分秒的日期格式

    const date = new Date() const year = date.getFullYear() const month = date.getMonth() + 1 >= 10 ? ...

最新文章

  1. linux C函数之access函数的用法
  2. 【数据结构与算法-2】链表
  3. element ui 获取文件的路径_win10使用WinAppDriver实现UI自动化
  4. Halcon学习笔记:select_points_object_model_3d(3D对象模型阀值分割)
  5. [算法总结] 13 道题搞定 BAT 面试——字符串
  6. 基于JAVA+SpringMVC+MYSQL的医院分诊挂号管理系统
  7. 1组第一次作业-小组自我介绍
  8. ffdshow 源代码分析 6: 对解码器的dll的封装(libavcodec)
  9. 编程菜鸟的日记-初学尝试编程递归
  10. http://nuyd.eastmoney.com/EM_UBG_PositionChangesInterface/api/js?rows=64page=9
  11. powerquery加载pdf_老板让我汇总PDF文件,我不会,同事用Excel两分钟就搞定
  12. python学习笔记4-切片
  13. 在Spring3中使用注解(@Scheduled)创建计划任务
  14. 一个数据分析报告的框架,主要包含哪几项?
  15. 元宇宙游戏项目:Decentraland(治理通证:MANA)
  16. ansys workbench17.0 lsdyna模块设置时间步长
  17. PTA-输出大写英文字母
  18. python3APP爬虫--爬取王者荣耀小姐姐cosplay照片(附源码)
  19. 西安知名IT互联网公司—为自己回西安做铺垫
  20. 4.java基础-static

热门文章

  1. Android studio真机运行失败,提示“软件包似乎无效” “应用程序安装异常(-15)”
  2. 使用Amazon SageMaker RL训练离线强化学习策略
  3. mybatiplus的apply_mybatis-plus入门
  4. ospf路由 华3_华三路由器命令信息
  5. pandas 取每天某个时刻的数据
  6. matlab条件统计个数,matlab计算条件概率
  7. 计算机isas测试,SAS硬盘测试:15,000转对决10,000转
  8. 通过PS制作逼真的车窗玻璃雨滴效果
  9. 掌握如何使用Rose绘制活动图的方法
  10. php通过JODConverter将word转换为pdf