Zeller公式推导及C#代码示例(待完善)
Zeller公式用于计算给定日期是星期几。
该方法可以用数论知识进行证明。
假设给定日期Date为Year-Month-Day,求解该日期是星期几的问题实际上就是以之前某个确定星期几的日期作为参考点,计算它们之间的总天数,然后再除以7取余数,即可算出指定日期是星期几。
这里,我们将选择公元0年12月31日作为参考点。原则原因是:1、公元1年1月1日是周1;2、选择一年的末尾,便于以整年计算日期,防止过多分段计算带来的麻烦。
由上可得,参考日期到给定日期的将分成两部分:PastYearsDays(过去的整数年天数)和PresentYearDays(指定年已流逝的天数);
则可以得到,WholeDays = PastYearsDays + PresentYearDays。
参考日期到指定日期经过的闰年数为:LeapYearsNum = [(Year - 1) / 4] - [(Year - 1) / 100] + [(Year - 1) / 400]。
由上可得到,PastYearsDays = (Year - 1) * 365 + LeapYearsNum。
又因为(Year - 1) * 365 = (Year - 1) * ( 7 * 52 + 1) ≡ Year - 1 (mod 7),故可得到,PastYearsDays ≡Year - 1 + LeapYearsNum。
因此,可得到WholeDays = PastYearsDays + PresentYearDays ≡ Year - 1 + LeapYearsNum + PresentYearDays (mod 7)。
接来下,我们开始计算PresentYearDays:
下表分别展示了每个月的天数:
Month | Jan. | Feb. | Mar. | Fri. | May. | Jun. | Jul. | Aug. | Sep | Oct. | Nov. | Dec. |
Days | 31 | 28(29) | 31 | 30 | 31 | 30 | 31 | 31 | 30 | 31 | 30 | 31 |
又因为离28、29、30、31最近的7的倍数是28 = 4 * 7。故,当每个月的天数都减去28后可得如下表格:
Month | Jan. | Feb. | Mar. | Fri. | May. | Jun. | Jul. | Aug. | Sep | Oct. | Nov. | Dec. |
LeftDays | 3 | 0(1) | 3 | 2 | 3 | 2 | 3 | 3 | 2 | 3 | 2 | 3 |
CommonYearAcc | 3 | 3 | 6 | 8 | 11 | 13 | 16 | 19 | 21 | 24 | 26 | 29 |
LeapYearAcc | 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。根据循环数列的规律(该理论将在另一博文中描述),可得到如下表述:
当Month = 1时,PresentYearDays = Day;
当Month = 2时,PresentYearDays = 31 + Day;
当Month ≥ 3时,[13 * (Month + 1) / 5] - 7 + (Month - 1) * 28 + Day + i,其中,当闰年时i = 1,当平年时i = 0.
将1月和2月当做上一年的“13月”和“14月”,最终上边三个公式将合并为以下公式:
PresentYearDays = [13 * (Month + 1) / 5] - 7 + (Month - 1) * 28 + Day (3 ≤ Month ≤ 14)
最终,WholeDays将变成:
WholeDays ≡ (Year - 1) + [(Year - 1) / 4] - [(Year - 1) / 100] + [(Year - 1) / 400] + [13 * (Month +1) / 5 ] - 7 + (Month-1) * 28 + Day (mod 7)
≡ (Year - 1) + [(Year - 1) / 4] - [(Year - 1) / 100] + [(Year - 1) / 400] + [13 * (Month +1) / 5 ] + Day (mod 7)
注意:当将1月和2月当做13月和14月计算的时候,年份也得减一。
又因为每隔四个世纪,星期就重复一次。
故我们可容易得到每个世纪的第一个月(3月1日)的计算公式:
PastYearsDays‘ ≡ (4 - (Century - 1) mod 4) * 2 - 4 (mod 7)
其中Century为给定时期所在的世纪。
最终得到计算每隔世纪第一年的星期几的公式:
WholeDays’ ≡ (4 - (Century - 1) mod 4) * 2 - 1 + [13 * (Month + 1) / 5] + Day
接下来,我们就要求在一个世纪内的任意天的星期。显然在一个世纪内,只需考虑能被4整除的年份即是闰年LeapYear,根据此规则,最终我们得到计算任意一天星期几的公式:
WholeDays ≡ (4 - (Century - 1) mod 4) * 2 - 1 + (Year - 1) + [Year / 4] + [13 * (Month + 1) / 5] + Day
假设C = Century - 1,根据数论知识,我们又可以得到如下公式:
4q + r = C,其中q为商,r为余数。
⇒ r = C - 4 * [C / 4]
⇒ (4 - C mod 4) * 2 = (4 - C + 4 * [C / 4]) * 2
= 8 - 2C + 8 * [C / 4]
≡ [C / 4] - 2C + 1 (mod 7)
最终,由上式,我们可以得到
WholeDay ≡ [C/4] - 2C + Year + [Year / 4] + [13 * (Month + 1) / 5] + Day - 1 (mod 7)
代码示例:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace TestOne
- {
- /// <summary>
- /// Used to record Date.
- /// </summary>
- class LocalDate
- {
- public int m_nYear;
- public int m_nMonth;
- public int m_nDay;
- public LocalDate(int year, int month, int day)
- {
- m_nYear = year;
- m_nMonth = month;
- m_nDay = day;
- }
- public LocalDate()
- {
- m_nYear = ;
- m_nMonth = ;
- m_nDay = ;
- }
- /// <summary>
- /// Used to calculate what day it is.
- /// </summary>
- /// <param name="localDate"></param>
- /// <returns></returns>
- public static int CalWhatDay(ref LocalDate localDate)
- {
- int year = localDate.m_nYear;
- int month = localDate.m_nMonth;
- int day = localDate.m_nDay;
- if (month < )
- {
- year -= ;
- month += ;
- }
- int c = year / , y = year - * c;
- int w = (c / ) - * c + y + (y / ) + ( * (month + ) / ) + day - ;
- w = (w % + ) % ;
- return w;
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- LocalDate localDate = new LocalDate(, , );
- int whatDay = LocalDate.CalWhatDay(ref localDate);
- Console.WriteLine("Date: {0}-{1}-{2} is {3}", localDate.m_nYear, localDate.m_nMonth, localDate.m_nDay, PrintWahtDay(whatDay));
- Console.ReadKey();
- }
- private static string PrintWahtDay(int whatDay)
- {
- switch(whatDay)
- {
- case : return "Sunday";
- case : return "Monday";
- case : return "Tuesday";
- case : return "Wednesday";
- case : return "Thursday";
- case : return "Friday";
- case : return "Saturday";
- default: return "Invalid number";
- }
- }
- }
- }
Code Here
Zeller公式推导及C#代码示例(待完善)的更多相关文章
- Mysql基础代码(不断完善中)
Mysql基础代码,不断完善中~ /* 启动MySQL */ net start mysql /* 连接与断开服务器 */ mysql -h 地址 -P 端口 -u 用户名 -p 密码 /* 跳过权限 ...
- 推荐Java五大微服务器及其代码示例教程
来源素文宅博客:http://blog.yoodb.com/yoodb/article/detail/1339 微服务越来越多地用于开发领域,因为开发人员致力于创建更大,更复杂的应用程序,这些应用程序 ...
- 高级渲染技巧和代码示例 GPU Pro 7
下载代码示例 移动设备正呈现着像素越来越高,屏幕尺寸越来越小的发展趋势. 由于像素着色的能耗非常大,因此 DPI 的增加以及移动设备固有的功耗受限环境为降低像素着色成本带来了巨大的压力. MSAA 有 ...
- Java8-Function使用及Groovy闭包的代码示例
导航 定位 概述 代码示例 Java-Function Groovy闭包 定位 本文适用于想要了解Java8 Function接口编程及闭包表达式的筒鞋. 概述 在实际开发中,常常遇到使用模板模式的场 ...
- [IOS 开发] 懒加载 (延迟加载) 的基本方式,好处,代码示例
懒加载的好处: 1> 不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强 2> 每个属性的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合 ...
- SELECT控件操作的JS代码示例
SELECT控件操作的JS代码示例 1 检测是否有选中 if(objSelect.selectedIndex > -1) { //说明选中 } else { //说明没有选中 } 2.动态创建s ...
- 转:HIBERNATE一些_方法_@注解_代码示例---写的非常好
HIBERNATE一些_方法_@注解_代码示例操作数据库7步骤 : 1 创建一个SessionFactory对象 2 创建Session对象 3 开启事务Transaction : hibernate ...
- Python实现各种排序算法的代码示例总结
Python实现各种排序算法的代码示例总结 作者:Donald Knuth 字体:[增加 减小] 类型:转载 时间:2015-12-11我要评论 这篇文章主要介绍了Python实现各种排序算法的代码示 ...
- C#与数据库访问技术总结(十五)之 DataAdapter对象代码示例
DataAdapter对象代码示例 下面的代码将说明如何利用DataAdapter对象填充DataSet对象. private static string strConnect=" data ...
随机推荐
- android 之 Crash信息的持久化处理
需求: 持久化运行时异常的信息 1.CrashHandler.java import android.content.Context; import android.content.pm.Packag ...
- Linux驱动学习笔记(6)信号量(semaphore)与互斥量(mutex)【转】
转自:http://blog.chinaunix.net/uid-24943863-id-3193530.html 并发导致竟态,从而导致对共享数据的非控制访问,产生非预期结果,我们要避免竟态的发生. ...
- Nagios监控Oralce
一.本文说明: 本文是监控本地的Oracle,其实监控远端的Oracle也是跟下面的步骤差不多的. 二.安装Nagios.Nagios插件.NRPE软件: 安装步骤可以参考<Linux下Nagi ...
- Mysql备份与还原实例
一.备份数据库 ----清空一下日志 mysql> reset master; Query OK, rows affected (0.02 sec) ----查看一下echo表的存储引擎 mys ...
- 《Linux/Unix系统编程手册》
TCP的TIME_WAIT状态,超时时间为2倍MSL(IP报文超过TTL前最大生存时间,BSD规范为30s,RFC1122建议为2分钟).
- C++的几种强制类型转换
有时我们希望显式地将对象强制类型转换成另外一种类型.例如,如果想在下面的代码中执行浮点数除法: int i, j; double slope = i / j; 就要使用某种方法将i和/或j显式地转换成 ...
- Python学习笔记-Day3-set集合操作
set集合,是一个无序且不重复的元素集合.定义方式类似字典使用{}创建 目前我们学过的数据类型: 1.字符串(str),2.整型(int),3.浮点型(float),4,列表(list) 5.元组(t ...
- [美]莫提默 J. 艾德勒《如何阅读一本书》
我最近在阅读一本书,这本书的书名叫<如何阅读一本书>(商务出版社,2015),顾名思义. 作者认为,阅读是一件跟写书一样复杂的活动,而许多人并不会阅读. 看过后,你可能会有“我真没 ...
- spark记录
Filtering multiple values in multiple columns: In the case where you're pulling data from a database ...
- css基本知识
WANGJUN59451 css基本知识 1.CSS 简介 CSS 指层叠样式表 (Cascading Style Sheets),是一种用来表现 HTML 文档样式的语言,样式定义如何显示 HT ...