最主要的功能就是农历转新历的工具类

package cn.hui.pm.utils;import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;/*** 工具类,实现阴阳历互转*/
public class LunarCalendarUtil {/*** 支持转换的最小农历年份*/public static final int MIN_YEAR = 1900;/*** 支持转换的最大农历年份*/public static final int MAX_YEAR = 2099;/*** 公历每月前的天数*/private static final int[] DAYS_BEFORE_MONTH = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};/*** 用来表示1900年到2099年间农历年份的相关信息,共24位bit的16进制表示,其中:* 1. 前4位表示该年闰哪个月;* 2. 5-17位表示农历年份13个月的大小月分布,0表示小,1表示大;* 3. 最后7位表示农历年首(正月初一)对应的公历日期。* 以2014年的数据0x955ABF为例说明:* 1001 0101 0101 1010 1011 1111*  闰九月   农历正月初一对应公历1月31号*/private static final int[] LUNAR_INFO = {/*1900*/0x84B6BF,/*1901-1910*/0x04AE53, 0x0A5748, 0x5526BD, 0x0D2650, 0x0D9544, 0x46AAB9, 0x056A4D, 0x09AD42, 0x24AEB6, 0x04AE4A,/*1911-1920*/0x6A4DBE, 0x0A4D52, 0x0D2546, 0x5D52BA, 0x0B544E, 0x0D6A43, 0x296D37, 0x095B4B, 0x749BC1, 0x049754,/*1921-1930*/0x0A4B48, 0x5B25BC, 0x06A550, 0x06D445, 0x4ADAB8, 0x02B64D, 0x095742, 0x2497B7, 0x04974A, 0x664B3E,/*1931-1940*/0x0D4A51, 0x0EA546, 0x56D4BA, 0x05AD4E, 0x02B644, 0x393738, 0x092E4B, 0x7C96BF, 0x0C9553, 0x0D4A48,/*1941-1950*/0x6DA53B, 0x0B554F, 0x056A45, 0x4AADB9, 0x025D4D, 0x092D42, 0x2C95B6, 0x0A954A, 0x7B4ABD, 0x06CA51,/*1951-1960*/0x0B5546, 0x555ABB, 0x04DA4E, 0x0A5B43, 0x352BB8, 0x052B4C, 0x8A953F, 0x0E9552, 0x06AA48, 0x6AD53C,/*1961-1970*/0x0AB54F, 0x04B645, 0x4A5739, 0x0A574D, 0x052642, 0x3E9335, 0x0D9549, 0x75AABE, 0x056A51, 0x096D46,/*1971-1980*/0x54AEBB, 0x04AD4F, 0x0A4D43, 0x4D26B7, 0x0D254B, 0x8D52BF, 0x0B5452, 0x0B6A47, 0x696D3C, 0x095B50,/*1981-1990*/0x049B45, 0x4A4BB9, 0x0A4B4D, 0xAB25C2, 0x06A554, 0x06D449, 0x6ADA3D, 0x0AB651, 0x095746, 0x5497BB,/*1991-2000*/0x04974F, 0x064B44, 0x36A537, 0x0EA54A, 0x86B2BF, 0x05AC53, 0x0AB647, 0x5936BC, 0x092E50, 0x0C9645,/*2001-2010*/0x4D4AB8, 0x0D4A4C, 0x0DA541, 0x25AAB6, 0x056A49, 0x7AADBD, 0x025D52, 0x092D47, 0x5C95BA, 0x0A954E,/*2011-2020*/0x0B4A43, 0x4B5537, 0x0AD54A, 0x955ABF, 0x04BA53, 0x0A5B48, 0x652BBC, 0x052B50, 0x0A9345, 0x474AB9,/*2021-2030*/0x06AA4C, 0x0AD541, 0x24DAB6, 0x04B64A, 0x6a573D, 0x0A4E51, 0x0D2646, 0x5E933A, 0x0D534D, 0x05AA43,/*2031-2040*/0x36B537, 0x096D4B, 0xB4AEBF, 0x04AD53, 0x0A4D48, 0x6D25BC, 0x0D254F, 0x0D5244, 0x5DAA38, 0x0B5A4C,/*2041-2050*/0x056D41, 0x24ADB6, 0x049B4A, 0x7A4BBE, 0x0A4B51, 0x0AA546, 0x5B52BA, 0x06D24E, 0x0ADA42, 0x355B37,/*2051-2060*/0x09374B, 0x8497C1, 0x049753, 0x064B48, 0x66A53C, 0x0EA54F, 0x06AA44, 0x4AB638, 0x0AAE4C, 0x092E42,/*2061-2070*/0x3C9735, 0x0C9649, 0x7D4ABD, 0x0D4A51, 0x0DA545, 0x55AABA, 0x056A4E, 0x0A6D43, 0x452EB7, 0x052D4B,/*2071-2080*/0x8A95BF, 0x0A9553, 0x0B4A47, 0x6B553B, 0x0AD54F, 0x055A45, 0x4A5D38, 0x0A5B4C, 0x052B42, 0x3A93B6,/*2081-2090*/0x069349, 0x7729BD, 0x06AA51, 0x0AD546, 0x54DABA, 0x04B64E, 0x0A5743, 0x452738, 0x0D264A, 0x8E933E,/*2091-2099*/0x0D5252, 0x0DAA47, 0x66B53B, 0x056D4F, 0x04AE45, 0x4A4EB9, 0x0A4D4C, 0x0D1541, 0x2D92B5};/*** 将农历日期转换为公历日期* @param year    农历年份* @param month   农历月* @param monthDay   农历日* @param isLeapMonth   该月是否是闰月(该参数可以根据本类中leapMonth()方法,先判断一下要查询的年份是否有闰月,并且闰的几月)* @return 返回农历日期对应的公历日期,year0, month1, day2.*/public static final Date lunarToSolar(int year, int month, int monthDay, boolean isLeapMonth){int dayOffset;int leapMonth;int i;if (year < MIN_YEAR || year > MAX_YEAR || month < 1 || month > 12|| monthDay < 1 || monthDay > 30) {throw new IllegalArgumentException("Illegal lunar date, must be like that:\n\t" +"year : 1900~2099\n\t" +"month : 1~12\n\t" +"day : 1~30");}dayOffset = (LUNAR_INFO[year - MIN_YEAR] & 0x001F) - 1;if (((LUNAR_INFO[year - MIN_YEAR] & 0x0060) >> 5) == 2) {dayOffset += 31;}for (i = 1; i < month; i++) {if ((LUNAR_INFO[year - MIN_YEAR] & (0x80000 >> (i - 1))) == 0) {dayOffset += 29;} else {dayOffset += 30;}}dayOffset += monthDay;leapMonth = (LUNAR_INFO[year - MIN_YEAR] & 0xf00000) >> 20;// 这一年有闰月if (leapMonth != 0) {if (month > leapMonth || (month == leapMonth && isLeapMonth)) {if ((LUNAR_INFO[year - MIN_YEAR] & (0x80000 >> (month - 1))) == 0) {dayOffset += 29;} else {dayOffset += 30;}}}if (dayOffset > 366 || (year % 4 != 0 && dayOffset > 365)) {year += 1;if (year % 4 == 1) {dayOffset -= 366;} else {dayOffset -= 365;}}int[] solarInfo = new int[3];for (i = 1; i < 13; i++) {int iPos = DAYS_BEFORE_MONTH[i];if (year % 4 == 0 && i > 2) {iPos += 1;}if (year % 4 == 0 && i == 2 && iPos + 1 == dayOffset) {solarInfo[1] = i;solarInfo[2] = dayOffset - 31;break;}if (iPos >= dayOffset) {solarInfo[1] = i;iPos = DAYS_BEFORE_MONTH[i - 1];if (year % 4 == 0 && i > 2) {iPos += 1;}if (dayOffset > iPos) {solarInfo[2] = dayOffset - iPos;} else if (dayOffset == iPos) {if (year % 4 == 0 && i == 2) {solarInfo[2] = DAYS_BEFORE_MONTH[i] - DAYS_BEFORE_MONTH[i - 1] + 1;} else {solarInfo[2] = DAYS_BEFORE_MONTH[i] - DAYS_BEFORE_MONTH[i - 1];}} else {solarInfo[2] = dayOffset;}break;}}solarInfo[0] = year;String date = solarInfo[0] + "-" + solarInfo[1] + "-" + solarInfo[2];return strToDate(date);}/*** 将公历日期转换为农历日期,且标识是否是闰月* (如果当年有闰月,被闰的阴历月份所对应的阳历日期计算出来不对,后期自己根据本方法leap3 返回值判断如果为1,给月份+1,如果为0就是正确的,不用在操作,阴历闰月对应的阳历日期计算出来的阴历闰月日期正确,leap3为0)* @param year* @param month 传入需要为单数如 08 为8* @param monthDay* @return 返回公历日期对应的农历日期,year0,month1,day2,leap3(0 为计算正常  1 月份会比正确少一个月,需要月份+1)*/public static final Date solarToLunar(int year, int month, int monthDay) {int[] lunarDate = new int[4];Date baseDate = new GregorianCalendar(1900, 0, 31).getTime();Date objDate = new GregorianCalendar(year, month - 1, monthDay).getTime();int offset = (int) ((objDate.getTime() - baseDate.getTime()) / 86400000L);// 用offset减去每农历年的天数计算当天是农历第几天// iYear最终结果是农历的年份, offset是当年的第几天int iYear, daysOfYear = 0;for (iYear = MIN_YEAR; iYear <= MAX_YEAR && offset > 0; iYear++) {daysOfYear = daysInLunarYear(iYear);offset -= daysOfYear;}if (offset < 0) {offset += daysOfYear;iYear--;}// 农历年份lunarDate[0] = iYear;int leapMonth = leapMonth(iYear);// 闰哪个月,1-12boolean isLeap = false;// 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天int iMonth, daysOfMonth = 0;for (iMonth = 1; iMonth <= 13 && offset > 0; iMonth++) {daysOfMonth = daysInLunarMonth(iYear, iMonth);offset -= daysOfMonth;}// 当前月超过闰月,要校正if (leapMonth != 0 && iMonth > leapMonth) {--iMonth;if (iMonth == leapMonth) {isLeap = true;}}// offset小于0时,也要校正if (offset < 0) {offset += daysOfMonth;--iMonth;}lunarDate[1] = iMonth;lunarDate[2] = offset + 1;lunarDate[3] = isLeap ? 1 : 0;String date = lunarDate[0] + "-" + lunarDate[1] + "-" + lunarDate[2];return strToDate(date);}/*** 传回农历year年month月的总天数** @param year   要计算的年份* @param month        要计算的月* @return 传回天数*/final public static int daysInMonth(int year, int month) {return daysInMonth(year, month, false);}/*** 传回农历year年month月的总天数** @param year   要计算的年份* @param month    要计算的月* @param leap   当月是否是闰月* @return 传回天数,如果闰月是错误的,返回0.*/public static final int daysInMonth(int year, int month, boolean leap) {int leapMonth = leapMonth(year);int offset = 0;// 如果本年有闰月且month大于闰月时,需要校正if (leapMonth != 0 && month > leapMonth) {offset = 1;}// 不考虑闰月if (!leap) {return daysInLunarMonth(year, month + offset);} else {// 传入的闰月是正确的月份if (leapMonth != 0 && leapMonth == month) {return daysInLunarMonth(year, month + 1);}}return 0;}/*** 传回农历 year年的总天数** @param year 将要计算的年份* @return 返回传入年份的总天数*/private static int daysInLunarYear(int year) {int i, sum = 348;if (leapMonth(year) != 0) {sum = 377;}int monthInfo = LUNAR_INFO[year - MIN_YEAR] & 0x0FFF80;for (i = 0x80000; i > 0x7; i >>= 1) {if ((monthInfo & i) != 0) {sum += 1;}}return sum;}/*** 传回农历 year年month月的总天数,总共有13个月包括闰月** @param year  将要计算的年份* @param month 将要计算的月份* @return 传回农历 year年month月的总天数*/private static int daysInLunarMonth(int year, int month) {if ((LUNAR_INFO[year - MIN_YEAR] & (0x100000 >> month)) == 0) {return 29;} else {return 30;}}/*** 传回农历 year年闰哪个月 1-12 , 没闰传回 0* @param year 将要计算的年份* @return 传回农历 year年闰哪个月1-12, 没闰传回 0*/public static int leapMonth(int year) {return ((LUNAR_INFO[year - MIN_YEAR] & 0xF00000)) >> 20;}public static Date getSort(Date date) {SimpleDateFormat str = new SimpleDateFormat("MM-dd");//时间格式String sort = str.format(date);DateFormat dateFormat = new SimpleDateFormat("MM-dd");Date date1 = null;try {date1 = dateFormat.parse(sort);} catch (ParseException e) {e.printStackTrace();}return date1;}public static int getMonth(Date date) {SimpleDateFormat str = new SimpleDateFormat("MM");//时间格式String month = str.format(date);return Integer.parseInt(month);}public static int getDay(Date date) {SimpleDateFormat str = new SimpleDateFormat("dd");//时间格式String day = str.format(date);return Integer.parseInt(day);}public static Date strToDate(String strDate){DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");Date date = null;try {date = dateFormat.parse(strDate);} catch (ParseException e) {e.printStackTrace();}return date;}public static String dateToStr(Date date){//日期转字符串DateFormat dateFormat = new SimpleDateFormat("MM-dd");String str = dateFormat.format(date);return str;}public static void main(String[] args) {//计算录入年份是否有闰月System.out.println(leapMonth(2023));//传回农历 year年month月的总天数,总共有13个月包括闰月System.out.println(daysInLunarMonth(2017,6));//传回农历year年month月的总天数System.out.println(daysInMonth(2017,6,false));//阳历转阴历  9.25  10.23 有问题System.out.println(solarToLunar(2023, 5, 22));//阴历转阳历System.out.println(lunarToSolar(2023,5,22,false));}
}

