zoukankan      html  css  js  c++  java
  • 通过阳历生日计算星座,阴历生日,生辰八字,生肖五行

    首先定义一个生日属性的实体对象:

    @Getter
    @Setter
    public class BirthInfo {
    
        // 阳历
        // 日期
        private String solarDay;
        // 时间,精确到分即可
        private String time;
        // 星期
        private String weekday;
        // 星座
        private String constellation;
    
        // 阴历
        // 阴历年
        private String lunarYear;
        // 阴历月日
        private String lunarDay;
        // 生辰
        private String period;
        // 属相
        private String zodiac;
        // 八字
        private String bazi;
        // 五行
        private String wuxing;
        private String wuxingDesc;
    
        @Override
        public String toString() {
            return solarDay + " " + time + "
    " + weekday + "
    " + constellation + "
    
    " + lunarYear
                    + lunarDay + "
    " + period + "
    " + zodiac + "
    " + bazi + "
    " + wuxing + "
    " + wuxingDesc;
        }
    }

    传入日期格式“1999-12-12 12:12”,调用guess得出计算结果:

    public class BirthInfoGuess {
    
        private static final String PATTERN = "yyyy-MM-dd HH:mm";
        private static DateFormat format = new SimpleDateFormat(PATTERN);
        private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern(PATTERN);
    
        private static final LocalDateTime MIN_DATE_TIME = LocalDateTime.of(1900, 1, 30, 8, 0);
        private static final LocalDateTime MAX_DATE_TIME = LocalDateTime.of(2049, 12, 31, 20, 0);
    
        public static final String[] NUMBERS = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
        public static final String[] WEEKDAYS = {"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"};
    
        public static final String[] CONSTELLATIONS = {"水瓶座", "双鱼座", "白羊座", "金牛座", "双子座", "巨蟹座", "狮子座", "处女座", "天秤座",
                "天蝎座", "射手座", "摩羯座"};
    
        public static final String[] MONTH_ALIAS = {"正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "冬月", "腊月"};
        public static final String[] DAY_ALIAS = {"初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十", "十一", "十二", "十三",
                "十四", "十五", "十六", "十七", "十八", "十九", "二十", "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"};
    
        public static final String[] GAN = {"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};
        public static final String[] ZHI = {"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};
        public static final String[] ZODIACS = {"猴", "鸡", "狗", "猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊"};
        public static final String[] PERIODS = {"子时", "丑时", "寅时", "卯时", "辰时", "巳时", "午时", "未时", "申时", "酉时", "戌时", "亥时"};
    
        public static final String[][] NIAN_SHANG_QI_YUE = {{"丙寅", "戊寅", "庚寅", "壬寅", "甲寅"},
                {"丁卯", "己卯", "辛卯", "癸卯", "乙卯"}, {"戊辰", "庚辰", "壬辰", "甲辰", "丙辰"}, {"己巳", "辛巳", "癸巳", "乙巳", "丁巳"},
                {"庚午", "壬午", "甲午", "丙午", "戊午"}, {"辛未", "癸未", "乙未", "丁未", "己未"}, {"壬申", "甲申", "丙申", "戊申", "庚申"},
                {"癸酉", "乙酉", "丁酉", "己酉", "辛酉"}, {"甲戌", "丙戌", "戊戌", "庚戌", "壬戌"}, {"乙亥", "丁亥", "己亥", "辛亥", "癸亥"},
                {"丙子", "戊子", "庚子", "壬子", "甲子"}, {"丁丑", "己丑", "辛丑", "癸丑", "乙丑"}};
    
        public static final String[][] RI_SHANG_QI_SHI = {{"甲子", "丙子", "戊子", "庚子", "壬子"}, {"乙丑", "丁丑", "己丑", "辛丑", "癸丑"},
                {"丙寅", "戊寅", "庚寅", "壬寅", "甲寅"}, {"丁卯", "己卯", "辛卯", "癸卯", "乙卯"}, {"戊辰", "庚辰", "壬辰", "甲辰", "丙辰"},
                {"己巳", "辛巳", "癸巳", "乙巳", "丁巳"}, {"庚午", "壬午", "甲午", "丙午", "戊午"}, {"辛未", "癸未", "乙未", "丁未", "己未"},
                {"壬申", "甲申", "丙申", "戊申", "庚申"}, {"癸酉", "乙酉", "丁酉", "己酉", "辛酉"}, {"甲戌", "丙戌", "戊戌", "庚戌", "壬戌"},
                {"乙亥", "丁亥", "己亥", "辛亥", "癸亥"}};
    
        private static int minYear = 1900;
        private static int maxYear = 2049;
    
        // 150年内的阴历数据,1900年到2049年
        private static final long[] LUNAR_INFO = 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};
    
        /**
         * 通过阳历日期计算阴历日期
         *
         * @param date 1990-12-12 12:12
         * @return
         */
        public static BirthInfo guess(String date) {
            LocalDateTime dateTime = LocalDateTime.parse(date, formatter);
            if (dateTime.isBefore(MIN_DATE_TIME) || dateTime.isAfter(MAX_DATE_TIME)) {
                throw new IllegalArgumentException("超出我能计算的时间范围(1900-01-30 08:00 - 2049-12-31 20:00)");
            }
    
            BirthInfo birthInfo = new BirthInfo();
    
            // 阳历年月日
            String solarDay = date.substring(0, 10);
            String time = date.substring(11);
            int weekday = dateTime.getDayOfWeek().getValue();
            birthInfo.setSolarDay(solarDay);
            birthInfo.setTime(time);
            birthInfo.setWeekday(WEEKDAYS[weekday - 1]);
    
            // 计算星座
            String constellation = getConstellation(dateTime.getMonthValue(), dateTime.getDayOfMonth());
            birthInfo.setConstellation(constellation);
    
            int i = 0;
            int temp = 0;
            int lunarYear;
            int lunarMonth;
            int lunarDayOfMonth;
            boolean isLeapYear = false;
            int offset = (int) MIN_DATE_TIME.until(dateTime, ChronoUnit.DAYS);
    
            for (i = minYear; i <= maxYear; i++) {
                temp = daysOfLunarYear(i);
                if (offset - temp < 1) {
                    break;
                } else {
                    offset -= temp;
                }
            }
    
            lunarYear = i;
            int leapMonth = getLeapMonth(lunarYear);
            isLeapYear = leapMonth > 0;
    
            // 计算每个月的天数,以此递减
            for (i = 1; i < 13; i++) {
                if (i == leapMonth + 1 && isLeapYear) {
                    temp = daysOfLeapMonth(lunarYear);
                    isLeapYear = false;
                    i--;
                } else {
                    temp = daysOfMonth(lunarYear, i);
                }
    
                offset -= temp;
    
                if (offset <= 0) {
                    break;
                }
            }
    
            offset += temp;
            lunarMonth = i;
            lunarDayOfMonth = offset;
    
            // 阴历年月日
            int qian = lunarYear / 1000;
            int bai = (lunarYear - 1000 * qian) / 100;
            int shi = (lunarYear - 1000 * qian - 100 * bai) / 10;
            int ge = lunarYear % 10;
            String year = NUMBERS[qian] + NUMBERS[bai] + NUMBERS[shi] + NUMBERS[ge];
            String ganzhiYear = getGanzhi(lunarYear);
            String lunarDay = MONTH_ALIAS[lunarMonth - 1] + DAY_ALIAS[lunarDayOfMonth - 1];
            birthInfo.setLunarYear(year + ganzhiYear + "年");
            birthInfo.setLunarDay(lunarDay);
    
            // 时辰
            int hour = dateTime.getHour();
            String period = getPeriod(hour);
            birthInfo.setPeriod(period);
    
            // 生肖
            String zodiac = getZodiac(lunarYear);
            birthInfo.setZodiac(zodiac);
    
            // 年上起月
            String ganzhiMonth = getGanzhiMonth(ganzhiYear, lunarMonth);
            // 纪日
            String ganzhiDay = getGanzhiDay(solarDay);
            // 日上起时
            String ganzhiTime = getGanzhiTime(ganzhiDay, hour);
            birthInfo.setBazi(ganzhiYear + " " + ganzhiMonth + " " + ganzhiDay + " " + ganzhiTime);
    
            // 五行,五行属性是以日干为准
            String[] wuxing = getWuxing(ganzhiYear, ganzhiMonth, ganzhiDay, ganzhiTime);
            String wuxingDesc = generateWuxingDesc(wuxing);
            birthInfo.setWuxing(wuxing[4]);
            birthInfo.setWuxingDesc(wuxingDesc);
    
            return birthInfo;
        }
    
        /**
         * 计算星座
         *
         * @param month
         * @param day
         * @return
         */
        private static String getConstellation(int month, int day) {
            switch (month) {
                case 1:
                    return day < 20 ? "摩羯座" : "水瓶座";
                case 2:
                    return day < 19 ? "水瓶座" : "双鱼座";
                case 3:
                    return day < 21 ? "双鱼座" : "白羊座";
                case 4:
                    return day < 21 ? "白羊座" : "金牛座";
                case 5:
                    return day < 21 ? "金牛座" : "双子座";
                case 6:
                    return day < 22 ? "双子座" : "巨蟹座";
                case 7:
                    return day < 23 ? "巨蟹座" : "狮子座";
                case 8:
                    return day < 23 ? "狮子座" : "处女座";
                case 9:
                    return day < 23 ? "处女座" : "天秤座";
                case 10:
                    return day < 24 ? "天秤座" : "天蝎座";
                case 11:
                    return day < 22 ? "天蝎座" : "射手座";
                case 12:
                    return day < 22 ? "射手座" : "摩羯座";
                default:
                    return "神秘星座";
            }
        }
    
        /**
         * 根据小时计算时辰
         *
         * @param hour
         * @return
         */
        private static String getPeriod(int hour) {
            switch (hour) {
                case 23:
                case 0:
                    return PERIODS[0];
                case 1:
                case 2:
                    return PERIODS[1];
                case 3:
                case 4:
                    return PERIODS[2];
                case 5:
                case 6:
                    return PERIODS[3];
                case 7:
                case 8:
                    return PERIODS[4];
                case 9:
                case 10:
                    return PERIODS[5];
                case 11:
                case 12:
                    return PERIODS[6];
                case 13:
                case 14:
                    return PERIODS[7];
                case 15:
                case 16:
                    return PERIODS[8];
                case 17:
                case 18:
                    return PERIODS[9];
                case 19:
                case 20:
                    return PERIODS[10];
                case 21:
                case 22:
                    return PERIODS[11];
                default:
                    return PERIODS[0];
            }
        }
    
        /**
         * 计算阴历年的总天数
         *
         * @param year
         * @return
         */
        private static int daysOfLunarYear(int year) {
            int sum = 29 * 12;
            for (int i = 0x8000; i >= 0x8; i >>= 1) {
                if ((LUNAR_INFO[year - 1900] & 0xfff0 & i) != 0) {
                    sum++;
                }
            }
    
            return sum + daysOfLeapMonth(year);
        }
    
        /**
         * 计算阴历年闰月天数
         *
         * @param year
         * @return
         */
        private static int daysOfLeapMonth(int year) {
            if (getLeapMonth(year) == 0) {
                return 0;
            } else {
                if ((LUNAR_INFO[year - 1900] & 0xf0000) == 0) {
                    return 29;
                } else {
                    return 30;
                }
            }
        }
    
        /**
         * 计算阴历阴历年某月的天数
         *
         * @param year
         * @param month
         * @return
         */
        private static int daysOfMonth(int year, int month) {
            if ((month > 12) || (month < 0)) {
                // 月份有错
                return 0;
            }
    
            int bit = 1 << (16 - month);
            if (((LUNAR_INFO[year - 1900] & 0x0FFFF) & bit) == 0) {
                return 29;
            } else {
                return 30;
            }
        }
    
        /**
         * 计算阴历年润哪个月,没有则返回0
         *
         * @param year
         * @return
         */
        private static int getLeapMonth(int year) {
            return (int) (LUNAR_INFO[year - 1900] & 0xf);
        }
    
        /**
         * 根据阴历年计算干支
         *
         * @param year
         * @return
         */
        private static String getGanzhi(int year) {
            int ganN = year % 10;
            if (ganN <= 3) {
                ganN = ganN + 10 - 3 - 1;
            } else {
                ganN = ganN - 3 - 1;
            }
    
            int zhiN = year % 12;
            if (zhiN <= 3) {
                zhiN = zhiN + 12 - 3 - 1;
            } else {
                zhiN = zhiN - 3 - 1;
            }
    
            return GAN[ganN] + ZHI[zhiN];
        }
    
        /**
         * 根据阴历年计算生肖
         *
         * @param year
         * @return
         */
        private static String getZodiac(int year) {
            int zhiN = year % 12;
            return ZODIACS[zhiN];
        }
    
        /**
         * 年上起月
         *
         * @return
         */
        private static String getGanzhiMonth(String ganZhiYear, int month) {
            String nianGan = ganZhiYear.substring(0, 1);
            if ("甲".equals(nianGan) || "己".equals(nianGan)) {
                return NIAN_SHANG_QI_YUE[month - 1][0];
            } else if ("乙".equals(nianGan) || "庚".equals(nianGan)) {
                return NIAN_SHANG_QI_YUE[month - 1][1];
            } else if ("丙".equals(nianGan) || "辛".equals(nianGan)) {
                return NIAN_SHANG_QI_YUE[month - 1][2];
            } else if ("丁".equals(nianGan) || "壬".equals(nianGan)) {
                return NIAN_SHANG_QI_YUE[month - 1][3];
            } else if ("戊".equals(nianGan) || "癸".equals(nianGan)) {
                return NIAN_SHANG_QI_YUE[month - 1][4];
            } else {
                return "未知";
            }
        }
    
        /**
         * 纪日
         *
         * @param solarDay
         * @return
         */
        private static String getGanzhiDay(String solarDay) {
            int C = Integer.parseInt(solarDay.substring(0, 2));
            int Y = Integer.parseInt(solarDay.substring(2, 4));
            int M = Integer.parseInt(solarDay.substring(5, 7));
            if (M == 1 || M == 2) {
                int year = Integer.parseInt(solarDay.substring(0, 4)) - 1;
                C = year / 100;
                Y = year % 100;
                M += 12;
            }
            int D = Integer.parseInt(solarDay.substring(8));
            int i = ((M & 1) == 1) ? 0 : 6;
    
            int G = 4 * C + (int) (C / 4) + 5 * Y + (int) (Y / 4) + (int) (3 * (M + 1) / 5) + D - 3;
            int Z = 4 * C + G + 10 + i;
    
            int indexG = G % 10;
            indexG = (indexG == 0) ? 9 : (indexG - 1);
    
            int indexZ = Z % 12;
            indexZ = (indexZ == 0) ? 11 : (indexZ - 1);
    
            return GAN[indexG] + ZHI[indexZ];
        }
    
        /**
         * 日上起时
         *
         * @param ganZhiDay
         * @param time
         * @return
         */
        private static String getGanzhiTime(String ganZhiDay, int time) {
            String tianGan = ganZhiDay.substring(0, 1);
            if ((time & 1) == 1) {
                time = (time + 1) / 2;
            } else {
                time = time / 2;
            }
    
            if ("甲".equals(tianGan) || "己".equals(tianGan)) {
                return RI_SHANG_QI_SHI[time][0];
            } else if ("乙".equals(tianGan) || "庚".equals(tianGan)) {
                return RI_SHANG_QI_SHI[time][1];
            } else if ("丙".equals(tianGan) || "辛".equals(tianGan)) {
                return RI_SHANG_QI_SHI[time][2];
            } else if ("丁".equals(tianGan) || "壬".equals(tianGan)) {
                return RI_SHANG_QI_SHI[time][3];
            } else if ("戊".equals(tianGan) || "癸".equals(tianGan)) {
                return RI_SHANG_QI_SHI[time][4];
            } else {
                return "未知";
            }
        }
    
        private static String[] getWuxing(String ganZhiYear, String ganZhiMonth, String ganZhiDay, String ganZhiTime) {
            String[] wuxing = new String[8];
            wuxing[0] = getWuxingByGan(ganZhiYear.substring(0, 1));
            wuxing[1] = getWuxingByZhi(ganZhiYear.substring(1));
            wuxing[2] = getWuxingByGan(ganZhiMonth.substring(0, 1));
            wuxing[3] = getWuxingByZhi(ganZhiMonth.substring(1));
            wuxing[4] = getWuxingByGan(ganZhiDay.substring(0, 1));
            wuxing[5] = getWuxingByZhi(ganZhiDay.substring(1));
            wuxing[6] = getWuxingByGan(ganZhiTime.substring(0, 1));
            wuxing[7] = getWuxingByZhi(ganZhiTime.substring(1));
            return wuxing;
        }
    
        private static String getWuxingByGan(String gan) {
            if ("甲".equals(gan) || "乙".equals(gan)) {
                return "木";
            } else if ("丙".equals(gan) || "丁".equals(gan)) {
                return "火";
            } else if ("戊".equals(gan) || "己".equals(gan)) {
                return "土";
            } else if ("庚".equals(gan) || "辛".equals(gan)) {
                return "金";
            } else {
                return "水";
            }
        }
    
        private static String getWuxingByZhi(String zhi) {
            if ("寅".equals(zhi) || "卯".equals(zhi) || "辰".equals(zhi)) {
                return "木";
            } else if ("巳".equals(zhi) || "午".equals(zhi) || "未".equals(zhi)) {
                return "火";
            } else if ("申".equals(zhi) || "酉".equals(zhi) || "戌".equals(zhi)) {
                return "金";
            } else if ("亥".equals(zhi) || "子".equals(zhi) || "丑".equals(zhi)) {
                return "水";
            } else {
                return "土";
            }
        }
    
        private static String generateWuxingDesc(String[] wuxing) {
            StringBuilder desc = new StringBuilder(String.join("", wuxing));
            List<String> wuxingList = Arrays.asList(wuxing);
            if (!wuxingList.contains("金")) {
                desc.append(",五行缺金");
            } else if (!wuxingList.contains("木")) {
                desc.append(",五行缺木");
            } else if (!wuxingList.contains("水")) {
                desc.append(",五行缺水");
            } else if (!wuxingList.contains("火")) {
                desc.append(",五行缺火");
            } else if (!wuxingList.contains("土")) {
                desc.append(",五行缺土");
            } else {
                desc.append(",五行不缺");
            }
    
            return desc.toString();
        }
    
        public static void main(String[] args) {
            String birthday = "1989-01-03 14:15";
            System.out.println(guess(birthday));
        }
    }

    输出如下:

  • 相关阅读:
    一周小记(十七)
    一周小记(十九)
    2021/12/28组会
    AdaIN论文阅读(Arbitrary Style Transfer in Realtime with Adaptive Instance Normalization)
    PostgreSQL新增、更新、删除触发器
    leetcodedphard最小距离
    leetcodedp编辑距离问题两个字符串的删除操作
    正向代理代理客服端,反向代理代理服务器
    mybatisplus逻辑删除 3.1一下版本
    Eclipse使用指定JDK,无需配置Path变量
  • 原文地址:https://www.cnblogs.com/zhou-920644981/p/12221828.html
Copyright © 2011-2022 走看看