java万年历

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java万年历相关的知识,希望对你有一定的参考价值。

请各位高手指点下万年历实现的思路好吗?不需要打印代码出来,只需要思路,本人想自己写,谢谢,没积分了,能收到回音码?
谢谢。。。。很详细,但就是太长了,我要的只是用Java写万年历的思路,要怎么样去计算,不是什么公式啊,我看了都头大了,简洁点好吗

别人写的 借花献佛

万年历的 但是不实现农历

如何计算某一天是星期几?
slowtiger 发表于 2005-10-11 21:43:00
如何计算某一天是星期几?
—— 蔡勒(Zeller)公式
历史上的某一天是星期几?未来的某一天是星期几?关于这个问题,有很多计算公式(两个通用计算公式和一些分段计算公式),其中最著名的是蔡勒(Zeller)公式。
即w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1

公式中的符号含义如下,w:星期;c:世纪-1;y:年(两位数);m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算);d:日;[ ]代表取整,即只要整数部分。(C是世纪数减一,y是年份后两位,M是月份,d是日数。

1月和2月要按上一年的13月和 14月来算,这时C和y均按上一年取值。)

算出来的W除以7,余数是几就是星期几。如果余数是0,则为星期日。

以2049年10月1日(100周年国庆)为例,用蔡勒(Zeller)公式进行计算,过程如下:
蔡勒(Zeller)公式:w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1
=49+[49/4]+[20/4]-2×20+[26× (10+1)/10]+1-1
=49+[12.25]+5-40+[28.6]
=49+12+5-40+28
=54 (除以7余5)
即2049年10月1日(100周年国庆)是星期5。

你的生日(出生时、今年、明年)是星期几?不妨试一试。

不过,以上公式只适合于1582年10月15日之后的情形(当时的罗马教皇将恺撒大帝制订的儒略历修改成格里历,即今天使用的公历)。

过程的推导:(对推理不感兴趣的可略过不看)

星期制度是一种有古老传统的制度。据说因为《圣经·创世纪》中规定上帝用了六
天时间创世纪,第七天休息,所以人们也就以七天为一个周期来安排自己的工作和生
活,而星期日是休息日。从实际的角度来讲,以七天为一个周期,长短也比较合适。所
以尽管中国的传统工作周期是十天(比如王勃《滕王阁序》中说的“十旬休暇”,即是
指官员的工作每十日为一个周期,第十日休假),但后来也采取了西方的星期制度。

在日常生活中,我们常常遇到要知道某一天是星期几的问题。有时候,我们还想知
道历史上某一天是星期几。通常,解决这个方法的有效办法是看日历,但是我们总不会
随时随身带着日历,更不可能随时随身带着几千年的万年历。假如是想在计算机编程中
计算某一天是星期几,预先把一本万年历存进去就更不现实了。这时候是不是有办法通
过什么公式,从年月日推出这一天是星期几呢?

答案是肯定的。其实我们也常常在这样做。我们先举一个简单的例子。比如,知道
了2004年5月1日是星期六,那么2004年5月31日“世界无烟日”是星期几就不难推算出
来。我们可以掰着指头从1日数到31日,同时数星期,最后可以数出5月31日是星期一。
其实运用数学计算,可以不用掰指头。我们知道星期是七天一轮回的,所以5月1日是星
期六,七天之后的5月8日也是星期六。在日期上,8-1=7,正是7的倍数。同样,5月15
日、5月22日和5月29日也是星期六,它们的日期和5月1日的差值分别是14、21和28,也
都是7的倍数。那么5月31日呢?31-1=30,虽然不是7的倍数,但是31除以7,余数为2,
这就是说,5月31日的星期,是在5月1日的星期之后两天。星期六之后两天正是星期一。

