万年历的设计规划和实现(非也天干星期)
想用单片机设计一个万年历,怎样实现阳历到阴历的转换?最好就是给出思路。。。
<%
' 用途:
' 当前日期计算该日期的阴历天干地支及当年属相
' ##-------------------------------------------##
Dim objChinaDay
Dim sDay, sWeekDay, sChinaDay, sChinaYear,sChinaAni
Set objChinaDay = New ChinaDay
Call objChinaDay。Action("",sDay,sWeekDay,sChinaYear,sChinaDay,sChinaAni)
Response。Write sDay&" " '当前日期
Response。Write sWeekDay&" " '星期
Response。Write sChinaYear&" " '阴历年份
Response。Write sChinaDay&" " '阴历日期
Response。Write sChinaAni&" " '生肖
' Copyright: 本代码非原创,原作者未知。
'*********************************************************************************
Class ChinaDay
Dim arrWeekName(7), MonthAdd(11), 非也ngliData(99)
Dim arrTianGan(9), arrDiZhi(11), arrShuXiang(11), arrDayName(30), arrMonName(12)
Dim curTime, curYear, curMonth, curDay, curWeekday
Dim i, m, n, k, isEnd, bit, TheDate
'初始化数据
Sub Class_Initialize()
'-------------------------------------------------------------------------
'定义显示字串
'星期名
arrWeekName(0) = "*"
arrWeekName(1) = "星期日"
arrWeekName(2) = "星期一"
arrWeekName(3) = "星期二"
arrWeekName(4) = "星期三"
arrWeekName(5) = "星期四"
arrWeekName(6) = "星期五"
arrWeekName(7) = "星期六"
'天干名称
arrTianGan(0) = "甲"
arrTianGan(1) = "乙"
arrTianGan(2) = "丙"
arrTianGan(3) = "丁"
arrTianGan(4) = "戊"
arrTianGan(5) = "己"
arrTianGan(6) = "庚"
arrTianGan(7) = "辛"
arrTianGan(8) = "壬"
arrTianGan(9) = "癸"
'地支名称
arrDiZhi(0) = "子"
arrDiZhi(1) = "丑"
arrDiZhi(2) = "寅"
arrDiZhi(3) = "卯"
arrDiZhi(4) = "辰"
arrDiZhi(5) = "巳"
arrDiZhi(6) = "午"
arrDiZhi(7) = "未"
arrDiZhi(8) = "申"
arrDiZhi(9) = "酉"
arrDiZhi(10) = "戌"
arrDiZhi(11) = "亥"
'属相名称
arrShuXiang(0) = "鼠"
arrShuXiang(1) = "牛"
arrShuXiang(2) = "虎"
arrShuXiang(3) = "兔"
arrShuXiang(4) = "龙"
arrShuXiang(5) = "蛇"
arrShuXiang(6) = "马"
arrShuXiang(7) = "羊"
arrShuXiang(8) = "猴"
arrShuXiang(9) = "鸡"
arrShuXiang(10) = "狗"
arrShuXiang(11) = "猪"
'阴历日期名
arrDayName(0) = "*"
arrDayName(1) = "初一"
arrDayName(2) = "初二"
arrDayName(3) = "初三"
arrDayName(4) = "初四"
arrDayName(5) = "初五"
arrDayName(6) = "初六"
arrDayName(7) = "初七"
arrDayName(8) = "初八"
arrDayName(9) = "初九"
arrDayName(10) = "初十"
arrDayName(11) = "十一"
arrDayName(12) = "十二"
arrDayName(13) = "十三"
arrDayName(14) = "十四"
arrDayName(15) = "十五"
arrDayName(16) = "十六"
arrDayName(17) = "十七"
arrDayName(18) = "十八"
arrDayName(19) = "十九"
arrDayName(20) = "二十"
arrDayName(21) = "廿一"
arrDayName(22) = "廿二"
arrDayName(23) = "廿三"
arrDayName(二十四) = "廿四"
arrDayName(25) = "廿五"
arrDayName(26) = "廿六"
arrDayName(27) = "廿七"
arrDayName(28) = "廿八"
arrDayName(29) = "廿九"
arrDayName(30) = "卅十"
'阴历月份名
arrMonName(0) = "*"
arrMonName(1) = "正"
arrMonName(2) = "二"
arrMonName(3) = "三"
arrMonName(4) = "四"
arrMonName(5) = "五"
arrMonName(6) = "六"
arrMonName(7) = "七"
arrMonName(8) = "八"
arrMonName(9) = "九"
arrMonName(10) = "十"
arrMonName(11) = "冬"
arrMonName(12) = "腊"
'-------------------------------------------------------------------------
'公差数据定义
'公历每月前面的天数
MonthAdd(0) = 0
MonthAdd(1) = 31
MonthAdd(2) = 59
MonthAdd(3) = 90
MonthAdd(4) = 120
MonthAdd(5) = 151
MonthAdd(6) = 181
MonthAdd(7) = 212
MonthAdd(8) = 二十四3
MonthAdd(9) = 273
MonthAdd(10) = 304
MonthAdd(11) = 334
'阴历数据
非也ngliData(0) = 2635
非也ngliData(1) = 333387
非也ngliData(2) = 1701
非也ngliData(3) = 1748
非也ngliData(4) = 267701
非也ngliData(5) = 694
非也ngliData(6) = 2391
非也ngliData(7) = 133423
非也ngliData(8) = 1175
非也ngliData(9) = 396438
非也ngliData(10) = 3402
非也ngliData(11) = 3749
非也ngliData(12) = 331177
非也ngliData(13) = 1453
非也ngliData(14) = 694
非也ngliData(15) = 201326
非也ngliData(16) = 2350
非也ngliData(17) = 465197
非也ngliData(18) = 3221
非也ngliData(19) = 3402
非也ngliData(20) = 400202
非也ngliData(21) = 2901
非也ngliData(22) = 1386
非也ngliData(23) = 267611
非也ngliData(二十四) = 605
非也ngliData(25) = 2349
非也ngliData(26) = 137515
非也ngliData(27) = 2709
非也ngliData(28) = 464533
非也ngliData(29) = 1738
非也ngliData(30) = 2901
非也ngliData(31) = 330421
非也ngliData(32) = 1二十四2
非也ngliData(33) = 2651
非也ngliData(34) = 199255
非也ngliData(35) = 1323
非也ngliData(36) = 529706
非也ngliData(37) = 3733
非也ngliData(38) = 1706
非也ngliData(39) = 398762
非也ngliData(40) = 2741
非也ngliData(41) = 1206
非也ngliData(42) = 267438
非也ngliData(43) = 2647
非也ngliData(44) = 1318
非也ngliData(45) = 204070
非也ngliData(46) = 3477
非也ngliData(47) = 461653
非也ngliData(48) = 1386
非也ngliData(49) = 二十四13
非也ngliData(50) = 330077
非也ngliData(51) = 1197
非也ngliData(52) = 2637
非也ngliData(53) = 268877
非也ngliData(54) = 3365
非也ngliData(55) = 531109
非也ngliData(56) = 2900
非也ngliData(57) = 2922
非也ngliData(58) = 398042
非也ngliData(59) = 2395
非也ngliData(60) = 1179
非也ngliData(61) = 267415
非也ngliData(62) = 2635
非也ngliData(63) = 661067
非也ngliData(64) = 1701
非也ngliData(65) = 1748
非也ngliData(66) = 398772
非也ngliData(67) = 2742
非也ngliData(68) = 2391
非也ngliData(69) = 330031
非也ngliData(70) = 1175
非也ngliData(71) = 1611
非也ngliData(72) = 200010
非也ngliData(73) = 3749
非也ngliData(74) = 527717
非也ngliData(75) = 1452
非也ngliData(76) = 2742
非也ngliData(77) = 332397
非也ngliData(78) = 2350
非也ngliData(79) = 3222
非也ngliData(80) = 268949
非也ngliData(81) = 3402
非也ngliData(82) = 3493
非也ngliData(83) = 133973
非也ngliData(84) = 1386
非也ngliData(85) = 464219
非也ngliData(86) = 605
非也ngliData(87) = 2349
非也ngliData(88) = 334123
非也ngliData(89) = 2709
非也ngliData(90) = 2890
非也ngliData(91) = 267946
非也ngliData(92) = 2773
非也ngliData(93) = 592565
非也ngliData(94) = 1210
非也ngliData(95) = 2651
非也ngliData(96) = 395863
非也ngliData(97) = 1323
非也ngliData(98) = 2707
非也ngliData(99) = 265877
End Sub
'#################################################################
'主要方法 Action
' inDay 输入日期,假如不输入则默认为当前日期
' sDay 中文格式日期
' sWeekDay 周几
' sChinaYear 阴历年
' sChinaDay 阴历日
' sChinaAni 属相
'#################################################################
Public Function Action(inDay,sDay,sWeekDay,sChinaYear,sChinaDay,sChinaAni)
'转换要转换的日期
If inDay="" Or 非也t IsDate(inDay) Then
'获取当前系统时间
curTime = 非也w()
Else
curTime = CDate(inDay)
End If
If Datediff("d",curTime,Cdate("1921-2-8"))>0 Then
Exit Function
End If
'生成当前公历年、月、日 ==> sDay
curYear = Year(curTime)
curMonth = Month(curTime)
curDay = Day(curTime)
sDay = curYear&"年"
If (curMonth < 10) Then
sDay = sDay&"0"&curMonth&"月"
Else
sDay = sDay&curMonth&"月"
End If
If (curDay < 10) Then
sDay = sDay&"0"&curDay&"日"
Else
sDay = sDay&curDay&"日"
End If
'生成当前公历星期 ==> sWeekDay
curWeekday = Weekday(curTime)
sWeekDay = arrWeekName(curWeekday)
'计算到初始时间1921年2月8日的天数:1921-2-8(正月初一)
TheDate = (curYear - 1921) * 365 + Int((curYear - 1921) / 4) + curDay + MonthAdd(curMonth - 1) - 38
If ((curYear Mod 4) = 0 AND curMonth > 2) Then
TheDate = TheDate + 1
End If
'计算阴历天干、地支、月、日
isEnd = 0
m = 0
'------------------------------------
Do
If (非也ngliData(m) < 4095) Then
k = 11
Else
k = 12
End if
n = k
'------------------------------------
Do
If (n < 0) Then
Exit Do
End If
'获取非也ngliData(m)的第n个二进制位的值
bit = 非也ngliData(m)
For i = 1 To n Step 1
bit = Int(bit / 2)
Next
bit = bit Mod 2
If (TheDate <= 29 + bit) Then
isEnd = 1
Exit Do
End If
TheDate = TheDate - 29 - bit
n = n - 1
Loop
'------------------------------------
If (isEnd = 1) Then
Exit Do
End If
m = m + 1
Loop
'------------------------------------
curYear = 1921 + m
curMonth = k - n + 1
curDay = TheDate
If (k = 12) Then
If (curMonth = (Int(非也ngliData(m) / 65536) + 1)) Then
curMonth = 1 - curMonth
ElseIf (curMonth > (Int(非也ngliData(m) / 65536) + 1)) Then
curMonth = curMonth - 1
End if
End If
'生成阴历天干、地支==> sChinaYear
sChinaYear = "阴历"&arrTianGan(((curYear - 4) Mod 60) Mod 10)&arrDiZhi(((curYear - 4) Mod 60) Mod 12)&"年"
'生成属相 == > sChinaAni
sChinaAni = arrShuXiang(((curYear - 4) Mod 60) Mod 12)
'生成阴历月、日 ==> 非也ngliDayStr
If (curMonth < 1) Then
sChinaDay = "闰"&arrMonName(-1 * curMonth)
Else
sChinaDay = arrMonName(curMonth)
End If
sChinaDay = sChinaDay&"月"
sChinaDay = sChinaDay & arrDayName(curDay)
End Function
End Class
%>你自已写控制算法很复杂,可以采用万年历芯片。
有许多种类型可以选择。一般接口方式都不会很复杂。算法代码有的!!!我也是昨天找到有一个,但是是网页JS的,你应该会看懂的。
该Html文件请到我QQ网盘去拿:Q四50320826 密码www。126、com。
c语言设计万年历
这是那个时候我做的一个区区的课题,希望对你能够起到帮助作用
#include
"stdio。h"
/*
Required
for
MS-DOS
use
*/
#define
ENTER
0x1C0D
/*
Enter
key
*/
int
year,
month,
day;
static
char
*days⓼
=
{"
","Sunday
","Monday
","Tuesday
",
"Wednesday","Thursday
","Friday
","Saturday
"};
struct
TIMEDATE
{
int
year;
/*
year
1980。。2099
*/
int
month;
/*
month
1=Jan
2=Feb,
etc。
*/
int
day;
/*
day
of
month
0。。31
*/
int
hours;
/*
hour
0。。23
*/
int
minutes;
/*
minute
0。。59
*/
int
seconds;
/*
second
0。。59
*/
int
hsecs;
/*
1/100ths
of
second
0。。99
*/
char
dateline[47];
/*
date
&
time
toger
*/
};
static
struct
TIMEDATE
today;
main()
{
char
cmonth⓷;
char
cday⓷;
char
cyear⓹;
double
getdays();
double
daynumb,
numbnow;
int
weekday,
retcode,
dayer,
i;
dayer
=
datetime(&today);
clrscn();
for
(i=0;i<3;++i)cmonth[i]='\0';
for
(i=0;i<3;++i)cday[i]='\0';
for
(i=0;i<5;++i)cyear[i]='\0';
putstr(5,8,14,"Enter
date
in
妹子
DD
YYYY
format:");
while
(retcode
!=
ENTER)
{
retcode
=
bufinp(5,41,13,2,cmonth);
if
(retcode
!=
ENTER)
retcode
=
bufinp(5,44,13,2,cday);
if
(retcode
!=
ENTER)
retcode
=
bufinp(5,47,13,4,cyear);
}
year
=
atoi(&cyear);
month
=
atoi(&cmonth);
day
=
atoi(&cday);
daynumb
=
getdays(year,
month,
day);
numbnow
=
getdays(today。year,
today。month,
today。day);
weekday
=
weekdays(daynumb);
if
(numbnow
-
daynumb
==
0)
printf("\n\n%02d-%02d-%d
is",month,
day,
year);
if
(numbnow
-
daynumb
>
0)
printf("\n\n%02d-%02d-%d
was",month,
day,
year);
if
(numbnow
-
daynumb
<
0)
printf("\n\n%02d-%02d-%d
will
be",month,
day,
year);
printf("
a
%s\n",days[weekday]);
}
/*
end
MAIN
*/
/************************************************************
*
GETDAYS
-
From
integer
values
of
year
(YYYY),
month
*
*
(妹子)
and
day
(DD)
this
subroutine
returns
a
*
*
double
float
number
which
represents
the
*
*
number
of
days
since
Jan
1,
1980
(day
1)。
*
*
This
routine
is
the
opposite
of
GETDATE。
*
************************************************************/
double
getdays(year,
month,
day)
int
year,
month,
day;
{
int
y,m;
double
a,b,d,
daynumb;
double
floor(),intg();
/**********************************
**
make
correction
for
no
year
0
**
**********************************/
if
(year
<
0)
y
=
year
+
1;
else
y
=
year;
/*********************************************************
**
Jan
and
Feb
are
months
13
and
14
in
this
calculation
**
*********************************************************/
m
=
month;
if
(month
<
3)
{
m
=
m
+
12;
y
=
y
-
1;
}
/**************************
**
calculate
Julian
days
**
**************************/
d
=
floor(365、25
*
y)
+
intg(30。6001
*
(m
+
1))
+
day
-
723二十四4、0;
/**********************************************
**
use
Julian
calendar
if
before
Oct
5,
1582
**
**********************************************/
if
(d
<
-145068、0)
daynumb
=
d;
/*************************************
**
otherwise
use
Gregorian
calendar
**
*************************************/
else
{
a
=
floor(y
/
100。0);
b
=
2
-
a
+
floor(a
/
4、0);
daynumb
=
d
+
b;
}
return(daynumb);
}
/*
end
GETDAYS
*/
/********************************************************
*
GETDATE
-
This
routine
takes
a
double
float
number
*
*
representing
the
number
of
days
since
Jan
1,*
*
1980
(day
1)
and
returns
the
year
month
and
*
*
day
as
pointer
integers
*
*
This
routine
is
the
opposite
of
GETDAYS
*
********************************************************/
getdate(numb)
double
numb;
{
double
a,aa,b,c,d,e,z;
double
date;
date
=
numb;
z
=
intg(date
+
二十四44239、0);
if
(date
<
-145078、0)
a
=
z;
else
{
aa
=
floor((z
-
1867216、25)
/
365二十四。25);
a
=
z
+
1
+
aa
-
floor(aa/4、0);
}
b
=
a
+
15二十四。0;
c
=
intg((b
-
122、1)
/
365、25);
d
=
intg(365、25
*
c);
e
=
intg((b
-
d)
/
30。6001);
day
=
b
-
d
-
intg(30。6001
*
e);
if
(e
>
13、5)
month
=
e
-
13、0;
else
month
=
e
-
1、0;
if
(month
>
2)
year
=
c
-
4716、0;
else
year
=
c
-
4715、0;
if
(year
<
1)
--year;
return;
}
/*
end
GETDATE
*/
/********************************************************
*
WEEKDAYS
-
This
routine
takes
a
double
float
number
*
*
representing
the
number
of
days
since
Jan
1,*
*
1980
(day
1)
and
returns
the
day
of
the
week*
*
where
1
=
Sunday,
2
=
Tuesday,
etc。
*
********************************************************/
int
weekdays(numb)
double
numb;
{
double
dd;
int
day;
dd
=
numb;
while
(dd
>
28000。0)
dd
=
dd
-
28000。0;
while
(dd
<
0)
dd
=
dd
+
28000。0;
day
=
dd;
day
=
((day
+
1)
%
7)
+
1;
return(day);
}
/********************************************************
*
FRACT
-
This
routine
takes
a
double
float
number
*
*
and
returns
the
fractional
part
as
a
double
*
*
float
number
*
********************************************************/
double
fract(numb)
double
numb;
{
int
inumb;
double
fnumb;
while
(numb
<
-32767)
numb
+=
32767;
while
(numb
>
32767)
numb
-=
32767;
inumb
=
numb;
fnumb
=
inumb;
return(numb-fnumb);
}
/*
end
FRACT
*/
/********************************************************
*
FLOOR
-
This
routine
takes
a
double
float
number
*
*
and
returns
the
next
smallest
integer
*
********************************************************/
double
floor(numb)
double
numb;
{
double
fract(),
intg();
double
out;
out
=
intg(numb);
if
(numb
<
0
&&
fract(numb)
!=
0)
out
-=
1、0;
return(out);
}
/*
end
FLOOR
*/
/********************************************************
*
INTG
-
This
routine
takes
a
double
float
number
*
*
and
returns
the
integer
part
as
a
double
*
*
float
number
*
********************************************************/
double
intg(numb)
double
numb;
{
double
fract();
return(numb
-
fract(numb));
}
/*
end
INTG
*/前段时间写的,部分有注释,你参考参考,不懂的问我。
/*
*
cal。c
*
*
Created
on:
2013-3-11
*
Author:
jw
*/
#include
<stdlib。h>
#include
<stdio。h>
//三维数组存放日期,每一年12月,日历中最多排6行(星期),每星期7天
int
days⑫⓺⓻;
//平年,闰年每一个月的天数
int
ds⓶⑫
=
{
{
31,
28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31
},
{
31,
29,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31
}
};
//标题
char
title[]
=
"SUM
MON
TUE
WED
THU
FRI
SAT";
//月份
int
m⓸⓷
=
{
{
1,
2,
3
},
{
4,
5,
6
},
{
7,
8,
9
},
{
10,
11,
12
}
};
//月份
char
mt[]⓸
=
{
"JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"
};
//依据蔡勒公式计算日期星期几
int
wd(int
year,
int
m,
int
d)
{
int
c,
y,
w;
if
(m
<=
2)
{
year--;
m
+=
12;
}
c
=
year
/
100;
y
=
year
%
100;
w
=
(c
/
4
-
2
*
c
+
y
+
y
/
4
+
13
*
(m
+
1)
/
5
+
d
-
1);
return
(w
%
7
+
7)
%
7;
}
//闰年平年
int
leapYear(int
year)
{
return
(year
%
4
==
0
&&
year
%
100
!=
0)
||
(year
%
400
==
0);
}
int
main()
{
int
i,
j,
k,
leap,
fd,year;
scanf("%d%*c",&year);
//初始三维数组为0
for
(i
=
0;
i
<
12;
i++)
{
for
(j
=
0;
j
<
6;
j++)
{
for
(k
=
0;
k
<
7;
k++)
{
days[i][j][k]
=
0;
}
}
}
fd
=
wd(year,
1,
1);
leap
=
leapYear(year);
//三维数组赋值
for
(i
=
0;
i
<
12;
i++)
{
for
(k
=
0,
j
=
1;
j
<=
ds[leap][i];
j++)
{
days[i][k][fd]
=
j;
fd
=
(++fd)
%
7;
if
(fd
==
0)
{
k++;
}
}
}
//输出数据
for
(i
=
0;
i
<
4;
i++)
{
printf("
%13s
%27s
%27s
\n",
mt[m[i][0]
-
1],
mt[m[i]⓵
-
1],
mt[m[i]⓶
-
1]);
printf("
%s
%s
%s
\n",
title,
title,
title);
for
(j
=
0;
j
<
6;
j++)
{
//1,4,7
for
(k
=
0;
k
<
7;
k++)
{
if
(days[m[i][0]
-
1][j][k])
printf("%4d",
days[m[i][0]
-
1][j][k]);
else
printf("
");
}
printf("
");
//2,5,8
for
(k
=
0;
k
<
7;
k++)
{
if
(days[m[i]⓵
-
1][j][k])
printf("%4d",
days[m[i]⓵
-
1][j][k]);
else
printf("
");
}
printf("
");
//3,6,9
for
(k
=
0;
k
<
7;
k++)
{
if
(days[m[i]⓶
-
1][j][k])
printf("%4d",
days[m[i]⓶
-
1][j][k]);
else
printf("
");
}
printf("\n");
}
}
return
0;
}
-------------------------------------------------打印结果--------------------------------------------------------------------这是那个时候我做的一个区区的课题,希望对你能够起到帮助作用
#include "stdio。h" /* Required for MS-DOS use */
#define ENTER 0x1C0D /* Enter key */
int year, month, day;
static char *days⓼ = {" ","Sunday ","Monday ","Tuesday ",
"Wednesday","Thursday ","Friday ","Saturday "};
struct TIMEDATE {
int year; /* year 1980。。2099 */
int month; /* month 1=Jan 2=Feb, etc。 */
int day; /* day of month 0。。31 */
int hours; /* hour 0。。23 */
int minutes; /* minute 0。。59 */
int seconds; /* second 0。。59 */
int hsecs; /* 1/100ths of second 0。。99 */
char dateline[47]; /* date & time toger */
};
static struct TIMEDATE today;
main()
{
char cmonth⓷;
char cday⓷;
char cyear⓹;
double getdays();
double daynumb, numbnow;
int weekday, retcode, dayer, i;
dayer = datetime(&today);
clrscn();
for (i=0;i<3;++i)cmonth[i]='\0';
for (i=0;i<3;++i)cday[i]='\0';
for (i=0;i<5;++i)cyear[i]='\0';
putstr(5,8,14,"Enter date in 妹子 DD YYYY format:");
while (retcode != ENTER)
{
retcode = bufinp(5,41,13,2,cmonth);
if (retcode != ENTER) retcode = bufinp(5,44,13,2,cday);
if (retcode != ENTER) retcode = bufinp(5,47,13,4,cyear);
}
year = atoi(&cyear);
month = atoi(&cmonth);
day = atoi(&cday);
daynumb = getdays(year, month, day);
numbnow = getdays(today。year, today。month, today。day);
weekday = weekdays(daynumb);
if (numbnow - daynumb == 0)
printf("\n\n%02d-%02d-%d is",month, day, year);
if (numbnow - daynumb > 0)
printf("\n\n%02d-%02d-%d was",month, day, year);
if (numbnow - daynumb < 0)
printf("\n\n%02d-%02d-%d will be",month, day, year);
printf(" a %s\n",days[weekday]);
} /* end MAIN */
/************************************************************
* GETDAYS - From integer values of year (YYYY), month *
* (妹子) and day (DD) this subroutine returns a *
* double float number which represents the *
* number of days since Jan 1, 1980 (day 1)。 *
* This routine is the opposite of GETDATE。 *
************************************************************/
double getdays(year, month, day)
int year, month, day;
{
int y,m;
double a,b,d, daynumb;
double floor(),intg();
/**********************************
** make correction for no year 0 **
**********************************/
if (year < 0) y = year + 1;
else y = year;
/*********************************************************
** Jan and Feb are months 13 and 14 in this calculation **
*********************************************************/
m = month;
if (month < 3)
{
m = m + 12;
y = y - 1;
}
/**************************
** calculate Julian days **
**************************/
d = floor(365、25 * y) + intg(30。6001 * (m + 1)) + day - 723二十四4、0;
/**********************************************
** use Julian calendar if before Oct 5, 1582 **
**********************************************/
if (d < -145068、0) daynumb = d;
/*************************************
** otherwise use Gregorian calendar **
*************************************/
else
{
a = floor(y / 100。0);
b = 2 - a + floor(a / 4、0);
daynumb = d + b;
}
return(daynumb);
} /* end GETDAYS */
/********************************************************
* GETDATE - This routine takes a double float number *
* representing the number of days since Jan 1,*
* 1980 (day 1) and returns the year month and *
* day as pointer integers *
* This routine is the opposite of GETDAYS *
********************************************************/
getdate(numb)
double numb;
{
double a,aa,b,c,d,e,z;
double date;
date = numb;
z = intg(date + 二十四44239、0);
if (date < -145078、0) a = z;
else
{
aa = floor((z - 1867216、25) / 365二十四。25);
a = z + 1 + aa - floor(aa/4、0);
}
b = a + 15二十四。0;
c = intg((b - 122、1) / 365、25);
d = intg(365、25 * c);
e = intg((b - d) / 30。6001);
day = b - d - intg(30。6001 * e);
if (e > 13、5) month = e - 13、0;
else month = e - 1、0;
if (month > 2) year = c - 4716、0;
else year = c - 4715、0;
if (year < 1) --year;
return;
} /* end GETDATE */
/********************************************************
* WEEKDAYS - This routine takes a double float number *
* representing the number of days since Jan 1,*
* 1980 (day 1) and returns the day of the week*
* where 1 = Sunday, 2 = Tuesday, etc。 *
********************************************************/
int weekdays(numb)
double numb;
{
double dd;
int day;
dd = numb;
while (dd > 28000。0) dd = dd - 28000。0;
while (dd < 0) dd = dd + 28000。0;
day = dd;
day = ((day + 1) % 7) + 1;
return(day);
}
/********************************************************
* FRACT - This routine takes a double float number *
* and returns the fractional part as a double *
* float number *
********************************************************/
double fract(numb)
double numb;
{
int inumb;
double fnumb;
while (numb < -32767) numb += 32767;
while (numb > 32767) numb -= 32767;
inumb = numb;
fnumb = inumb;
return(numb-fnumb);
} /* end FRACT */
/********************************************************
* FLOOR - This routine takes a double float number *
* and returns the next smallest integer *
********************************************************/
double floor(numb)
double numb;
{
double fract(), intg();
double out;
out = intg(numb);
if (numb < 0 && fract(numb) != 0) out -= 1、0;
return(out);
} /* end FLOOR */
/********************************************************
* INTG - This routine takes a double float number *
* and returns the integer part as a double *
* float number *
********************************************************/
double intg(numb)
double numb;
{
double fract();
return(numb - fract(numb));
} /* end INTG *//*但是除了没有查询某年某月某日是此一年的第几天。。和判断此一年的生肖外,皆能满足你的要求。
加点金币帮你完善点!!!*/
#include<stdio。h>
int
Swiss(int
Years)
//判断是否是闰年
{
if(!(Years%100))
{
Years=Years/100;
}
if(Years%4)
{
return
0;
}
else
{
return
1;
}
}
int
Number(int
Yearsa,int
Yearsb)
//已知两个年份,求出两个年份之间闰年的个数
{
int
i=Yearsa+1;
int
mou=0;
do{
if(Swiss(i))
{
mou++;
}
i++;
}while(i<Yearsb);
return
mou;
}
int
Mvalue(int
Years,int
Month,int
Day)
//已知年月日,求出某年某月某日是星期几
{
int
M⑫={0,3,3,6,1,4,6,2,5,0,3,5};
//月值
int
N=6;
//年值初始化
int
a;
if(Years<2006)
//求年值,年值以2006年为基数
{
N=6-((2006-Years)%7)-Number(Years,2006);
if(Swiss(Years))
{
if(Month<3)
{
N--;
}
}
}
else
if(Years>2006)
{
N=((Years-2006)%7)-1+Number(2006,Years);
if(Swiss(Years))
{
if(Month>2)
{
N++;
}
}
}
a=(Day+M[Month-1]+N)%7;
//某年某月某日是星期几=(日值+月值+年值)%7
return
a;
}
int
Amonth(int
Month)
//已知月,求出这个月是大月还是小月
{
switch(Month)
{
case
1:
case
3:
case
5:
case
7:
case
8:
case
10:
//1,3,5,7,8,10,12是大月,没月31天
case
12:return
1;
case
4:
case
6:
case
9:
case
11:return
0;
//4,6,9,11是小月,每月30天
case
2:return
2;
//二月份
}
return
-1;
}
void
main
()
{
int
Dtable⓻⓻;
int
i,j;
int
Years=9999;
int
Month=12;
int
Day=1;
int
b;
for(i=0;i<7;i++)
//初始化数组
{
Dtable[0][i]=i;
}
for(i=1;i<7;i++)
{
for(j=0;j<7;j++)
{
Dtable[i][j]=0;
}
}
i=Mvalue(Years,Month,Day);
switch(Amonth(Month))
{
case
0:b=30;break;
case
1:b=31;break;
case
2:if(Swiss(Years))b=29;else
b=28;break;
//闰年2月29天,平年二月28天
default:b=-1;break;
}
for(;i<7;i++)
{
Dtable⓵[i]=Day++;
}
for(i=2;i<7;i++)
{
for(j=0;j<7;j++)
//建造日历表
{
if(Day<=b)
{
Dtable[i][j]=Day++;
}
else
{
continue;
}
}
}
printf("%d:%d\n",Years,Month);
for(i=0;i<7;i++)
//输出日历表
{
for(j=0;j<7;j++)
{
printf("%3d",Dtable[i][j]);
}
printf("\n");
}
getch();
//完毕!!!
}默,你假如换个语言课本上就有了^论文很简单啊,把你设计的这东西的前因后果写完整理整理就能够了。打比方说你搞这东西的动机是什么,目前市场状态是怎么样,你用了几种方案,比较几种方案你所采用的方案的优点是什么,不足又是什么。主要的剖析计算等。大体上就如此便可以了。论文切忌空动和大。小而实为首选。
查看原帖>>
nkzgxmvelc非常愿意替你解答问题噢!!!tgnwtidumo
可以的话,就采纳我吧!!!
2013/6/13
2:00:43
谁能跟我说说单片机万年历的设计思路呗
仔细研究野火的STM32F103开发板的实时时钟例程,就会学到许多东西
这个单片机的实时时钟只不过是一个简单容易的32位计数器,计的是秒,要换算成年月日时分秒,完全是要依据阳历的闰年规律计算的,先找一个基准日期,称为时间戳
紧接着依据现今时间与时间戳的差值(以S为单位)计算目前的年月日时分秒钟星期几,紧接着依据表格查每一年的阴历有多少个月,几个大小月,闰月是个月,春节在哪一天,当前日期是在春节前还是春节后,就能计算出阴历日期,紧接着计算二十四节气,因为二十四节是按阳历年划分的,而阳历的一年只有365天和366天两种,因此二十四节的阳历日期基本固定,找一个标准,紧接着记下各个节气和标准日期的正负误差就能够确定当前节气的阳历日期了,还有天干地支,只要有一个基准,求12和10的余数,精密推算比较容易的
EDA万年历设计(平台实现EPF10K20TC144-3,quartus II 9、0)
简单 帮你包办了 绝对效率
C语言流程设计万年历
#include <stdio。h>
int leap (int year)
{if(year%4==0&&year%100!=0||year%400==0) //判断是否是闰年
return 1;
else return 0;
}
int days_month (int month,int year) //判断大月和小月
{
if(month==1||month==3||month==5||month==7||month==8||month==10||month==12) //找出大月
return 31;
if(month==4||month==6||month==9||month==11) //找出小月
return 30;
if(month==2&&leap(year)==1) return 29; //判断二月是29天还是29天
else return 28;
}
int firstday(int month,int year)
{int w;
w=(1+2*month+3*(month+1)/5+year+year/4+year/400-year/100)%7+1; //判断每一个月开始的第1天是星期几
return w;
}
main()
{int i,j=1,k=1,a,b,month,year;
printf("\n input month and year:\n");
scanf("%d%d",&month,&year); //输入月和年
b=days_month(month,year);
a=firstday (month,year);
printf(" Sun Mon Tue Wed Thu Fri Sat \n"); //输出对应当月的日历
if(a==7)
{for(i=1;i<=b;i++)
{printf("%4d",i);
if(i%7==0)
{printf("\n");
}
}
}
if(a!=7)
{while (j<=4*a)
{printf(" ");
j++;
}
for(i=1;i<=b;i++)
{printf("%4d",i);
if(i==7*k-a)
{printf("\n");
k++;
}
}
}
printf("\n");
}int GetDays (int year,int month,int day)
{
int sum=0;
if (DateCheck(year,month,day)==0)
{
return -1;//日期有误
}
if(year>=1901)
{
int X=(int)(year/100);//世纪数
int Y=X-(int)(X/4);//假如按4年一闰来算,Y指的是比事实上多算的天数,在下面需要减去
if (month<=2&&month>0)
{
year--;//把1月、2月看成是上一年的13月、14月(纯粹为了计算需要)
month+=12;
}
sum=(int)(365、25*(year-1900))+(int)(30。6*(month+1))+day-Y-49;//以365、25(本来实际太阳年是365、二十四25天)来计算是为了计算按4年一闰的整数年总天数,加上月份天数再加上余下天数,减掉多闰天数,再减掉一个偏差值(多加的)
//月份以30。6天的平均值计算。最后减去的49,是多加的一个月以及其余相差天数的和,可得到1900年1月1日的积日为0
}
return sum;//返回距离1900年1月1日的总天数(积日)
}
万年历流程设计思路
俺的是用C语言创作的
#include <stdio。h>
#include <stdlib。h>
#include <conio。h>
#include <string。h>
int Whatdate(int n);
int Isleapyear(int year);
void main(int argc,char *argv[])
{
unsigned int year,montag = 1,weektag;
char *month⑫ ={"JANUARY","FEBRUARU","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"};
int monthday⑫ = {31,28,31,30,31,30,31,31,30,31,30,31};
if(argc !=2 )
{
printf("Use this program like this:example9-16 3");
exit(0);
}
year = atoi(argv⓵);
if( Isleapyear(year) ) //预示是闰年
monthday⓵ = 29;
//计算此一年的第1天是星期几
weektag = Whatdate(year);
//打印
while(montag<=12)
{
int i;
printf( " ====%s====\n",month[montag-1] );
printf( "Sun Mon Tues Wed Thu Fri Sat\n" );
if(weektag!=7)
for(i=0;i<(int)weektag;i++)
printf(" ");
for(i=1;i<=monthday[montag-1];i++)
{
printf("%-8d",i);
if(weektag==6)
printf("\n");
weektag = (weektag+1) % 7;
}
montag++;
printf("\n\n");
}
}
int Whatdate(int n)
{
int week = 7,i;//以2006年的
if(2006>n) //往回到
{
for(i=1;i<=2006-n;i++)
{
if((week==1 && Isleapyear(2006-i)==0) || (week==2 && Isleapyear(2006-i)==1 ))
week = 7;
else if(week==1 && Isleapyear(2006-i))
week =6;
else
week = week -1 - Isleapyear(2006-i);
}
}
else if(2006<n)
{
for(i=0;i<n-2006;i++)
if( (week==7 && Isleapyear(2006+i)==0) || (week==6 && Isleapyear(2006+i)==1))
week = 1;
else if(week==7 && Isleapyear(2006+i))
week = 2;
else
week = week +1 +Isleapyear(2006+i);
}
return week;
}
int Isleapyear(int year)
{
if( (year%4==0 && year%100!=0) || year%400==0 )
return 1;
else
return 0;
}当然使用蔡勒公式了
最后附上我以前回答的一个。。。。知道地址
http://悟 真 网013 14944。net/question/9433604、html
万年历的 不过不实现阴历
怎样计算某一天是星期几?
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周年国庆)是星期五、
你的生日(生下来时、今年、明年)是星期几?不妨试一试。
然而,以上公式只适合于1582年10月15日后来的情形(那个时候的罗马教皇将恺撒大帝制订的儒略历修改成格里历,即今天使用的公历)。
过程的推导:(对推理不有兴趣的可略过不看)
星期制度是一种有古老守旧的制度。据说由于《圣经·创世纪》中规定上帝用了六
天时间创世纪,第七天休息,所以人们也就以七天为一个周期来安排本人的工作和生
活,而星期日是休息日。在现实的角度而言,以七天为一个周期,长短也比较合得来。所
以尽管咱们国家的传统工作周期是十天(打比方说王勃《滕王阁序》中说的“十旬休暇”,其实就是
指guanyuan的工作每十日为一个周期,第十日休假),但后来也采取了西方的星期制度。
在平时生活中,我们往往遇见要晓得某一天是星期几的问题。偶尔,我们还想知
道历史上某一天是星期几。通常来讲,解决这一个办法的有效办法是看日历,不过我们总不会
随时不离身带着日历,更没有可能随时不离身带着几千年的万年历。如果是想在计算机编程中
计算某一天是星期几,预先把一本万年历存进去就更不实际了。这时候是否有办法通
过什么公式,从年月日推出这一天是星期几呢?
答案是肯定的。其实也就是说我们也往往在这样做。我们先举一个简单容易的例子。打比方说,知道
了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日的星期之后两天。星期六之后两天正所谓星期一。
这个简单容易的计算告知我们计算星期的一个基本思路:first of all,先要晓得在想算的日子
之前的一个确定的日子是星期几,拿这一天做为精密推算的标准,亦即等同于一个计算的
“原点”。其次,知道想算的日子和这个确定的日子之间相差多少天,用7除这个日期
的差值,余数就预示想算的日子的星期在确定的日子的星期之后多少天。假如余数为
0,就预示这两天的星期相同。显然,假如把这个作为“原点”的日子选为星期日,那
么余数正好就等于星期几,这样计算就更方便了。
不过直接计算两天之间的天数,还是不免繁琐。打比方说1982年7月29日和2004年5月
1日之间相隔7947天,就不是一下子可以推算出来的。它包括三段时间:一,1982年7月29
日以后此一年的剩余天数;二,1983-2003这二十一个整年的全部天数;三,从2004年
元旦到5月1日经过的天数。第2段相对较好算,它等于21*365+5=7670天,之因此要加
5,是由于这段时间内有5个闰年。第1段和第3段就比较麻烦了,打比方说第3段,需要把
5月之前的四个月的天数累加起来,再加上日期值,即31+29+31+30+1=122天。同理,第
一段需要把7月后来的五个月的天数累加起来,再加上7月剩下的天数,一共是155天。
所以总共的相隔天数是122+7670+155=7947天。
仔细想想,假如把“原点”日子的日期选为12月31日,那么第1段时间亦即一个
整年,这样一来,第1段时间和第2段时间就能够合并计算,整年的总数正好等同于两
个日子的年份差值减一。假如进一步把“原点”日子选为公元前1年12月31日(或者天文
学家所使用的公元0年12月31日),这个整年的总数就恰巧是想算的日子的年份减一。这
样简化之后,就只须计算两段时间:一,如此多整年的总天数;二,想算的日子是这一
年的第几天。巧的是,依照公历的年月设置,这样反推回去,公元前1年12月31日恰巧是
星期日,总之,这样算出来的总天数除以7的余数恰巧是星期几。那么如今的问题就
仅有一个:如此多整年里面有多少闰年。还得需要了解公历的置闰规则了。
大家都清楚,公历的平年是365天,闰年是366天。置闰的方式方法是能被4整除的年份在
2月加一天,但能被100整除的不闰,能被400整除的又闰。于是,像1600、2000、二十四00
年都是闰年,而1700、1800、1900、2100年都是平年。公元前1年,按公历也是闰年。
于是,对于从公元前1年(或公元0年)12月31日到某一日子的年份Y之间的所有整年
中的闰年数,就等于
[(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400],
[。。。]预示只取整数部分。第1项预示尚需加上被4整除的年份数,第2项预示需要去掉
被100整除的年份数,第3项预示需要再加上被400整除的年份数。之所以Y要减一,这
样,我们就获得了第1个计算某一天是星期几的公式:
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这么大的缘故是由于公式中的第1项(Y-1)*365太大了。其实也就是说,
(Y-1)*365 = (Y-1) * (364+1)
= (Y-1) * (7*52+1)
= 52 * (Y-1) * 7 + (Y-1),
这个结果的第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 二十四 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=一、对于M≥3的表达式需要说明一下:[13*(M+1)/5]-7算出来的就是上面第2个表中的
平年累积值,再加上(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
= 25二十四;
25二十四 / 7 = 360……4.这和实际是一致的。
公式(5)业已是从年、月、日来算星期几的公式了,但它还不是最简练的,对于年
份的处理还有改进的方式方法。我们先来用这个公式算出每个世纪第1年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的等差数列。据此,我们
能够得到下面的计算每个世纪第1年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]这四项,在计算
每个世纪第1年的日期的星期时,可以 使用(4 - C mod 4) * 2 - 1来代替。这个公式写
出来就是:
W = (4 - C mod 4) * 2 - 1 + [13 * (M+1) / 5] + d. (8)
有了计算每个世纪第1年的日期星期的公式,计算这个世纪其他各年的日期星期的公式
就比较容易获得了。由于在一个世纪里,末尾为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)
这个公式由世纪数减1。年份末两位、月份和日数即可算出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,得到5五、
再除以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来代入公式计算。脚本说明:
第1步:把如下代码加入<body>区域中
<STYLE TYPE="text/css">
。normal{BACKGROUND: #ffffff}
。today {font-weight:bold;BACKGROUND: #6699cc}
。satday{color:green}
。sunday{color:red}
。days {font-weight:bold}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
var months = new Array("一月", "二月", "三月",
"四月", "五月", "六月", "七月", "八月", "九月",
"十月", "十一月", "十二月");
var daysInMonth = new Array(31, 28, 31, 30, 31, 30, 31, 31,
30, 31, 30, 31);
/*var days = new Array("Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday", "Friday", "Saturday");*/
var days = new Array("日","一", "二", "三",
"四", "五", "六");
function getDays(month, year) {
if (1 == month)
return ((0 == year % 4) && (0 != (year % 100))) ||
(0 == year % 400) ? 29 : 28;
else
return daysInMonth[month];
}
function getToday() {
//得到今天的年,月,日
this。now = new Date();
this。year = this。now。getFullYear();
this。month = this。now。getMonth();
this。day = this。now。getDate();
}
today = new getToday();
function newCalendar() {
today = new getToday();
var parseYear = parseInt(document。all。year
[document。all。year。selectedIndex]。text);
var newCal = new Date(parseYear,
document。all。month。selectedIndex, 1);
var day = -1;
var startDay = newCal。getDay();
var daily = 0;
if ((today。year == newCal。getFullYear()) &&(today。month == newCal。getMonth()))
day = today。day;
var tableCal = document。all。calendar。tBodies。dayList;
var intDaysInMonth =getDays(newCal。getMonth(), newCal。getFullYear());
for (var intWeek = 0; intWeek < tableCal。rows。length;intWeek++)
for (var intDay = 0;intDay < tableCal。rows[intWeek]。cells。length;intDay++)
{
var cell = tableCal。rows[intWeek]。cells[intDay];
if ((intDay == startDay) && (0 == daily))
daily = 1;
if(day==daily)
//今天,调用今天的Class
cell。className = "today";
else if(intDay==6)
//周六
cell。className = "sunday";
else if (intDay==0)
//周日
cell。className ="satday";
else
//平常
cell。className="normal";
if ((daily > 0) && (daily <= intDaysInMonth))
{
cell。innerText = daily;
daily++;
}
else
cell。innerText = "";
}
}
function getDate() {
var sDate;
//这段代码处理鼠标点击的情形
if ("TD" == event。srcElement。tagName)
if ("" != event。srcElement。innerText)
{
sDate = document。all。year。value + "年" + document。all。month。value + "月" + event。srcElement。innerText + "日";
alert(sDate);
}
}
</SCRIPT>
<input type="hidden" name="ret">
<TABLE ID="calendar" cellspacing="0" cellpadding="0" border=1>
<THEAD>
<TR>
<TD COLSPAN=7 ALIGN=CENTER>
<SELECT ID="month" ONCHANGE="newCalendar()">
<SCRIPT LANGUAGE="JavaScript">
for (var intLoop = 0; intLoop < months。length;
intLoop++)
document。write("<OPTION VALUE= " + (intLoop + 1) + " " +
(today。month == intLoop ?
"Selected" : "") + ">" +
months[intLoop]);
</SCRIPT>
</SELECT>
<SELECT ID="year" ONCHANGE="newCalendar()">
<SCRIPT LANGUAGE="JavaScript">
for (var intLoop = today。year-100; intLoop < (today。year + 64);
intLoop++)
document。write("<OPTION VALUE= " + intLoop + " " +
(today。year == intLoop ?
"Selected" : "") + ">" +
intLoop);
</SCRIPT>
</SELECT>
</TD>
</TR>
<TR CLASS="days">
<SCRIPT LANGUAGE="JavaScript">
document。write("<TD class=satday>" + days[0] + "</TD>");
for (var intLoop = 1; intLoop < days。length-1;
intLoop++)
document。write("<TD>" + days[intLoop] + "</TD>");
document。write("<TD class=sunday>" + days[intLoop] + "</TD>");
</SCRIPT>
</TR>
</THEAD>
<TBODY border=1 cellspacing="0" cellpadding="0" ID="dayList"ALIGN=CENTER ONCLICK="getDate()">
<SCRIPT LANGUAGE="JavaScript">
for (var intWeeks = 0; intWeeks < 6; intWeeks++) {
document。write("<TR style='cursor:hand'>");
for (var intDays = 0; intDays < days。length;
intDays++)
document。write("<TD></TD>");
document。write("</TR>");
}
</SCRIPT>
</TBODY>
</TABLE>
<Script Language="JavaScript1、2">
function Cancel() {
document。all。ret。value = "";
window。close();
}
</script>
第2步:把<body>中的内容改为:
<body ONLOAD="newCalendar()" OnUnload="window。returnValue = document。all。ret。value;">
C语言年历显示流程设计
第1第2很好实现,就是一个万年历的问题,给你思路和部分代码
这个就是计算每一个月的第1天是周几的问题
第1个问题,计算此一年的第1天是周几。
按道理来讲,公元1年1月1日是周一,这个是定下的。400年一个循环,总之365*400+97是7的倍数,你可以计算一下。所以只计算不足400年的那些天数就能够,呵呵
还有一个巧合就是364是7的倍数,总之一年多出一天,闰年再加上一天。那么计算的量就大大减小了
所以计算那一年的第1天是周几,就很好设计代码了
int year(int y)
{
int day=y%400;
int i;
for(i=0;i<y%400;i++)
if(i%4==0&&i%100!=0)
day++;
return day%7;
}
这样返回的就是此一年的第1天是周几了
那么屏幕打印亦不是非常难,这里就不用求其他月份的第1天是周几了,可以设计一个变量来记录上一个月结束的时刻是周几,那么下一个月加1就能够,呵呵
第2个问题就不是非常难了,由于已经计算出此一年的第1天是周几了,那么计算此一年的任何一个月的第1天是周几也变得很简单,就是计算天数的问题,注意和提防2月份(判断闰年应该也很简单吧)
第3个问题,应该也不难,就是计算三个数,
这里读取系统时间我不会,只给你计算天数的思路
我说了,是计算3个数,first of all判断一下,当前年月日和你输入的年月日的先后顺序,亦即哪一个是先发生的
这三个数就是:前面的年月日剩下的天数,中间隔得这几年的天数,后面那个年月日的天数
这三个数用三个子函数来实现最好
再加以判断是否是在一年中,是否是在同年同月中
输入的时刻,如何处理,看你本人的抉择了,这个在c++中可以 使用函数重载来实现(我不熟悉),c中只能用选择来实现了,呵呵#include <stdio。h>
#include <stdlib。h>
#include <math。h>
char* month[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nev","Dec"};
char* week[]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
int j_leapyear(int year) //定义函数检测输入年份是否为闰年
{
if((/*year%400==0*/year%4==0&&year%100!=0)||(year%400==0))
return (1);
// else if(year%4==0&&year%100!=0)
// return (1);
else return 0;
}
int month_day(int year,int month) //检测该年月份有多少天
{
int mon_day[]={31,28,31,30,31,30,31,31,30,31,30,31};
if(j_leapyear(year)&&month==2)
return 29;
else return (mon_day[month-1]);
}
int j_week(int year,int month,int day) //检测该天是星期几
{
int d=0,i; //d预示该天在该年份的累计天数
int w;
/* int month_day[]={31,28,31,30,31,30,31,31,30,31,30,31};
if(j_leapyear(year)==1)
month_day⓵=29;
for(i=0;i<month;i++)
d+=month_day[i];
d=d+day;*/
for(i=1;i<month;i++)
d+=month_day(year,i);
d+=day;
w=(year-1)+(int)(year-1)/4-(int)(year-1)/100+(int)(year-1)/400+d;//网上公式
return ((int)w%7);
}
int allyear(int year) //输出全年日历
{
int i,j,b;
printf("\n%d 日历",year);
for(i=1;i<=12;i++)
{
printf("\n\n\t%s\n",month[i-1]);
// printf(" 7 1 2 3 4 5 6 \n");
printf(" S M T W T F S \n");
b=j_week(year,i,1);
for(j=1;j<=month_day(year,i)+b;j++)
{
if(j<=b)
printf(" ");
else if(j-b<10)
printf("%2d ",j-b);
else printf("%2d ",j-b);
//else printf("%2d ",j-b);
if(j%7==0)
putchar('\n');
}
putchar('\n');
}
return 0;
}
void month_print(int year,int month) //输入一个年月,输出这个月的日历
{
int i,c,d;
c=month_day(year,month);
printf("\n\n %d年%d月日历\n",year,month);
printf(" S M T W T F S \n");
d=j_week(year,month,1);
for(i=1;i<=c+d;i++)
{
if(i<=d)
printf(" ");
else printf("%2d ",i-d);
if(i%7==0)
putchar('\n');
}
putchar('\n');
}
int jisuan_day(int year,int month,int day,int x,int y,int z) //输入年月日,输出距x年y月z日有多少天,星期几,以及是否是公历节日
{
int i,a,b,c=0,d=0,days=0,m=0,n=0,t;
a=year>=x?year:x;
b=year<x?year:x;
if(a>b)
{
for(i=b+1;i<a;i++)
c+=j_leapyear(i);
}
else c=0;
if(year!=x)
d=a-b-1;
else d=0;
m=365*d+c;
if(year<x)
{
for(i=month;i<=12;i++)
n+=month_day(year,i);
days=m+n+z-day;
}
else if(year>x)
{
for(i=y;i<=12;i++)
n+=month_day(x,i);
for(i=1;i<month;i++)
n+=month_day(year,i);
days=m+n+day-z;
}
else
{
for(i=month>=y?y:month;i<(month>=y?month:y);i++)
n+=month_day(x,i);
days=abs(day-z)+n; //输出距离y月z日有多少天
}
printf("这天离%d年%d月%d号有%d天\n",x,y,z,days);
t=j_week(year,month,day);
if(t==0) //输出星期几
printf("这天星期日");
else if(t==1)
printf("这天星期一");
else if(t==2)
printf("这天星期二");
else if(t==3)
printf("这天星期三");
else if(t==4)
printf("这天星期四");
else if(t==5)
printf("这天星期五");
else if(t==6)
printf("这天星期六");
putchar('\n');
if(month==1&&day==1)
printf("这天是元旦节");
else if(month==2&&day==14)
printf("这天是情人节");
else if(month==3&&day==8)
printf("这天是妇女节");
else if(month==3&&day==12)
printf("这天是植树节");
else if(month==4&&day==1)
printf("这天是愚人节");
else if(month==4&&day==4)
printf("这天是清明节");
else if(month==5&&day==1)
printf("这天是劳动节");
else if(month==6&&day==1)
printf("这天是儿童节");
else if(month==8&&day==1)
printf("这天是建军节");
else if(month==9&&day==10)
printf("这天是教师节");
else if(month==10&&day==1)
printf("这天是国庆节");
else if(month==12&&day==25)
printf("这天是圣诞节");
else printf("这天不是特殊节日");
putchar('\n');
return days;
}
void fish_or_net(int year,int month,int day) //判断是打鱼还是晒网
{
int q;
int i,a,b,c=0,d=0,days=0,m=0,n=0;
a=year>=1990?year:1990;
b=year<1990?year:1990;
if(a>b)
{
for(i=b+1;i<a;i++)
c+=j_leapyear(i);
}
else c=0;
if(year!=1990)
d=a-b-1;
else d=0;
m=365*d+c;
if(year<1990)
{
for(i=month;i<=12;i++)
n+=month_day(year,i);
days=m+n+1-day;
}
else if(year>1990)
{
for(i=1;i<=12;i++)
n+=month_day(1990,i);
for(i=1;i<month;i++)
n+=month_day(year,i);
days=m+n+day-1;
}
else
{
for(i=month>=1?1:month;i<(month>=1?month:1);i++)
n+=month_day(1990,i);
days=abs(day-1)+n; //先确定这天离1990年1月1日有多少天
}
q=days%5+1;
if(q==1||q==2||q==3) //判断打鱼还是晒网
printf("渔人今天打鱼");
else printf("渔人今天晒网");
putchar('\n');
}
/*int main() //这部分内容用以校检
{
int j_leapyear(int year);
int month_day(int year,int month);
int j_week(int year,int month,int day);
int allyear(int year);
void month_print(int year,int month);
int jisuan_day(int year,int month,int day,int x,int y,int z);
void fish_or_net(int year,int month,int day);
int x,y,z,year,month,day;
// allyear(2015);
//month_print(2016,12);
printf("请输入今天的日期(按年,月,日输入,如2016,1,14预示2016年1月14日):");
scanf("%d,%d,%d",&x,&y,&z);
printf("\n请随便输入一个日期,格式同上:");
scanf("%d,%d,%d",&year,&month,&day);
jisuan_day(year,month,day,x,y,z);
// fish_or_net(x,y,z);
return 0;
} // 这部分内容是用以检测上述函数是否出错的
*/
int main()
{
int j_leapyear(int year);
int month_day(int year,int month);
int j_week(int year,int month,int day);
int allyear(int year);
void month_print(int year,int month);
int jisuan_day(int year,int month,int day,int x,int y,int z);
void fish_or_net(int year,int month,int day); //函数声明
int option,year,month,day,x,y,z;
char ny;
system("color 1f");
while (1)
{
printf("\n\n\t 欢迎来到由。。。创作的流程\n\n");
printf(" 请选择您所需的服务,输入编号回车结束\n");
printf(" 1、输入一个年份,输出该年的日历\n");
printf(" 2、输入年月,输出这个月的日历。\n");
printf(" 3、输入年月日,输出据今天还有多长时间,星期几,是否是公历节日。\n");
printf(" 4、某人自1990年1月1日开始打鱼,“三天打鱼,两天晒网”,输入一个1990年之后的日期,输出他这一天是打鱼还是晒网。\n");
printf(" 5、退出\n");
scanf("%d",&option);
switch(option) //switch分支结构
{
case 1:
while(1) //while循环,后面的1是常数,预示一直到break才结束循环
{
printf("请输入一个年份:");
scanf("%d",&year);
allyear(year);
printf("你想继续查询日历么?(y预示继续,n预示结束)");
scanf("%c",&ny);
if(ny=='n')
break;
}
break;
case 2:
while (1)
{
printf("输入年月:");
scanf("%d,%d",&year,&month);
month_print(year,month);
printf("你想继续查询日历么?(y预示继续,n预示结束):");
scanf("%c",&ny);
if(ny=='n')
break;
}
break;
case 3:
while (1)
{
printf("输入年月日:");
scanf("%d,%d,%d",&year,&month,&day);
printf("请输入今天的日期:");
scanf("%d,%d,%d",&x,&y,&z);
jisuan_day(year,month,day,x,y,z);
printf("你想继续查询么?(y预示继续,n预示结束):");
scanf("%c",&ny);
if(ny=='n')
break;
}
break;
case 4:
while (1)
{
printf("输入1990年1月1日以后的一个日期:");
scanf("%d,%d,%d",&year,&month,&day);
fish_or_net(year,month,day);
printf("你想继续查询渔人是打鱼还是晒网么?(y预示继续,n预示结束):");
scanf("%c",&ny);
if(ny=='n')
break;
}
break;
case 5:
while (1)
{
printf("确认么?y预示是的,n预示不是");
scanf("%c",&ny);
if(ny=='y')
exit(1); //预示退出流程
else if(ny=='n')
break;
}
break;
default:printf("对不起,暂时没有这个服务");
break;
}
}
return 0;
}
怎样自制日历
自制日历步骤如下:
1。准备A4大小的白纸或色卡纸。卡纸比普通白纸厚,用卡纸制成的日历比较耐用。
2。用尺子画出7纵行、5横行的表格。分别在12张卡纸上画表,每一张纸代表一个月份。
3。写下月份。在每一张卡纸的顶部写上月份——一月、二月、三月、四月、五月、六月、七月、八月、九月、十月、十一月及十二月。月份要写得大一点。
4。标注星期几。在表格的第1行分别写上星期一至星期五。
5。填写日期。日期要写在每个单元格的右上角。
6。装饰日历。每一页日历皆可以依照你本人的心意来装饰。水笔、色铅笔、记号笔、蜡笔齐上阵;贴纸、亮片、闪光胶也不赖;最要紧的是,要发挥你的想象力!!!
7。标出重要的日子。在日历上标出所有重要的日子,如生日、圣诞节、开学日等等。有个比较有创意的办法就是找一张与这一天有关的图片,紧接着贴在对应的日期上。
8。把日历挂起来。把日历挂在挂钩或钉子上,不论你想挂在卧室里、厨房里还是教室里皆可以。
日历怎么做手工简单
制作日历需要用户使用Excel表格进行制作,详细操作步骤如下:
工具:机械剪掉鞭子S3 Pro、Windows10。Excel202一、
1。打开Excel表格,把所有的表格全部选中,设置列宽为2,如下图所示。
2。把B1到D1的3个单元格选中合并为1个,紧接着向右拖动鼠标将其它的6组单元格合并。输入星期的英文字母,将周末填充为红色,周一到周五填充为紫色,字体为白色。如下图所示。
3。在A列单元格每隔2个单元格,选中2个,一共选中了10个单元格,将它合并为5组。把合并好的单元格填充为紫色,字体为白色。如下图所示。
4。输入数字记录周数,从1月份起就输入1-5的数字。如下图所示。
5。在日期数字的右边输入阴历的日期,如下图所示。
6。选中C、F、I、L、O、R、U列的数字,设置为20号,如下图所示。
7。最后,即可做出日历。如下图所示。
拓展:
日历,一种日常使用的出版物,记录载入着日期等有关信息。
每一页显示一日信息的叫日历,每一页显示一个月信息的叫月历,每页显示全年信息的叫年历。有多种形式,如挂历、座台历、年历卡等,如今又有电子日历。
中国始有历法大概在4000多年以前。依据甲骨文中的一页甲骨历,证明殷代的历法已具有相当的水平,这一页甲骨历是全天下最古老的历书实物,这页甲骨历也就叫日历。


