posts - 38,  comments - 22,  trackbacks - 0
import  java.text.ParseException;
import  java.text.SimpleDateFormat;
import  java.util.Calendar;
import  java.util.Date;

public   class  Lunar  {
    
private   int  year;
    
private   int  month;
    
private   int  day;
    
private   boolean  leap;
    
final   static  String chineseNumber[]  =   { " 一 " ,  " 二 " ,  " 三 " ,  " 四 " ,  " 五 " ,  " 六 " ,  " 七 " ,  " 八 " ,  " 九 " ,  " 十 " ,  " 十一 " ,  " 十二 " } ;
    
static  SimpleDateFormat chineseDateFormat  =   new  SimpleDateFormat( " yyyy年MM月dd日 " );
    
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 }
;

    
// ====== 传回农历 y年的总天数
     final   private   static   int  yearDays( int  y)  {
        
int  i, sum  =   348 ;
        
for  (i  =   0x8000 ; i  >   0x8 ; i  >>=   1 )  {
            
if  ((lunarInfo[y  -   1900 ]  &  i)  !=   0 ) sum  +=   1 ;
        }

        
return  (sum  +  leapDays(y));
    }


    
// ====== 传回农历 y年闰月的天数
     final   private   static   int  leapDays( int  y)  {
        
if  (leapMonth(y)  !=   0 )  {
            
if  ((lunarInfo[y  -   1900 ]  &   0x10000 )  !=   0 )
                
return   30 ;
            
else
                
return   29 ;
        }
  else
            
return   0 ;
    }


    
// ====== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
     final   private   static   int  leapMonth( int  y)  {
        
return  ( int ) (lunarInfo[y  -   1900 ]  &   0xf );
    }


    
// ====== 传回农历 y年m月的总天数
     final   private   static   int  monthDays( int  y,  int  m)  {
        
if  ((lunarInfo[y  -   1900 ]  &  ( 0x10000   >>  m))  ==   0 )
            
return   29 ;
        
else
            
return   30 ;
    }


    
// ====== 传回农历 y年的生肖
     final   public  String animalsYear()  {
        
final  String[] Animals  =   new  String[] { " 鼠 " ,  " 牛 " ,  " 虎 " ,  " 兔 " ,  " 龙 " ,  " 蛇 " ,  " 马 " ,  " 羊 " ,  " 猴 " ,  " 鸡 " ,  " 狗 " ,  " 猪 " } ;
        
return  Animals[(year  -   4 )  %   12 ];
    }


    
// ====== 传入 月日的offset 传回干支, 0=甲子
     final   private   static  String cyclicalm( int  num)  {
        
final  String[] Gan  =   new  String[] { " 甲 " ,  " 乙 " ,  " 丙 " ,  " 丁 " ,  " 戊 " ,  " 己 " ,  " 庚 " ,  " 辛 " ,  " 壬 " ,  " 癸 " } ;
        
final  String[] Zhi  =   new  String[] { " 子 " ,  " 丑 " ,  " 寅 " ,  " 卯 " ,  " 辰 " ,  " 巳 " ,  " 午 " ,  " 未 " ,  " 申 " ,  " 酉 " ,  " 戌 " ,  " 亥 " } ;
        
return  (Gan[num  %   10 ]  +  Zhi[num  %   12 ]);
    }


    
// ====== 传入 offset 传回干支, 0=甲子
     final   public  String cyclical()  {
        
int  num  =  year  -   1900   +   36 ;
        
return  (cyclicalm(num));
    }


    
/**
     * 传出y年m月d日对应的农历.
     * yearCyl3:农历年与1864的相差数              ?
     * monCyl4:从1900年1月31日以来,闰月数
     * dayCyl5:与1900年1月31日相差的天数,再加40      ?
     * 
@param  cal 
     * 
@return  
     
*/

    
public  Lunar(Calendar cal)  {
        @SuppressWarnings(
" unused " )  int  yearCyl, monCyl, dayCyl;
        
int  leapMonth  =   0 ;
        Date baseDate 
=   null ;
        
try   {
            baseDate 
=  chineseDateFormat.parse( " 1900年1月31日 " );
        }
  catch  (ParseException e)  {
            e.printStackTrace();  
// To change body of catch statement use Options | File Templates.
        }


        
// 求出和1900年1月31日相差的天数
         int  offset  =  ( int ) ((cal.getTime().getTime()  -  baseDate.getTime())  /   86400000L );
        dayCyl 
=  offset  +   40 ;
        monCyl 
=   14 ;

        
// 用offset减去每农历年的天数
        
//  计算当天是农历第几天
        
// i最终结果是农历的年份
        
// offset是当年的第几天
         int  iYear, daysOfYear  =   0 ;
        
for  (iYear  =   1900 ; iYear  <   2050   &&  offset  >   0 ; iYear ++ )  {
            daysOfYear 
=  yearDays(iYear);
            offset 
-=  daysOfYear;
            monCyl 
+=   12 ;
        }

        
if  (offset  <   0 )  {
            offset 
+=  daysOfYear;
            iYear
-- ;
            monCyl 
-=   12 ;
        }

        
// 农历年份
        year  =  iYear;

        yearCyl 
=  iYear  -   1864 ;
        leapMonth 
=  leapMonth(iYear);  // 闰哪个月,1-12
        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(year);
            }
  else
                daysOfMonth 
=  monthDays(year, iMonth);

            offset 
-=  daysOfMonth;
            
// 解除闰月
             if  (leap  &&  iMonth  ==  (leapMonth  +   1 )) leap  =   false ;
            
if  ( ! leap) monCyl ++ ;
        }

        
// offset为0时,并且刚才计算的月份是闰月,要校正
         if  (offset  ==   0   &&  leapMonth  >   0   &&  iMonth  ==  leapMonth  +   1 )  {
            
if  (leap)  {
                leap 
=   false ;
            }
  else   {
                leap 
=   true ;
                
-- iMonth;
                
-- monCyl;
            }

        }

        
// offset小于0时,也要校正
         if  (offset  <   0 )  {
            offset 
+=  daysOfMonth;
            
-- iMonth;
            
-- monCyl;
        }

        month 
=  iMonth;
        day 
=  offset  +   1 ;
    }


    
public   static  String getChinaDayString( int  day)  {
        String chineseTen[] 
=   { " 初 " ,  " 十 " ,  " 廿 " ,  " 卅 " } ;
        
int  n  =  day  %   10   ==   0   ?   9  : day  %   10   -   1 ;
        
if  (day  >   30 )
            
return   "" ;
        
if  (day  ==   10 )
            
return   " 初十 " ;
        
else
            
return  chineseTen[day  /   10 ]  +  chineseNumber[n];
    }


    
public  String toString()  {
        
return  year  +   " 年 "   +  (leap  ?   " 闰 "  :  "" )  +  chineseNumber[month  -   1 ]  +   " 月 "   +  getChinaDayString(day);
    }


    
public   static   void  main(String[] args)  throws  ParseException  {
        Calendar today 
=  Calendar.getInstance();
        today.setTime(chineseDateFormat.parse(
" 2003年1月1日 " ));
        Lunar lunar 
=   new  Lunar(today);

        System.out.println(
" 北京时间: "   +  chineseDateFormat.format(today.getTime())  +   "  农历 "   +  lunar);
    }

}
 

posted on 2007-01-04 19:12 aaabbb 阅读(2652) 评论(3)  编辑  收藏 所属分类: java