这个简单的计算告诉我们计算星期的一个基本思路:首先,先要知道在想算的日子
之前的一个确定的日子是星期几,拿这一天做为推算的标准,也就是相当于一个计算的
“原点”。其次,知道想算的日子和这个确定的日子之间相差多少天,用7除这个日期
的差值,余数就表示想算的日子的星期在确定的日子的星期之后多少天。如果余数是
0,就表示这两天的星期相同。显然,如果把这个作为“原点”的日子选为星期日,那
么余数正好就等于星期几,这样计算就更方便了。

但是直接计算两天之间的天数,还是不免繁琐。比如1982年7月29日和2004年5月
1日之间相隔7947天,就不是一下子能算出来的。它包括三段时间:一,1982年7月29
日以后这一年的剩余天数;二,1983-2003这二十一个整年的全部天数;三,从2004年
元旦到5月1日经过的天数。第二段比较好算,它等于21*365+5=7670天,之所以要加
5,是因为这段时间内有5个闰年。第一段和第三段就比较麻烦了,比如第三段,需要把
5月之前的四个月的天数累加起来,再加上日期值,即31+29+31+30+1=122天。同理,第
一段需要把7月之后的五个月的天数累加起来,再加上7月剩下的天数,一共是155天。
所以总共的相隔天数是122+7670+155=7947天。

仔细想想,如果把“原点”日子的日期选为12月31日,那么第一段时间也就是一个
整年,这样一来,第一段时间和第二段时间就可以合并计算,整年的总数正好相当于两
个日子的年份差值减一。如果进一步把“原点”日子选为公元前1年12月31日(或者天文
学家所使用的公元0年12月31日),这个整年的总数就正好是想算的日子的年份减一。这
样简化之后,就只须计算两段时间:一,这么多整年的总天数;二,想算的日子是这一
年的第几天。巧的是,按照公历的年月设置,这样反推回去,公元前1年12月31日正好是
星期日,也就是说,这样算出来的总天数除以7的余数正好是星期几。那么现在的问题就
只有一个:这么多整年里面有多少闰年。这就需要了解公历的置闰规则了。

我们知道,公历的平年是365天,闰年是366天。置闰的方法是能被4整除的年份在
2月加一天,但能被100整除的不闰,能被400整除的又闰。因此,像1600、2000、2400
年都是闰年,而1700、1800、1900、2100年都是平年。公元前1年,按公历也是闰年。

因此,对于从公元前1年(或公元0年)12月31日到某一日子的年份Y之间的所有整年
中的闰年数,就等于

