计算日期,天数,星期几的小例子

从指针到日期计算:个人编程成长之旅
本文分享了一位程序员通过阅读书籍《The C Programming Language》深入理解指针概念后,重新解决大学时期计算机编程大赛中未解决的日期天数问题的过程。文章详细介绍了日期计算的C语言实现,包括闰年判断、月份天数查找和日期转换等功能,并通过代码示例展示了如何通过输入年月日来获取该日期对应的星期几。同时,文章特别指出1752年9月3日是公历调整的关键点,解释了这一日期前后公历发生了11天的跳跃,以及这一历史背景对编程实现的影响。

       最近在看《The C Programing Language》,进一步加深了自己对于指针赋值的理解,现在看来关于日期,天数这类的题目很是简单,但是遥想当年大一的时候自己去参加计算机学院的编程大赛,五个问题只是求解出来一个,而没解答出的问题中就包含关于日期天数的一个问题,今天为了弥补一下以前的遗憾,就把这个程序再写一写吧。(话说程序还就需要多写多练,本来以为自己看书的时候想枚举,多维数组,局部变量初始化等问题都是很简单的,但是自己写起来还是很费劲,说明自己写的代码还是少,需要加强训练啊。)

#include <stdio.h>
#include <stdlib.h>
  
int monthday[2][12]=
  {
  	{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 *Month[] = 
   {
  	"January",
  	"February",
  	"March",
  	"April",
  	"May",
  	"June",
  	"July",
  	"August",
  	"September",
  	"October",
  	"November",
  	"December"
  };
  
int year_days(int year,int month,int day)
  {
  	int leap,yeardays,i;
  	yeardays = 0;
  	leap = ((year%4==0 && year%100!=0) || (year%400==0));
  	for(i=0;i<month-1;i++)
  	  yeardays += monthday[leap][i];
  	yeardays = yeardays+day;
  	return yeardays;
  }
  
  void month_day(int year,int yeardays,int* pmonth,int* pday)
  {
  	int leap,i;
  	leap = ((year%4==0 && year%100!=0) || (year%400==0));
  	for(i=0;yeardays>monthday[leap][i];i++)
  	  yeardays -= monthday[leap][i];
  	*pmonth = i;
  	*pday = yeardays;
  }
  
int main()
  {
  	int year = 1997;
  	int month = 3;
  	int day = 1;
  	int *pmonth;
  	int *pday;
  	int yeardays = year_days(year,month,day);
  	pmonth = (int*)malloc(sizeof(int));
  	pday = (int*)malloc(sizeof(int));
  	month_day(year,yeardays,pmonth,pday);
  	printf("The yeardays is %d\n",yeardays);
  	printf("The Month is %s, The Date is %d \n",Month[*pmonth],*pday);
  	return 0;
  }
  

对于程序的完美运行需要进行用户输入的合法性判断,下面是另外一个版本:

#include <stdio.h>
  
 static char daytab[2][13] =  {
         {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
         {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
 };
  
 /* day_of_year: set day of year from month & day */
 int day_of_year(int year, int month, int day)
 {
         int i, leap;
         
         if (year < 1752 || month < 1 || month > 12 || day < 1)
                return -1;
  
         leap = (year%4 == 0 && year%100 != 0) || year%400 == 0;
         if (day > daytab[leap][month])
                return -1;
  
         for (i = 1; i < month; i++)
                day += daytab[leap][i];
         return day;
 }
  
 /* month_day: set month, day from day of year */
 int month_day(int year, int yearday, int *pmonth, int *pday)
 {
         int i, leap;
         
         if (year < 1752 || yearday < 1)
                return -1;
  
         leap = (year%4 == 0 && year%100 != 0) || year%400 == 0;
         if ((leap && yearday > 366) || (!leap && yearday > 365))
                return -1;
  
         for (i = 1; yearday > daytab[leap][i]; i++)
                yearday -= daytab[leap][i];
         *pmonth = i;
         *pday = yearday;
         
         return 0;
 }
  
  
 /* main: test day_of_year and month_day */
 int main(void)
 {
         int year, month, day, yearday;
         
         for (year = 1970; year <= 2000; ++year) {
                for (yearday = 1; yearday < 366; ++yearday) {
                        if (month_day(year, yearday, &month, &day) == -1) {
                                printf("month_day failed: %d %d\n",
                                       year, yearday);
                        } else if (day_of_year(year, month, day) == yearday) {
                                printf("bad result: %d %d\n", year, yearday);
                                printf("month = %d, day = %d\n", month, day);
                        }
                }
         }
         
         return 0;
 }
 

下面是根据年月日求解当天星期几的代码

#include <stdio.h>
char *name[] = {"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday" }; 
int main() 
{  
	int d, m, y, a;  
	printf("Day: "); 
	scanf("%d",&d);  
	printf("Month: "); 
	scanf("%d",&m);  
	printf("Year: ");  
	scanf("%d",&y);  
	// 1213,14  
	if (m == 1 || m == 2) 
	{ 
		m += 12; 
		y--; 
	}  
	// 175293     
	if ((y < 1752) || (y == 1752 && m < 9) ||   (y == 1752 && m == 9 && d < 3))   
		a = (d + 2*m + 3*(m+1)/5 + y + y/4 +5) % 7;  
	else   
		a = (d + 2*m + 3*(m+1)/5 + y + y/4 - y/100 + y/400)%7;  
	printf("it's a %s\n", name[a]);  
	return 0; 
} 

根据代码可以发现1752年9月3日是一个转折点。说明那天发生了什么大事,

现行的公历是格利戈里历法,这个历法的是1582年教皇格利戈里根据恺撒大帝引进的算法改进的。它采用的是闰年制也就是现行的制度,不过有一个需要注意的地方就是,这个历法并不是连续的,中间缺少了11天。1752年9月2日之后的那一天并不是1752年9月3日,而是1752年9月14日。也就是说,从1752年9月3日到1752年9月13日的11天并不存在。抹掉这11天是由英国议会做出的决定。所以要计算某年每个月的天数的,除了要考虑是否是闰年以外,还要考虑1752年的9月。

 




 




<think>首先,用户的问题是:“我想在MySQL数据库中将日期值转换为对应的星期 请问MySQL convert date to weekday”。这涉及到MySQL中日期处理函数。 关键点:将日期转换为星期。在MySQL中,有函数可以直接获取星期的信息。 回顾引用内容: - 引用[1]:提到了DAYOFWEEK函数,示例:SELECT DAYOFWEEK('2007-02-03')。这个函数返回星期的索引(1=Sunday, 2=Monday, ..., 7=Saturday)。 - 引用[2]:提到了DATE函数,但主要是提取日期部分,不直接相关。 - 引用[3]:提到了TO_DAYS函数,但这是将日期转换为天数,不直接用于星期。 - 引用[4]:提到了ROW_NUMBER()和日期偏移,但具体例子是关于训练安排的,不直接相关。 所以,最相关的函数是DAYOFWEEK,因为它直接返回星期的数字表示。 还有其他函数吗?是的,MySQL有WEEKDAY函数。WEEKDAY函数返回星期的索引(0=Monday, 1=Tuesday, ..., 6=Sunday)。这与DAYOFWEEK不同。 用户要求“转换为对应的星期”,可能指的是数字索引或字符串表示。MySQL也提供DAYNAME函数,它返回星期的英文名称(如Monday, Tuesday等)。 所以,选项包括: 1. DAYOFWEEK(date):返回1(Sunday)到7(Saturday)。 2. WEEKDAY(date):返回0(Monday)到6(Sunday)。 3. DAYNAME(date):返回英文名称。 用户可能需要中文或特定格式,但函数是英文的。用户可以用CASE语句或ELT函数转换为中文。 在回答中,我应该: - 解释这些函数。 - 提供示例SQL查询。 - 确保格式正确:行内数学表达式用$...$,但这里是SQL代码,所以用代码块。 - 生成相关问题。 - 使用中文回答。 - 添加引用标识,如[^1]。 结构化回答: 1. 介绍问题:将日期转换为星期。 2. 解释DAYOFWEEK函数:返回数字索引(1-7),Sunday为1。 3. 解释WEEKDAY函数:返回数字索引(0-6),Monday为0。 4. 解释DAYNAME函数:返回英文名称。 5. 提供示例SQL查询。 6. 如果需要中文星期,建议使用CASE语句或ELT函数。 7. 生成相关问题。 从引用[1],有DAYOFWEEK的例子,所以可以引用它。 用户查询是“convert date to weekday”,所以WEEKDAY函数更直接,因为它有“weekday”在名字中。 在MySQL文档中: - DAYOFWEEK():返回工作日的索引,其中1=Sunday,2=Monday,...,7=Saturday。 - WEEKDAY():返回工作日的索引,其中0=Monday,1=Tuesday,...,6=Sunday。 - DAYNAME():返回工作日的名称。 为了清晰,我应该介绍所有选项。 示例SQL: 使用DAYOFWEEK: SELECT DAYOFWEEK('2023-10-01'); -- 返回1,因为2023-10-01是Sunday 使用WEEKDAY: SELECT WEEKDAY('2023-10-01'); -- 返回6,因为2023-10-01是Sunday,WEEKDAY以Monday为0 使用DAYNAME: SELECT DAYNAME('2023-10-01'); -- 返回'Sunday' 如果用户想要中文名称,需要自定义。例如: SELECT CASE DAYOFWEEK(date_column) WHEN 1 THEN '星期日' WHEN 2 THEN '星期一' WHEN 3 THEN '星期二' WHEN 4 THEN '星期三' WHEN 5 THEN '星期四' WHEN 6 THEN '星期五' WHEN 7 THEN '星期六' END AS weekday_chinese FROM table_name; 或者用ELT函数简化。 ELT(N,str1,str2,...):返回第N个字符串。 所以:SELECT ELT(DAYOFWEEK(date_column), '星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六') AS weekday_chinese; 但注意DAYOFWEEK返回1-7,所以ELT(1,...)是第一个元素'星期日',正确。 如果使用WEEKDAY,它返回0-6,需要调整:SELECT ELT(WEEKDAY(date_column)+1, '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'); 因为WEEKDAY=0是Monday,所以+1后为1对应'星期一'。 在回答中,提供这些选项。 生成相关问题: 基于这个主题: 1. MySQL中其他日期函数是什么? 2. 如何计算日期之间的工作日(排除周末)? 3. 如何在MySQL中处理时区转换? 4. 如何优化日期查询的性能? 确保回答清晰、可靠。 添加引用:引用[1]提到了DAYOFWEEK,所以末尾添加[^1]。 最终回答结构: - 开头:解释可以用DAYOFWEEK或WEEKDAY函数。 - 详细描述每个函数。 - 提供SQL例子。 - 建议如何获取中文名称。 - 生成相关问题。</think>### MySQL中将日期值转换为星期的方法 在MySQL中,将日期值转换为对应的星期(weekday)是一个常见的需求。MySQL提供了个内置函数来实现这一功能,包括`DAYOFWEEK()`、`WEEKDAY()`和`DAYNAME()`。这些函数可以返回数字索引或英文名称,您可以根据需要选择使用。下面我将逐步解释这些函数的用法,并提供示例SQL查询,帮助您轻松实现转换。 #### 1. **使用DAYOFWEEK()函数** - `DAYOFWEEK(date)` 返回一个数字索引,表示日期对应的星期。 - 返回值范围:1(Sunday)到7(Saturday)。 - 例如,Sunday=1, Monday=2, ..., Saturday=7。 - 这个函数在引用[^1]中被提及,适用于需要以Sunday为起点的场景。 - 示例SQL: ```sql SELECT DAYOFWEEK('2023-10-01') AS weekday_index; -- 返回1(因为2023-10-01是Sunday) SELECT DAYOFWEEK('2023-10-02') AS weekday_index; -- 返回2(Monday) ``` #### 2. **使用WEEKDAY()函数** - `WEEKDAY(date)` 也返回一个数字索引,但以Monday为起点。 - 返回值范围:0(Monday)到6(Sunday)。 - 例如,Monday=0, Tuesday=1, ..., Sunday=6。 - 如果您需要以Monday作为一周的开始(符合ISO标准),这个函数更合适。 - 示例SQL: ```sql SELECT WEEKDAY('2023-10-01') AS weekday_index; -- 返回6(因为2023-10-01是Sunday) SELECT WEEKDAY('2023-10-02') AS weekday_index; -- 返回0(Monday) ``` #### 3. **使用DAYNAME()函数** - `DAYNAME(date)` 直接返回星期的英文名称(如Monday, Tuesday等)。 - 返回值是字符串形式,便于直接阅读。 - 示例SQL: ```sql SELECT DAYNAME('2023-10-01') AS weekday_name; -- 返回'Sunday' SELECT DAYNAME('2023-10-02') AS weekday_name; -- 返回'Monday' ``` #### 4. **获取中文星期名称** - MySQL默认不提供中文输出,但您可以通过`CASE`语句或`ELT()`函数将数字索引转换为中文名称。 - **方法一:使用CASE语句(推荐,可读性好)** - 基于`DAYOFWEEK()`的结果(1-7): ```sql SELECT CASE DAYOFWEEK(date_column) WHEN 1 THEN '星期日' WHEN 2 THEN '星期一' WHEN 3 THEN '星期二' WHEN 4 THEN '星期三' WHEN 5 THEN '星期四' WHEN 6 THEN '星期五' WHEN 7 THEN '星期六' END AS weekday_chinese FROM your_table; ``` - 基于`WEEKDAY()`的结果(0-6): ```sql SELECT CASE WEEKDAY(date_column) WHEN 0 THEN '星期一' WHEN 1 THEN '星期二' WHEN 2 THEN '星期三' WHEN 3 THEN '星期四' WHEN 4 THEN '星期五' WHEN 5 THEN '星期六' WHEN 6 THEN '星期日' END AS weekday_chinese FROM your_table; ``` - **方法二:使用ELT()函数(简洁)** - `ELT(index, string1, string2, ...)` 根据索引返回对应字符串。 - 基于`DAYOFWEEK()`(索引1-7): ```sql SELECT ELT(DAYOFWEEK(date_column), '星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六') AS weekday_chinese FROM your_table; ``` - 基于`WEEKDAY()`(索引0-6,需+1调整): ```sql SELECT ELT(WEEKDAY(date_column) + 1, '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日') AS weekday_chinese FROM your_table; ``` #### 5. **实际应用示例** - 假设您有一个表`sales`,其中包含`order_date`列。以下查询将日期转换为中文星期: ```sql -- 使用DAYOFWEEK()和CASE语句 SELECT order_date, CASE DAYOFWEEK(order_date) WHEN 1 THEN '星期日' WHEN 2 THEN '星期一' -- ... 省略其他WHEN子句 END AS weekday_chinese FROM sales; ``` - 输出类似: | order_date | weekday_chinese | |------------|-----------------| | 2023-10-01 | 星期日 | | 2023-10-02 | 星期一 | #### 注意事项 - **函数选择**:如果您的应用场景需要以Sunday为起点,使用`DAYOFWEEK()`(如引用[^1]所示);如果以Monday为起点(如工作日计算),使用`WEEKDAY()`。 - **性能**:这些函数在索引日期列上效率较高,但如果表数据量大,建议在应用层处理转换以减轻数据库负载。 - **日期格式**:确保输入日期为有效格式(如'YYYY-MM-DD'),否则函数可能返回`NULL`。您可以使用`STR_TO_DATE()`函数处理非标准格式。 - **引用说明**:`DAYOFWEEK()`函数在MySQL文档中被明确支持,如引用[^1]中的示例所示[^1]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值