importjava.util.Arrays;importjava.util.Date;importjava.util.GregorianCalendar;/*** 工具类,实现阴阳历互转

*

*@authorluohao*/

public classLunarCalendar {/*** 支持转换的最小农历年份*/

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};/*** 将农历日期转换为公历日期

*

*@paramyear 农历年份

*@parammonth 农历月

*@parammonthDay 农历日

*@paramisLeapMonth 该月是否是闰月

*@return返回农历日期对应的公历日期,year0, month1, day2.*/

public static final int[] lunarToSolar(int year, int month, int monthDay, booleanisLeapMonth) {intdayOffset;intleapMonth;inti;if (year < MIN_YEAR || year > MAX_YEAR || month < 1 || month > 12

|| monthDay < 1 || monthDay > 30) {throw newIllegalArgumentException("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;returnsolarInfo;

}/*** 将公历日期转换为农历日期,且标识是否是闰月

*

*@paramyear

*@parammonth

*@parammonthDay

*@return返回公历日期对应的农历日期,year0,month1,day2,leap3*/

public static final int[] solarToLunar(int year, int month, intmonthDay) {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-12

boolean 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;returnlunarDate;

}/*** 传回农历year年month月的总天数

*

*@paramyear 要计算的年份

*@parammonth 要计算的月

*@return传回天数*/

final public static int daysInMonth(int year, intmonth) {return daysInMonth(year, month, false);

}/*** 传回农历year年month月的总天数

*

*@paramyear 要计算的年份

*@parammonth 要计算的月

*@paramleap 当月是否是闰月

*@return传回天数,如果闰月是错误的,返回0.*/

public static final int daysInMonth(int year, int month, booleanleap) {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年的总天数

*

*@paramyear 将要计算的年份

*@return返回传入年份的总天数*/

private static int daysInLunarYear(intyear) {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;

}

}returnsum;

}/*** 传回农历 year年month月的总天数,总共有13个月包括闰月

*

*@paramyear 将要计算的年份

*@parammonth 将要计算的月份

*@return传回农历 year年month月的总天数*/

private static int daysInLunarMonth(int year, intmonth) {if ((LUNAR_INFO[year - MIN_YEAR] & (0x100000 >> month)) == 0) {return 29;

}else{return 30;

}

}/*** 传回农历 year年闰哪个月 1-12 , 没闰传回 0

*

*@paramyear 将要计算的年份

*@return传回农历 year年闰哪个月1-12, 没闰传回 0*/

private static int leapMonth(intyear) {return ((LUNAR_INFO[year - MIN_YEAR] & 0xF00000)) >> 20;

}public static voidmain(String[] args) {

System.out.println(Arrays.toString(solarToLunar(2019, 4, 4)));

}

}

java 公历 农历_Java 阴历阳历转换相关推荐

  1. java 公历 农历_java已知阳历日期求对应阴历日期源代码

    import java.text.*; import java.util.*; class ChineseCalendarGB { private int gregorianYear; private ...

  2. java阳历转为阴历错了一天_Java 阴历阳历转换

    代码如下 收藏备用 import java.util.Arrays; import java.util.Date; import java.util.GregorianCalendar; /** * ...

  3. java 公历 农历_Java给定公历日期计算相应农历/阴历日期

    import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; impor ...

  4. java 字母大写_Java字母大小写转换的方法

    案例: 要求从控制台接收用户输入的一个字母,如果这个字母是小写,转换为大写:如果这个字母是大写,转换为小写:只能输入字母,如果是其他值,提示数据有误! 实现代码: import java.util.S ...

  5. java的字母_Java字母大小写转换的方法

    案例: 要求从控制台接收用户输入的一个字母,如果这个字母是小写,转换为大写:如果这个字母是大写,转换为小写:只能输入字母,如果是其他值,提示数据有误! 实现代码: import java.util.S ...

  6. java 阴历阳历转换

    public class SolarLunarConverter {/* * |----4位闰月|-------------13位1为30天,0为29天| */private static int[] ...

  7. java 自动类型_java类型自动转换

    package com.kevin.basic; /* * java类型自动转换方面的知识点 * int类型 double类型 默认类型 */ public class Test { /** * @p ...

  8. java隐含转化_java中自动转换和强制转换还有隐含转换

    匿名用户 1级 2016-08-29 回答 转型被用来将一个数值从一种类型转换到另一种类型.下面的程序连续使用了三个转型.那么它到底会打印出什么呢? public class Multicast{ p ...

  9. java中大数值_Java大数值转换

    在java语言中,包括了很多种java数据类型,相信大家对这些基础知识并不陌生,但是有时候这些数据类型的精度不能满足要求时,就需要用更大或者精度更高的类型,这时候就需要使用到大数值.那么大数值是什么? ...

  10. java生成图片大小_Java 对图片进行大小转换

    1.实际项目中要将"图片档案"生成缩略图(将图片大小变成 160*160),参考网上代码写了Demo. 2.工具类. /* * @(#) ImageResizer.java 1.0 ...

最新文章

  1. Android平台的事件处理机制和手指滑动例子
  2. 事件绑定及解除事件绑定
  3. 【模型解读】从“局部连接”回到“全连接”的神经网络
  4. 全新的 flow.ci Dashboard 上线
  5. WebSocket入门
  6. 基础才是重中之重~再说面向接口的编程
  7. python绘制散点图、如何选两列作为横坐标_在matplotlib散点图(水平杆图)中从x=0到数据点绘制水平线...
  8. idea修改jdk的版本号
  9. xlib/x11:创建一个监测键盘事件的窗口-3-fullscreen-windowed
  10. js获取jsp上下文地址
  11. angular使用动态组件后属性值_Angular 2-组件
  12. 【PHP学习】—PHP连接数据库实现表单页面的验证功能(七)
  13. MyBatis sql查询字段问题
  14. filesplit的Python项目详细描述
  15. 边框盒子 box-sizing 的 content-box 和 border-box属性
  16. Python sklearn针对不同人群的差异化保险费用定价方案
  17. 新浪微博批量取消关注
  18. Tasteless challenges medium WP
  19. Harry Potter Sorting Ceremony(分院帽)
  20. Kibana中KQL的使用

热门文章

  1. 嵌入式系统架构设计师的理解
  2. 日常工作常用的几款小工具
  3. python爬虫获取维基百科词条
  4. 前端性能优化gzip压缩
  5. 网站开发流程(附图)
  6. Frenet和笛卡尔坐标系互转
  7. 湖南出台不动产登记新规 “小产权房”不予办理
  8. 每天脑子里莫名其妙冒出来的话(常见于早上起床之后)持续记录,这也是日记的一种
  9. 迪杰斯特拉算法(dijkstra)
  10. 计算机组装物料清单,物料清单