[(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400],

[...]表示只取整数部分。第一项表示需要加上被4整除的年份数,第二项表示需要去掉
被100整除的年份数,第三项表示需要再加上被400整除的年份数。之所以Y要减一,这
样,我们就得到了第一个计算某一天是星期几的公式:

W = (Y-1)*365 + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + D. (1)

其中D是这个日子在这一年中的累积天数。算出来的W就是公元前1年(或公元0年)12月
31日到这一天之间的间隔日数。把W用7除,余数是几,这一天就是星期几。比如我们来
算2004年5月1日:

W = (2004-1)*365 + [(2004-1)/4] - [(2004-1)/100] + [(2004-1)/400] +
(31+29+31+30+1)
= 731702,

731702 / 7 = 104528……6,余数为六,说明这一天是星期六。这和事实是符合的。

上面的公式(1)虽然很准确,但是计算出来的数字太大了,使用起来很不方便。仔
细想想,其实这个间隔天数W的用数仅仅是为了得到它除以7之后的余数。这启发我们是
不是可以简化这个W值,只要找一个和它余数相同的较小的数来代替,用数论上的术语
来说,就是找一个和它同余的较小的正整数,照样可以计算出准确的星期数。

显然,W这么大的原因是因为公式中的第一项(Y-1)*365太大了。其实,

(Y-1)*365 = (Y-1) * (364+1)
= (Y-1) * (7*52+1)
= 52 * (Y-1) * 7 + (Y-1),

这个结果的第一项是一个7的倍数,除以7余数为0,因此(Y-1)*365除以7的余数其实就
等于Y-1除以7的余数。这个关系可以表示为:

(Y-1)*365 ≡ Y-1 (mod 7).

其中,≡是数论中表示同余的符号,mod 7的意思是指在用7作模数(也就是除数)的情
况下≡号两边的数是同余的。因此,完全可以用(Y-1)代替(Y-1)*365,这样我们就得到
了那个著名的、也是最常见到的计算星期几的公式:

W = (Y-1) + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + D. (2)

这个公式虽然好用多了,但还不是最好用的公式,因为累积天数D的计算也比较麻
烦。是不是可以用月份数和日期直接计算呢?答案也是肯定的。我们不妨来观察一下各
个月的日数,列表如下:

月 份:1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月
--------------------------------------------------------------------------
天 数: 31 28(29) 31 30 31 30 31 31 30 31 30 31

如果把这个天数都减去28(=4*7),不影响W除以7的余数值。这样我们就得到另一张
表:

月 份:1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月
------------------------------------------------------------------------
剩余天数: 3 0(1) 3 2 3 2 3 3 2 3 2 3
平年累积: 3 3 6 8 11 13 16 19 21 24 26 29
闰年累积: 3 4 7 9 12 14 17 20 22 25 27 30

仔细观察的话,我们会发现除去1月和2月,3月到7月这五个月的剩余天数值是3,2,3,2,
3;8月到12月这五个月的天数值也是3,2,3,2,3,正好是一个重复。相应的累积天数中,
后一月的累积天数和前一月的累积天数之差减去28就是这个重复。正是因为这种规律的
存在,平年和闰年的累积天数可以用数学公式很方便地表达:

╭ d; (当M=1)
D = 31 + d; (当M=2) (3)
╰ [ 13 * (M+1) / 5 ] - 7 + (M-1) * 28 + d + i. (当M≥3)

其中[...]仍表示只取整数部分;M和d分别是想算的日子的月份和日数;平年i=0,闰年
i=1。对于M≥3的表达式需要说明一下:[13*(M+1)/5]-7算出来的就是上面第二个表中的
平年累积值,再加上(M-1)*28就是想算的日子的月份之前的所有月份的总天数。这是一
个很巧妙的办法,利用取整运算来实现3,2,3,2,3的循环。比如,对2004年5月1日,有:

D = [ 13 * (5+1) / 5 ] - 7 + (5-1) * 28 + 1 + 1
= 122,

这正是5月1日在2004年的累积天数。

假如,我们再变通一下,把1月和2月当成是上一年的“13月”和“14月”,不仅仍
然符合这个公式,而且因为这样一来,闰日成了上一“年”(一共有14个月)的最后一
天,成了d的一部分,于是平闰年的影响也去掉了,公式就简化成:

D = [ 13 * (M+1) / 5 ] - 7 + (M-1) * 28 + d. (3≤M≤14) (4)

上面计算星期几的公式,也就可以进一步简化成:

W = (Y-1) + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + [ 13 * (M+1) / 5 ] - 7
+ (M-1) * 28 + d.

因为其中的-7和(M-1)*28两项都可以被7整除,所以去掉这两项,W除以7的余数不变,
公式变成:

W = (Y-1) + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + [ 13 * (M+1) / 5 ] + d.
(5)

当然,要注意1月和2月已经被当成了上一年的13月和14月,因此在计算1月和2月的日子
的星期时,除了M要按13或14算,年份Y也要减一。比如,2004年1月1日是星期四,用这
个公式来算,有:

W = (2003-1) + [(2003-1)/4] - [(2003-1)/100] + [(2003-1)/400] + [13*(13+1)/5]
+ 1
= 2002 + 500 - 20 + 5 + 36 + 1
= 2524;
2524 / 7 = 360……4.这和实际是一致的。

公式(5)已经是从年、月、日来算星期几的公式了,但它还不是最简练的,对于年
份的处理还有改进的方法。我们先来用这个公式算出每个世纪第一年3月1日的星期,列
表如下:

年份: 1(401,801,…,2001) 101(501,901,…,2101)
--------------------------------------------------------------------
星期: 4 2
====================================================================
年份:201(601,1001,…,2201) 301(701,1101,…,2301)
--------------------------------------------------------------------
星期: 0 5

可以看出,每隔四个世纪,这个星期就重复一次。假如我们把301(701,1101,…,2301)
年3月1日的星期数看成是-2(按数论中对余数的定义,-2和5除以7的余数相同,所以可
以做这样的变换),那么这个重复序列正好就是一个4,2,0,-2的等差数列。据此,我们
可以得到下面的计算每个世纪第一年3月1日的星期的公式:

W = (4 - C mod 4) * 2 - 4. (6)

式中,C是该世纪的世纪数减一,mod表示取模运算,即求余数。比如,对于2001年3月
1日,C=20,则:

W = (4 - 20 mod 4) * 2 - 4
= 8 - 4
= 4.

把公式(6)代入公式(5),经过变换,可得:

(Y-1) + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] ≡ (4 - C mod 4) * 2 - 1
(mod 7). (7)

