c语言将元年1月1日起的天数转化成日期,不用循环和数组
上篇文章中提到了将日期转化成天数的方法:c语言计算两个日期相差天数,不用循环语句。这篇文章介绍反过来将天数转化成日期的方法,于是可以直接用天数代替日期,只在显示时转化成日期形式。
记天数为days,日期为year年month月day日
求年份
400年一个周期,共146097天;除以146097的余数是100年一个周期,共36524天;余数再除以36524的余数是4年一个周期,共1461天;再除以1461的余数则是每365天一年。于是:
year=1;
year+=days/146097*400;
days%=146097;
year+=days/36524*100;
days%=36524;
year+=days/1461*4;
days%=1461;
year+=days/365;
days%=365;
这个是有误差的,由于闰年是加到2月后面,而不是一年的最后,所以在闰年交替时会出错,比如当days=1460时,求出的year=5。解决方法是将3月1日作为一年的起点。3月1日与次年1月1日相差天数为306天,将计日起点移到0年3月1日,则天数加306天,算完年份后,若天数的余数小于306,则年份因为加了306天而多算了1年,于是再减1。代码如下:
days += 306;
year = 1;
year += days / 146097 * 400;
days %= 146097;
year += days / 36524 * 100;
days %= 36524;
year += days / 1461 * 4;
days %= 1461;
year += days / 365;
days %= 365;
if(days<306){year--;
}
求月和日
用天数的余数计算月份,相当于3月1日的days天后是几月。先算(days+1)天相当于几个月,算出来的结果加2,对12取余,再加1,就是月份。每月天数可以用一个数组表示:
天数 |
31 |
30 |
31 |
30 |
31 |
31 |
30 |
31 |
30 |
31 |
31 |
月份 |
3月 |
4月 |
5月 |
6月 |
7月 |
8月 |
9月 |
10月 |
11月 |
12月 |
1月 |
mon[]={31,30,31,30,31,31,30,31,30,31,31}
根据天数求月份的公式其实是根据月份和日求天数的公式猜出来的。虽然试过用数学方法证明,但是没有成功。
mon数组的前n项和,凑出来的公式为(和上一篇文章里的公式一致):
sum=(n*367+7)/12;
凑出来的天数求月份的公式为:
month=((days+1)*12-8)/367+1;
剩余天数加1就是day日:
day=days-((month-1)*367+7)/12;
刚才的月份是3月起的月份,需要加1模12再加1才是月份。
全部代码:
days += 306;
year = 1;
year += days / 146097 * 400;
days %= 146097;
year += days / 36524 * 100;
days %= 36524;
year += days / 1461 * 4;
days %= 1461;
year += days / 365;
days %= 365;
days -= 306;
if (days < 0) {year--;
}
days++;
month = (days * 12 - 8) / 367;
daysay = days - (month * 367 + 7) / 12;
month = (month + 2) % 12 + 1;
尝试用c++写一个日期类,并调用:
#include<stdio.h>//将计日起点定为1970年1月1日
#define ORIGIN_YEAR 1600
#define OFFSET_DAYS 135141class Date {public:int days;void setdate(int year, int month, int day);void getdate(int&year, int&month, int&day);Date operator + (int days);int operator - (Date date);
};unsigned int getdate(Date date);//date早于ORIGIN_YEAR+1年会出错 int main() {//输入年份,打印当年日历,会溢出1~2天 Date t;unsigned int date;scanf("%u", &date);t.setdate(date, 1, 1);for (int i = 0; i < 367; i++) {date = getdate(t+i);printf("%d年%d月%d日\n", (date >> 16)&0xffff, (date >> 8) & 0xff, date & 0xff);}return 0;
}void Date::setdate(int year, int month, int day) {year-=ORIGIN_YEAR;days =month <= 2 ? ((year - 1) * 365 + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400+ (month - 1) * 30 + month * 7 / 12+ day - 1) : ((year) * 365 + (year) / 4 - (year) / 100 + (year) / 400- (13 - month) * 30 - (14 - month) * 7 / 12+ day - 1);days-=OFFSET_DAYS;
}unsigned int getdate(Date date) {int year, month, day;date.getdate(year,month,day);return (year << 16) | (month << 8) | day;
}void Date::getdate(int&year, int&month, int&day) {int d = days + 306+OFFSET_DAYS;year = 1;year += d / 146097 * 400;d %= 146097;year += d / 36524 * 100;d %= 36524;year += d / 1461 * 4;d %= 1461;year += d / 365;d %= 365;if (d < 306) {year--;}year+=ORIGIN_YEAR;d++;month = (d * 12 - 8) / 367 + 1;day = d - ((month - 1) * 367 + 7) / 12;month=(month+1)%12+1;
}Date Date::operator + (int d) {Date r;r.days = days + d;return r;
}int Date::operator - (Date date) {return days - date.days;
}
c语言将元年1月1日起的天数转化成日期,不用循环和数组相关推荐
- java把距离1970年 1月1日 的秒数 转换成对应的日期
java 中把 已知的距离1970年 1月1日 的秒数 转化 为相应的日期 的实现方式 第一种方式: 采用 Date 类的 setTime( Long time ) 方法 public class T ...
- c语言求某年某月1日是星期几,蔡勒(Zeller)公式:根据日期推算是星期几
Zeller's Congruence: w=y + [y/4] + [c/4] - 2c + [26(m+1)/10] + d - 1 公式中的符号含义如下: w:星期: w对7取模得:0-星期日, ...
- 2013年10月20日江苏省高校计算机等级考试二级c语言,2012年10月14日江苏省高校计算机等级考试二级C语言上机题(C02)及其解答_张柏雄.doc...
2012年10月14日江苏省高校计算机等级考试二级C语言上机题(C02)及其解答_张柏雄 [上机题命题评述]2012年10月14日C01套编程试题是求三位数的水仙花数及其反序数分别存入数组a和b.为本 ...
- 水仙花亲密数c语言,★2015年3月15日江苏省高校计算机等级考试二级C语言1套上机题(C01)及其解答_张柏雄.doc...
★2015年3月15日江苏省高校计算机等级考试二级C语言1套上机题(C01)及其解答_张柏雄 目录 C01(上午8:00-9:10)原题 解答 附录:通用的自编函数 2015春江苏省高校计算机二级C语 ...
- C语言——输入年、月、日,输出该日期是当年的第几天,其中区分了闰年和平年
主要考察了循环和数组的利用,笔者的代码比较冗余,但是简单易懂,方便初学者阅读与理解. 代码如下:用switch嵌套,更易于理解,当然也有改进的缩减代码在后文 #include<stdio.h&g ...
- C语言 输入年、月、日判断天数
题目:任意给出一个年月日,判断是这一年的第几天 如:2012 5 10 是这一年的第131天. 闰年算法:能被4整除且不能被100整除,或者能被400整除. #include<stdio.h&g ...
- c语言每轮for循环初始化i,十三.Linux博客-2016年8月18日while、for特殊用法、selet循环与菜单、函数...
格式说明: 操作 概念 命令 说明及举例 十三.while.for特殊用法.selet循环与菜单.函数 while特殊用法 while循环的特殊用法(遍历文件的每一行): while read lin ...
- matlab儒略日转日期,将日期(年、月、日)转换为儒略日编号并返回日期
我尝试实现两个功能:1)将日期转换为儒略日数;2)将儒略日数转换回日期(年.月和日).我的代码返回的结果是关闭了一天.我不熟悉算法的工作原理,但是如果我使用 Math.Ceiling 朱利安数的工作, ...
- java 距离1970年1月1日的秒数 转换成对应现在的日期
Long ulTimeSecond = 1660789024L; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm: ...
最新文章
- Linux学习第三章
- FPGA 控制 FLASH 之 Startup 原语使用相关链接
- Python主要智能优化算法库汇总
- emq插件开发mysql_EMQ的Mysql插件
- 数据揭秘中国女性的薪水普遍比男性低,说好的“同工同酬”呢?
- js设置控件的隐藏与显示的两种方法
- Simple2D-15(音乐播放器)使用 glfw 库
- c 语言程序上机考试系统,计算机二级C语言上机考试操作步骤及流程
- “串标围标”,是如何被识破的?
- 怎么批量修改文件夹名称?
- arccatalog点要素显示不完_利用ArcCatalog 管理地理空间数据库
- python人口普查数据显示_如何使用FCC的API在Python中查找人口普查数据块并遍历dict列表?...
- 信号与系统(关于流程框图的一个简单问题记录)
- MySQL学习笔记(七)视图,触发器,事务,存储过程,函数,流程控制,索引
- Caffe_stu03_小训练
- MATLAB-APP编程
- 递归删除符合条件的目录,文件, kotlin,java
- 如何将excel表格导入matlab,将Excel数据导入MATLAB中的方法
- Kubernetes开发(4)-webhook 实现拦截请求
- 【前端趋势】Vue、Vite作者尤雨溪前端趋势2022主题演讲