Controller方法

    /*** 员工生日列表* @return*/@RequestMapping(value = "/staffBirthday", method = RequestMethod.POST)@ApiOperation(value = "员工生日列表",httpMethod = "POST")public ResultMsg staffBirthday(@RequestBody RsUserBirthdayRequest request) {List<RsUserBirthResponse> responses = rsUserinfoService.getStaffBirthday(request);PageResp<RsUserBirthResponse> resultPage = null;//list转分页对象Page<RsUserBirthResponse> page = PageUtil.convertList2PageVO(request.getPageNo(), request.getPageSize(), responses);resultPage = BeanConvertUtils.convertBean(page.convert(taskBatch -> BeanConvertUtils.convertBean(taskBatch, RsUserBirthResponse.class)),PageResp.class);return ResultMsg.ok(resultPage);}

SeviceImpl:列出所有员工的生日列表,将农历生日转成果历生日,根据日期进行牌组,并根据年份月份进行筛选

    @Overridepublic List<RsUserBirthResponse> getStaffBirthday(RsUserBirthdayRequest request) {// 获取所有员工生日列表List<RsUserBirthResponse> staffBirthday = rsUserinfoMapper.getStaffBirthday();// 获取当前年份并判断当前年份有无闰月,并且闰的几月int leapMonth = LunarCalendarUtil.leapMonth(request.getYear());staffBirthday.stream().forEach(birth -> {// 农历if (birth.getCalendar() !=null && birth.getCalendar().equals(StaffBirthdayEnums.LUNAR.getName())) {//提示农历生日birth.setLunar( "农历(" + LunarCalendarUtil.dateToStr(birth.getBirthdate()) +")");int month = LunarCalendarUtil.getMonth(birth.getBirthdate());// 获取月份int day = LunarCalendarUtil.getDay(birth.getBirthdate());// 获取具体哪一天boolean isLeapMonth = leapMonth == month ? true : false;// 是否为闰月// 将农历生日转换成国历生日Date date = LunarCalendarUtil.lunarToSolar(Calendar.getInstance().get(Calendar.YEAR), month, day, isLeapMonth);birth.setBirthdate(date);}});// 排序,距离当前日期最近的生日在前并过滤List<RsUserBirthResponse> collect = staffBirthday.stream().sorted(Comparator.comparing(s -> LunarCalendarUtil.getSort(s.getBirthdate()))).collect(Collectors.toList());// 筛选所年份和选月份List<RsUserBirthResponse> collect1 = collect;if (request.getMonth() != null) {collect1 = collect.stream().filter(birth ->Objects.equals(request.getMonth(), LunarCalendarUtil.getMonth(birth.getBirthdate()))).collect(Collectors.toList());}return collect1;}

XML

    <select id="getStaffBirthday" resultType="cn.hui.pm.entity.response.rs.RsUserBirthResponse">SELECT u.staff_id                as staffId,u.user_name               as staffName,u.birthdate,u.calendar,group_concat(d.dept_name) as departmentNameFROM rs_userinfo uleft join sys_staff_dept sd on sd.staff_id = u.staff_idleft join sys_dept d on d.id = sd.dept_idWHERE d.is_deleted = 'N'and u.is_deleted = 'N'and sd.is_deleted = 'N'and u.birthdate IS NOT NULLGROUP BY u.staff_id</select>

公司需求,需要一个员工生日列表,需要区分农历和国历相关推荐

  1. 平安多喜乐 岁岁都欢颜 | 中创员工生日会

    凛冽的风带来寒冬的萧索,冬日的暖阳却显得格外温柔.12月25日是圣诞也是中创2021年最后一个员工生日会. 提到圣诞当然少不了"平安果",为了让每位中创员工都领到独属于自己的一份礼 ...

  2. 动态代理 需求:一个超级明星技能跳舞、唱歌、拍电影、睡觉。明星经纪人公司接活动,赚的钱37分。请用写出代码。

    需求:一个超级明星技能跳舞.唱歌.拍电影.睡觉.明星经纪人公司接活动,赚的钱37分.请用写出代码. 这是一个典型的动态代理的问题,代码实现如下: 准备工作 我们需要建立2个类和一个接口. SuperS ...

  3. C#某公司有各类员工,定义一个员工类(Employee),该类具有员工的姓名(Name)和基本薪金(Salary)等属性;并有一个虚方法(CalSalary)用于计算并输出员工的总薪金。

    .某公司有各类员工,定义一个员工类(Employee),该类具有员工的姓名(Name)和基本薪金(Salary)等属性:并有一个虚方法(CalSalary)用于计算并输出员工的总薪金. 对不同的员工, ...

  4. 公司员工生日活动策划方案PPT模板

    模板介绍 精美PPT模板设计,公司员工生日活动策划方案PPT模板.一套生日会幻灯片模板,内含灰色多种配色,精美风格设计,动态播放效果,精美实用. 一份设计精美的PPT模板,可以让你在汇报演讲时脱颖而出 ...

  5. 对话苹果公司的一号员工Bill Fernandez

    Employee #1 是一个专注于分享科技公司早期员工背后故事的系列访谈. \ Bill Fernandez是继Steve Jobs.Steve Wozniak和Mike Markkula创办苹果公 ...

  6. 一个员工的离职,背后都意味着什么?

    来源 | web前端开发 一个员工的离职成本,很恐怖! 一个员工离职后留下的坑,并不是再找一个人填上就万事大吉了.一般来说,核心人才的流失,至少有1-2个月的招聘期.3个月的适应期,6个月的融入期:此 ...

  7. 使用Jquery+EasyUI进行框架项目开发案例解说之中的一个---员工管理源代码分享

    使用Jquery+EasyUI 进行框架项目开发案例解说之中的一个 员工管理源代码分享 在開始解说之前,我们先来看一下什么是Jquery EasyUI?jQuery EasyUI是一组基于jQuery ...

  8. 写给粪坑里的钻石——烂公司里的好员工

    一个公司之所以"烂",必然是管理混乱或者没有核心竞争力,而且公司氛围很差,员工内部.员工和老板之间的矛盾很多. 但凡是这种垃圾公司,必然会有几个员工工作能力特别强,而且这些能力特别 ...

  9. 程序人生:一个员工的离职成本到底有多高,看完你就懂了!

    一个员工的离职成本,很恐怖! 一个员工离职后留下的坑,并不是再找一个人填上就万事大吉了.一般来说,核心人才的流失,至少有1-2个月的招聘期.3个月的适应期,6个月的融入期:此外,还有相当于4个月工资的 ...

最新文章

  1. 深入理解ajax系列第六篇——头部信息
  2. redis中KEYS替代命令
  3. 是什么能让 APP 快速精准定位到我们的位置?
  4. python 获取当前月份月初日期和月末日期
  5. tps波动很大的原因_期货揭秘:价格的波动规律(2)
  6. 【Python 安装】安装第三方库时 PermissionError: [WinError 5] Access is denied
  7. html缩放背景不缩放_缩放并不可怕。
  8. 苹果8a1660是什么版本_苹果a1780是什么版本
  9. PRAM模型与Amdahl定律
  10. Pandas 之DataFrame二维表基础操作及演示
  11. 密西根州立大学计算机qs分数,密歇根州立大学2021年QS世界大学排名第157
  12. 微信小程序开发之视频video组件报错:渲染层网络层错误
  13. 通讯:白先勇的“八千里路云和月”
  14. 超强!Figma汉化版下载教程来了!
  15. Hazel引擎学习(八)
  16. Android车载系统app性能自动化测试规划
  17. 基于深度学习的图标型验证码识别系统(包含完整代码、界面)
  18. python+win32com分割多页ppt为单页多文件
  19. TI公司三大系列DSP内部结构之比较
  20. laya 学习抛出事件与接收事件

热门文章

  1. 电脑经常显示交互式服务器,win10系统打印机出现交互式服务检测的解决办法
  2. 软件测试(二)-经典测试技术-静态测试
  3. python通过调用百度api实现语音识别(超详细)
  4. 19-10-19 屏幕尺寸、分辨率、PPI、像素之间的关系
  5. 妖怪宝可萌html5游戏,妖怪宝可萌h5斗宠棋玩法规则以及技巧分析
  6. Android视图绑定ViewBinding的使用
  7. [病毒木马] 利用 Windows 任务计划程序
  8. 时间机器无法存入备份之外的文件的解决方法
  9. Android Git 拉取代码报错:error: cannot pull with rebase: Your index contains uncommitted changes.
  10. ML - 线性回归的评估(MSE、RMSE、MAE、R Square)