因此,公式(5)中的(Y-1) + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400]这四项,在计算
每个世纪第一年的日期的星期时,可以用(4 - C mod 4) * 2 - 1来代替。这个公式写
出来就是:

W = (4 - C mod 4) * 2 - 1 + [13 * (M+1) / 5] + d. (8)

有了计算每个世纪第一年的日期星期的公式,计算这个世纪其他各年的日期星期的公式
就很容易得到了。因为在一个世纪里,末尾为00的年份是最后一年,因此就用不着再考
虑“一百年不闰,四百年又闰”的规则,只须考虑“四年一闰”的规则。仿照由公式(1)
简化为公式(2)的方法,我们很容易就可以从式(8)得到一个比公式(5)更简单的计算任意
一天是星期几的公式:

W = (4 - C mod 4) * 2 - 1 + (y-1) + [y/4] + [13 * (M+1) / 5] + d. (9)

式中,y是年份的后两位数字。

如果再考虑到取模运算不是四则运算,我们还可以把(4 - C mod 4) * 2进一步改写
成只含四则运算的表达式。因为世纪数减一C除以4的商数q和余数r之间有如下关系:

4q + r = C,

其中r即是 C mod 4,因此,有:

r = C - 4q
= C - 4 * [C/4]. (10)



(4 - C mod 4) * 2 = (4 - C + 4 * [C/4]) * 2
= 8 - 2C + 8 * [C/4]
≡ [C/4] - 2C + 1 (mod 7). (11)

把式(11)代入(9),得到:

W = [C/4] - 2C + y + [y/4] + [13 * (M+1) / 5] + d - 1. (12)

这个公式由世纪数减一、年份末两位、月份和日数即可算出W,再除以7,得到的余数是
几就表示这一天是星期几,唯一需要变通的是要把1月和2月当成上一年的13月和14月,
C和y都按上一年的年份取值。因此,人们普遍认为这是计算任意一天是星期几的最好的
公式。这个公式最早是由德国数学家克里斯蒂安·蔡勒(Christian Zeller, 1822-
1899)在1886年推导出的,因此通称为蔡勒公式(Zeller’s Formula)。为方便口算,
式中的[13 * (M+1) / 5]也往往写成[26 * (M+1) / 10]。

现在仍然让我们来算2004年5月1日的星期,显然C=20,y=4,M=5,d=1,代入蔡勒
公式,有:

W = [20/4] - 40 + 4 + 1 + [13 * (5+1) / 5] + 1 - 1
= -15.

注意负数不能按习惯的余数的概念求余数,只能按数论中的余数的定义求余。为了方便
计算,我们可以给它加上一个7的整数倍,使它变为一个正数,比如加上70,得到55。
再除以7,余6,说明这一天是星期六。这和实际是一致的,也和公式(2)计算所得的结
果一致。

最后需要说明的是,上面的公式都是基于公历(格里高利历)的置闰规则来考虑
的。对于儒略历,蔡勒也推出了相应的公式是:

W = 5 - C + y + [y/4] + [13 * (M+1) / 5] + d - 1. (13)

========================================
(2005-10-20 22:25:00) --------(4575252)
计算任何一天是星期几的几种算法
近日在论坛上看到有人在问星期算法,特别整理了一下,这些算法都是从网上搜索而来,算法的实现是我在项目中写的。希望对大家有所帮助。
一:常用公式

W = [Y-1] + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + D

Y是年份数,D是这一天在这一年中的累积天数,也就是这一天在这一年中是第几天。

二:蔡勒(Zeller)公式

w=y+[y/4]+[c/4]-2c+[26(m+1)/10]+d-1

公式中的符号含义如下,w:星期;c:世纪;y:年(两位数); m:月(m大于等于3,小于等于14,即在蔡勒公式中,某年的1、2月要看作上一年的13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算);d:日;[ ]代表取整,即只要整数部分。

相比于通用通用计算公式而言,蔡勒(Zeller)公式大大降低了计算的复杂度。

三:对蔡勒(Zeller)公式的改进

作者:冯思琮
相比于另外一个通用通用计算公式而言,蔡勒(Zeller)公式大大降低了计算的复杂度。不过,笔者给出的通用计算公式似乎更加简洁(包括运算过程)。现将公式列于其下:
W=[y/4]+r (y/7)-2r(c/4)+m’+d

公式中的符号含义如下,r ( )代表取余,即只要余数部分;m’是m的修正数,现给出1至12月的修正数1’至12’如下:(1’,10’)=6;(2’,3’,11’)=2;(4’,7’)=5;5’=0;6’=3;8’=1;(9’,12’)=4(注意:在笔者给出的公式中,y为润年时1’=5;2’=1)。其他符号与蔡勒(Zeller)公式中的含义相同。

四:基姆拉尔森计算公式

这个公式名称是我给命名的,哈哈希望大家不要见怪。

W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400) mod 7

在公式中d表示日期中的日数,m表示月份数,y表示年数。

注意:在公式中有个与其他公式不同的地方:

把一月和二月看成是上一年的十三月和十四月,例:如果是2004-1-10则换算成:2003-13-10来代入公式计算。

参考资料:http://zhidao.baidu.com/question/9491607.html

参考技术A import java.util.*;

public class Java
public static void main (String[] args)

Calendar cal=Calendar.getInstance();
System.out.println ("请输入年份:");
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
System.out.println ("请输入月份:");
int m=sc.nextInt();
cal.set(n,m-1,1);
System.out.println (cal.getTime());
System.out.println ();
System.out.println ("日\t一\t二\t三\t四\t五\t六");
System.out.println ();
System.out.println ("--\t--\t--\t--\t--\t--\t--");
System.out.println ();
int k=cal.get(Calendar.DAY_OF_WEEK);
for(int j=0;j<k-1;j++)
System.out.print (" ");
System.out.print ("\t");

for(int i=1;i<=cal.getActualMaximum(Calendar.DATE);i++)
System.out.print (i);
System.out.print ("\t");
if((i+k-1)%7==0)
System.out.println ();


System.out.println ();

JAVA线程万年历(阳历+阴历+节日+时间)

JAVA线程万年历(阳历+阴历+节日+时间)

package myCalendar;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.text.SimpleDateFormat;
import java.util.Calendar;
 class Clock extends Canvas implements Runnable{
     /**
     * 
     */
    private static final long serialVersionUID = 3660124045489727166L;
    MainFrame mf;
    Thread t;
    String time;
     public Clock(MainFrame mf){
    this.mf=mf;
    setSize(280,40);
    setBackground(Color.white);
    t=new Thread(this);                //实例化线程
    t.start();                        //调用线程
    }
     public void run(){
     while(true){
     try{
    Thread.sleep(1000);                    //休眠1秒钟
     }catch(InterruptedException e){
    System.out.println("异常");
    }
    this.repaint(100);
    }
    }
     public void paint(Graphics g){
    Font f=new Font("宋体",Font.BOLD,16);
    SimpleDateFormat SDF=new SimpleDateFormat("yyyy'年'MM'月'dd'日'HH:mm:ss");//格式化时间显示类型
    Calendar now=Calendar.getInstance();
    time=SDF.format(now.getTime());        //得到当前日期和时间
    g.setFont(f);
    g.setColor(Color.black);
    g.drawString(time,45,25);
    }
}
package myCalendar;

import java.awt.Color;
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));
    }
    
    
    
    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];
    }

    /** *//**
     * 传出y年m月d日对应的农历.
     * yearCyl3:农历年与1864的相差数              ?
     * monCyl4:从1900年1月31日以来,闰月数
     * dayCyl5:与1900年1月31日相差的天数,再加40      ?
     * @param cal 
     * @return 
     */
    public String getLunarDate(int year_log, int month_log, int day_log) {
        //@SuppressWarnings("unused") 
    	int yearCyl, monCyl, dayCyl;
        int leapMonth = 0;
        String nowadays;
        Date baseDate = null;
        Date nowaday=null;
        try {
            baseDate = chineseDateFormat.parse("1900年1月31日");
        } catch (ParseException e) {
            e.printStackTrace();  //To change body of catch statement use Options | File Templates.
        }
        
        nowadays=year_log+"年"+month_log+"月"+day_log+"日";
        try {
        	nowaday = chineseDateFormat.parse(nowadays);
        } catch (ParseException e) {
            e.printStackTrace();  //To change body of catch statement use Options | File Templates.
        }

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

        //用offset减去每农历年的天数
        // 计算当天是农历第几天
        //i最终结果是农历的年份
        //offset是当年的第几天
        int iYear, daysOfYear = 0;
        for (iYear = 1900; iYear < 10000 && 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;
    
        if(((month)==1)&&day==1){
        	return "春节";
        	
        }
        else if(((month)==1)&&day==15){
        	return "元宵";
        	
        }	
        else if(((month)==5)&&day==5)
        	return "端午";
        else if(((month)==8)&&day==15)
        	return "中秋";
        else if(day==1)
    		return chineseNumber[month - 1] + "月";
    	else 
    		return getChinaDayString(day);
    
    
    }

   

    public String toString() {
    	if(chineseNumber[month - 1]=="一"&&getChinaDayString(day)=="初一")
    		return "农历"+year + "年";
    	else if(getChinaDayString(day)=="初一")
    		return chineseNumber[month - 1] + "月";
    	else 
    		return getChinaDayString(day);
        //return year + "年" + (leap ? "闰" : "") + chineseNumber[month - 1] + "月" + getChinaDayString(day);
    }
}

package myCalendar;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Date;
import java.util.Calendar;

import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JButton;


 class MainFrame extends JFrame {
     /**
     * 
     */
    private static final long serialVersionUID = 1L;
    JPanel panel = new JPanel(new BorderLayout());
    JPanel panel1 = new JPanel();
    JPanel panel2 = new JPanel(new GridLayout(7, 7));
    JPanel panel3 = new JPanel();
    JLabel[] label = new JLabel[49];
    JLabel y_label = new JLabel("年份");
    JLabel m_label = new JLabel("月份");
    JComboBox com1 = new JComboBox();
    JComboBox com2 = new JComboBox();
    
    JButton but1=new JButton("上个月");
    JButton but2=new JButton("下个月");
    
    int re_year, re_month;
    int x_size, y_size;
    String year_num;
    Calendar now = Calendar.getInstance(); // 实例化Calendar

     MainFrame() {
        super("万年历");
        setSize(600, 700);
        x_size = (int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth());
        y_size = (int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight());
        setLocation((x_size - 300) / 2, (y_size - 350) / 2);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        panel1.add(but1);
        
        panel1.add(y_label);
        panel1.add(com1);
        panel1.add(m_label);
        panel1.add(com2);
        
        panel1.add(but2);
        
         for (int i = 0; i < 49; i++) {
            label[i] = new JLabel("", JLabel.CENTER);// 将显示的字符设置为居中
            panel2.add(label[i]);
        }
        panel3.add(new Clock(this));
        panel.add(panel1, BorderLayout.NORTH);
        panel.add(panel2, BorderLayout.CENTER);
        panel.add(panel3, BorderLayout.SOUTH);
        panel.setBackground(Color.white);
        panel1.setBackground(Color.white);
        panel2.setBackground(Color.white);
        panel3.setBackground(Color.gray);
        Init();
        but1.addActionListener(new AnAction());
        but2.addActionListener(new AnAction());
        com1.addActionListener(new ClockAction());
        com2.addActionListener(new ClockAction());
        

        setContentPane(panel);
        setVisible(true);
        setResizable(false);
    }

 
    class AnAction implements ActionListener 
     {
    	 public void actionPerformed(ActionEvent e)
    	 {
    		 int c_year, c_month,c_week;
    		 
             c_month = Integer.parseInt(com2.getSelectedItem().toString()) - 1; // 得到当前月份,并减1,计算机中的月为0-11
             c_year = Integer.parseInt(com1.getSelectedItem().toString())-1; // 得到当前所选年份
             if(e.getSource()==but1)
             {	
            	 if(c_month==0)
                 {
                	 c_year=c_year-1;
                	 c_month=11;
                 }
            	 else
            		 c_month=c_month-1;
            	 
             }
             if(e.getSource()==but2)
             {
            	 if(c_month==11)
                 {
                	 c_year=c_year+1;
                	 c_month=0;
                 }
            	 else
            		 c_month=c_month+1;
             }
             com1.setSelectedIndex(c_year);
             com2.setSelectedIndex(c_month);
             c_year = Integer.parseInt(com1.getSelectedItem().toString()); // 得到当前所选年份
             c_month = Integer.parseInt(com2.getSelectedItem().toString()) - 1; // 得到当前月份,并减1,计算机中的月为0-11
             c_week = use(c_year, c_month); // 调用函数use,得到星期几
             Resetday(c_week, c_year, c_month); // 调用函数Resetday
    		 
    	 }
    	 
     }
    
   /* class NextAction implements ActionListener 
    {
   	 public void actionPerformed(ActionEvent arg0)
   	 {
   		 int c_year, c_month,c_week;
   		 
            c_month = Integer.parseInt(com2.getSelectedItem().toString()) - 1; // 得到当前月份,并减1,计算机中的月为0-11
            c_year = Integer.parseInt(com1.getSelectedItem().toString()); // 得到当前所选年份
            if(c_month==11)
            {
           	 c_year=c_year+1;
           	 c_month=0;
            }
            c_week = use(c_year, c_month); // 调用函数use,得到星期几
            Resetday(c_week, c_year, c_month); // 调用函数Resetday
   		 
   	 }
   	 
    }
    
     */
     
     class ClockAction implements ActionListener {
         public void actionPerformed(ActionEvent arg0) {
            int c_year, c_month, c_week;
            c_year = Integer.parseInt(com1.getSelectedItem().toString()); // 得到当前所选年份
            c_month = Integer.parseInt(com2.getSelectedItem().toString()) - 1; // 得到当前月份,并减1,计算机中的月为0-11
            c_week = use(c_year, c_month); // 调用函数use,得到星期几
            Resetday(c_week, c_year, c_month); // 调用函数Resetday
        }
    }
    
     public void Init() {
        int year, month_num, first_day_num;
         String log[] = { "日", "一", "二", "三", "四", "五", "六" };
         for (int i = 0; i < 7; i++) {
            label[i].setText(log[i]);
        }
         for (int i = 0; i < 49; i = i + 7) {
            label[i].setForeground(Color.blue); // 将星期日的日期设置为红色
        }
         for (int i = 6; i < 49; i = i + 7) {
            label[i].setForeground(Color.blue);// 将星期六的日期设置为hong色
        }
         for (int i = 1; i < 10000; i++) {
            com1.addItem("" + i);
        }
         for (int i = 1; i < 13; i++) {
            com2.addItem("" + i);
        }
        month_num = (int) (now.get(Calendar.MONTH)); // 得到当前时间的月份
        year = (int) (now.get(Calendar.YEAR)); // 得到当前时间的年份
        com1.setSelectedIndex(year - 1); // 设置下拉列表显示为当前年???????????
        com2.setSelectedIndex(month_num); // 设置下拉列表显示为当前月
        first_day_num = use(year, month_num);
        Resetday(first_day_num, year, month_num);
    }

     public int use(int reyear, int remonth) {
        int week_num;
        now.set(reyear, remonth, 1); // 设置时间为所要查询的年月的第一天
        week_num = (int) (now.get(Calendar.DAY_OF_WEEK));// 得到第一天的星期
        return week_num;
    }

   // @SuppressWarnings("deprecation")
     public void Resetday(int week_log, int year_log, int month_log) {
    	 
        int month_day_score; // 存储月份的天数
        int count;
        Lunar lunar;
        int month_day;
        String[] LunarDate=new String[49];
        
        month_day_score = 0;
        count = 1;
        
        
        for (int i = 1; i < 49; i ++) {
        	for(int j=0;j<49;j=j+7)
        	{
        		if(i!=j&&i!=j+6)
        			label[i].setForeground(Color.black); 
        	}
             
        }
        

        Date date = new Date(year_log, month_log + 1, 1); // now MONTH是从0开始的, 对于一月第几天来说,DAY_OF_MONTH第一天就是1. 对于一年第几个月来说,MONTH一月份是0,二月份是1...
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, -1); // 前个月
        month_day_score = cal.getActualMaximum(Calendar.DAY_OF_MONTH);// 最后一天
        month_day=month_day_score;

         for (int i = 7; i < 49; i++) { // 初始化标签
            label[i].setText("");
        }
        week_log = week_log + 6; // 将星期数加6,使显示正确
        month_day_score = month_day_score + week_log;
        
        lunar=new Lunar();
        for(int i=0;i<month_day;i++)
        {
        	LunarDate[i]=lunar.getLunarDate( year_log,  month_log+1, i+1);
        }
        
        
        
         for (int i = week_log; i < month_day_score; i++, count++) {
        	if(month_log==9&&count==1){
        		label[i].setText(count +"国庆" );
        		label[i].setForeground(Color.red);
        	}
        	else if(month_log==0&&count==1){
        		label[i].setText(count +"元旦" );
        		label[i].setForeground(Color.red);
        		
        	}
        	else if(month_log==11&&count==24){
        		label[i].setText(count +"平安夜" );
        		label[i].setForeground(Color.red);
        		
        	}
        	else if(month_log==11&&count==25){
        		label[i].setText(count +"圣诞" );
        		label[i].setForeground(Color.red);
        	}
        	else if(month_log==1&&count==14){
        		label[i].setText(count +"情人节" );
        		label[i].setForeground(Color.red);
        	}	
        	else if(month_log==4&&count==1){
        		label[i].setText(count +"劳动节" );
        		label[i].setForeground(Color.red);
        	
        	}	
        	else if(LunarDate[i-week_log].equals("春节")||LunarDate[i-week_log].equals("元宵")||LunarDate[i-week_log].equals("端午")||LunarDate[i-week_log].equals("中秋"))
        	{
        		label[i].setText(count +LunarDate[i-week_log] );
        		label[i].setForeground(Color.red);
        	}
        	else
        		label[i].setText(count +LunarDate[i-week_log] );
        }
    }

     public static void main(String[] args) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        new MainFrame();
    }
}


作者:冲天之峰     20160623

以上是关于java万年历的主要内容,如果未能解决你的问题,请参考以下文章

JAVA线程万年历(阳历+阴历+节日+时间)

万年历-Java课程设计题(eclipse编辑器)

JAVA线程万年历(阳历+阴历+节日+时间)

Java流程控制练习--万年历

java万年历

Java实验项目二打印万年历