C程序查找给定日期的星期几
有没有办法在一行C代码中查找给定日期的星期几?
例如
考虑到19-05-2011(dd-mm-yyyy)给我星期四
单线程不太可能,但strptime函数可用于解析您的日期格式,并且可以在自动修改这些字段的系统上查询其tm_wday
成员的struct tm
参数(例如,某些glibc实现)。
int get_weekday(char * str) { struct tm tm; memset((void *) &tm, 0, sizeof(tm)); if (strptime(str, "%d-%m-%Y", &tm) != NULL) { time_t t = mktime(&tm); if (t >= 0) { return localtime(&t)->tm_wday; // Sunday=0, Monday=1, etc. } } return -1; }
或者你可以编码这些规则来在一个非常长的单行中做一些算术:
- 1900年1月1日是星期一。
- 三十天有九月,四月,六月和十一月; 所有其他人都有三十一人,仅仅拯救二月,二十八岁,风雨无阻,闰年二十九岁。
- 闰年发生在任何一年,可被4整除,但除非可被400整除,否则不会在一个世纪上。
编辑:请注意,此解决方案仅适用于UNIX纪元(1970-01-01T00:00:00Z)之后的日期。
正如维基百科所报道的那样,1990年迈克尔基思和汤姆克拉弗发表了一个表达式,以尽量减少进入一个自包含函数所需的击键次数,以便将格里高利日期转换为一周中的数字日。
表达式既不保留y
也不保留d
,并返回表示日期的从零开始的索引,从星期日开始,即如果日期是星期一,则表达式返回1
。
使用表达式的代码示例如下:
int d = 15 ; //Day 1-31 int m = 5 ; //Month 1-12` int y = 2013 ; //Year 2013` int weekday = (d += m < 3 ? y-- : y - 2, 23*m/9 + d + 4 + y/4- y/100 + y/400)%7;
该表达式使用逗号运算符 ,如本答案中所述 。
请享用! 😉
这是基于维基百科关于朱利安日的文章的C99版本
#include const char *wd(int year, int month, int day) { /* using C99 compound literals in a single line: notice the splicing */ return ((const char *[]) \ {"Monday", "Tuesday", "Wednesday", \ "Thursday", "Friday", "Saturday", "Sunday"})[ \ ( \ day \ + ((153 * (month + 12 * ((14 - month) / 12) - 3) + 2) / 5) \ + (365 * (year + 4800 - ((14 - month) / 12))) \ + ((year + 4800 - ((14 - month) / 12)) / 4) \ - ((year + 4800 - ((14 - month) / 12)) / 100) \ + ((year + 4800 - ((14 - month) / 12)) / 400) \ - 32045 \ ) % 7]; } int main(void) { printf("%d-%02d-%02d: %s\n", 2011, 5, 19, wd(2011, 5, 19)); printf("%d-%02d-%02d: %s\n", 2038, 1, 19, wd(2038, 1, 19)); return 0; }
通过从wd()函数中的return
行中删除拼接和空格,可以将其压缩为286个字符的单行:)
编辑:版本2(3行)—通过使其成为静态来避免返回自动数组元素的可能复杂性。
#include const char *wd(int year, int month, int day) { static const char *weekdayname[] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; size_t JND = \ day \ + ((153 * (month + 12 * ((14 - month) / 12) - 3) + 2) / 5) \ + (365 * (year + 4800 - ((14 - month) / 12))) \ + ((year + 4800 - ((14 - month) / 12)) / 4) \ - ((year + 4800 - ((14 - month) / 12)) / 100) \ + ((year + 4800 - ((14 - month) / 12)) / 400) \ - 32045; return weekdayname[JND % 7]; } int main(void) { printf("%d-%02d-%02d: %s\n", 2011, 5, 19, wd(2011, 5, 19)); printf("%d-%02d-%02d: %s\n", 2038, 1, 19, wd(2038, 1, 19)); return 0; }
这是我的实施。 它很短,包括错误检查。 如果您想要在01-01-1900之前的日期,您可以轻松地将锚更改为公历的开始日期。
#include int main(int argv, char** arv) { int month[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; char* day[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; int d, m, y, i; printf("Fill in a date after 01-01-1900 as dd-mm-yyyy: "); scanf("%d-%d-%d", &d, &m, &y); // correction for leap year if (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) month[1] = 29; if (y < 1900 || m < 1 || m > 12 || d < 1 || d > month[m - 1]) { printf("This is an invalid date.\n"); return 1; } for (i = 1900; i < y; i++) if (i % 4 == 0 && (i % 100 != 0 || i % 400 == 0)) d += 366; else d += 365; for (i = 0; i < m - 1; i++) d += month[i]; printf("This is a %s.\n", day[d % 7]); return 0; }
/* Program to calculate the day on a given date by User */ #include #include #include void main() { int dd=0,mm=0,i=0,yy=0,odd1=0,todd=0;//variable declaration for inputing the date int remyr=0,remyr1=0,lyrs=0,oyrs=0,cyr=0,upyr=0,leap=0;//variable declaration for calculation of odd days int montharr[12]={31,28,31,30,31,30,31,31,30,31,30,31};//array of month days clrscr(); printf("Enter the date as DD-MM-YY for which you want to know the day\t:"); scanf("%d%d%d",&dd,&mm,&yy); //input the date /* check out correct date or not? */ if(yy%100==0) { if(yy%400==0) { //its the leap year leap=1; if(dd>29&&mm==2) { printf("You have entered wrong date"); getch(); exit(0); } } else if(dd>28&&mm==2) { //not the leap year printf("You have entered wrong date"); getch(); exit(0); } } else if(yy%4==0) { //again leap year leap=1; if(dd>29&mm==2) { printf("You have entered wrong date"); getch(); exit(0); } } else if(dd>28&&mm==2) { //not the leap year printf("You have entered wrong date"); getch(); exit(0); } //if the leap year feb month contains 29 days if(leap==1) { montharr[1]=29; } //check date,month,year should not be beyond the limits if((mm>12)||(dd>31)|| (yy>5000)) { printf("Your date is wrong"); getch(); exit(0); } //odd months should not contain more than 31 days if((dd>31 && (mm == 1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12))) { printf("Your date is wrong"); getch(); exit(0); } //even months should not contains more than 30 days if((dd>30 && (mm == 4||mm==6||mm==9||mm==11))) { printf("Your date is wrong"); getch(); exit(0); } //logic to calculate odd days..... printf("\nYou have entered date: %d-%d-%d ",dd,mm,yy); remyr1=yy-1; remyr=remyr1%400; cyr=remyr/100; if(remyr==0) { oyrs=0; } else if(cyr==0 && remyr>0) { oyrs=0; } else if(cyr==1) { oyrs=5; } else if(cyr==2) { oyrs=3; } else if(cyr==3) { oyrs=1; } upyr=remyr%100; lyrs=upyr/4; odd1=lyrs+upyr; odd1=odd1%7; odd1=odd1+oyrs; for(i=0;i7) todd=todd%7; //total odd days gives the re quired day.... printf("\n\nThe day on %d-%d-%d :",dd,mm,yy); if(todd==0) printf("Sunday"); if(todd==1) printf("Monday"); if(todd==2) printf("Tuesday"); if(todd==3) printf("Wednesday"); if(todd==4) printf("Thrusday"); if(todd==5) printf("Friday"); if(todd==6) printf("Saturday"); getch(); }
我想出的答案:
const int16_t TM_MON_DAYS_ACCU[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; int tm_is_leap_year(unsigned year) { return ((year & 3) == 0) && ((year % 400 == 0) || (year % 100 != 0)); } // The "Doomsday" the the day of the week of March 0th, // ie the last day of February. // In common years January 3rd has the same day of the week, // and on leap years it's January 4th. int tm_doomsday(int year) { int result; result = TM_WDAY_TUE; result += year; // I optimized the calculation a bit: result += year >>= 2; // result += year / 4 result -= year /= 25; // result += year / 100 result += year >>= 2; // result += year / 400 return result; } void tm_get_wyday(int year, int mon, int mday, int *wday, int *yday) { int is_leap_year = tm_is_leap_year(year); // How many days passed since Jan 1st? *yday = TM_MON_DAYS_ACCU[mon] + mday + (mon <= TM_MON_FEB ? 0 : is_leap_year) - 1; // Which day of the week was Jan 1st of the given year? int jan1 = tm_doomsday(year) - 2 - is_leap_year; // Now just add these two values. *wday = (jan1 + *yday) % 7; }
使用这些定义(匹配time.h
struct tm
):
#define TM_WDAY_SUN 0 #define TM_WDAY_MON 1 #define TM_WDAY_TUE 2 #define TM_WDAY_WED 3 #define TM_WDAY_THU 4 #define TM_WDAY_FRI 5 #define TM_WDAY_SAT 6 #define TM_MON_JAN 0 #define TM_MON_FEB 1 #define TM_MON_MAR 2 #define TM_MON_APR 3 #define TM_MON_MAY 4 #define TM_MON_JUN 5 #define TM_MON_JUL 6 #define TM_MON_AUG 7 #define TM_MON_SEP 8 #define TM_MON_OCT 9 #define TM_MON_NOV 10 #define TM_MON_DEC 11
#include #include #include int fm(int date, int month, int year) { int fmonth, leap; if ((year % 100 == 0) && (year % 400 != 0)) leap = 0; else if (year % 4 == 0) leap = 1; else leap = 0; fmonth = 3 + (2 - leap) * ((month + 2) / (2 * month))+ (5 * month + month / 9) / 2; fmonth = fmonth % 7; return fmonth; } int day_of_week(int date, int month, int year) { int dayOfWeek; int YY = year % 100; int century = year / 100; printf("\nDate: %d/%d/%d \n", date, month, year); dayOfWeek = 1.25 * YY + fm(date, month, year) + date - 2 * (century % 4); //remainder on division by 7 dayOfWeek = dayOfWeek % 7; switch (dayOfWeek) { case 0: printf("weekday = Saturday"); break; case 1: printf("weekday = Sunday"); break; case 2: printf("weekday = Monday"); break; case 3: printf("weekday = Tuesday"); break; case 4: printf("weekday = Wednesday"); break; case 5: printf("weekday = Thursday"); break; case 6: printf("weekday = Friday"); break; default: printf("Incorrect data"); } return 0; } int main() { int date, month, year; printf("\nEnter the year "); scanf("%d", &year); printf("\nEnter the month "); scanf("%d", &month); printf("\nEnter the date "); scanf("%d", &date); day_of_week(date, month, year); return 0; }
输出:输入2012年
输入月份02
输入日期29
日期:2012年2月29日
工作日=星期三
查找星期几的超高效单线C代码
int dayOfWeek(int y, int m, int d) { return ((y-=m<3)+y/4-y/100+y/400+"-bed=pen+mad."[m]+d)%7; }
来源 - 这里↗
详情 - 这里↗
我想你可以在glib中找到它: http : //developer.gnome.org/glib/unstable/glib-Date-and-Time-Functions.html#g-date-get-day
问候
#include static char day_tab[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} }; int main() { int year,month; scanf("%d%d%d",&year,&month,&day); printf("%d\n",day_of_year(year,month,day)); return 0; } int day_of_year(int year ,int month,int day) { int i,leap; leap = year%4 == 0 && year%100 != 0 || year%400 == 0; if(month < 1 || month >12) return -1; if (day <1 || day > day_tab[leap][month]) return -1; for(i= 1;i
这是我在c中创建的一个简单代码,可以解决您的问题:
#include #include int main() { int y,n,oy,ly,td,a,month,mon_,d,days,down,up; // oy==ordinary year, td=total days, d=date printf("Enter the year,month,date: "); scanf("%d%d%d",&y,&month,&d); n= y-1; //here we subtracted one year because we have to find on a particular day of that year, so we will not count whole year. oy= n%4; if(oy==0) // for leap year { mon_= month-1; down= mon_/2; //down means months containing 30 days. up= mon_-down; // up means months containing 31 days. if(mon_>=2) { days=(up*31)+((down-1)*30)+29+d; // here in down case one month will be of feb so we subtracted 1 and after that seperately td= (oy*365)+(ly*366)+days; // added 29 days as it is the if block of leap year case. } if(mon_==1) { days=(up*31)+d; td= (oy*365)+(ly*366)+days; } if(mon_==0) { days= d; td= (oy*365)+(ly*366)+days; } } else { mon_= month-1; down= mon_/2; up= mon_-down; if(mon_>=2) { days=(up*31)+((down-1)*30)+28+d; td= (oy*365)+(ly*366)+days; } if(mon_==1) { days=(up*31)+d; td= (oy*365)+(ly*366)+days; } if(mon_==0) { days= d; td= (oy*365)+(ly*366)+days; } } ly= n/4; a= td%7; if(a==0) printf("\nSunday"); if(a==1) printf("\nMonday"); if(a==2) printf("\nTuesday"); if(a==3) printf("\nWednesday"); if(a==4) printf("\nThursday"); if(a==5) printf("\nFriday"); if(a==6) printf("\nSaturday"); return 0; }
对于星期几,2000年至2099年。
uint8_t rtc_DayOfWeek(uint8_t year, uint8_t month, uint8_t day) { //static const uint8_t month_offset_table[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; // Typical table. // Added 1 to Jan, Feb. Subtracted 1 from each instead of adding 6 in calc below. static const uint8_t month_offset_table[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; // Year is 0 - 99, representing years 2000 - 2099 // Month starts at 0. // Day starts at 1. // Subtract 1 in calc for Jan, Feb, only in leap years. // Subtracting 1 from year has the effect of subtracting 2 in leap years, subtracting 1 otherwise. // Adding 1 for Jan, Feb in Month Table so calc ends up subtracting 1 for Jan, Feb, only in leap years. // All of this complication to avoid the check if it is a leap year. if (month < 2) { year--; } // Century constant is 6. Subtract 1 from Month Table, so difference is 7. // Sunday (0), Monday (1) ... return (day + month_offset_table[month] + year + (year >> 2)) % 7; } /* end rtc_DayOfWeek() */
这个有效:我把2006年1月作为参考。 (这是一个星期天)
int isLeapYear(int year) { if(((year%4==0)&&(year%100!=0))||((year%400==0))) return 1; else return 0; } int isDateValid(int dd,int mm,int yyyy) { int isValid=-1; if(mm<0||mm>12) { isValid=-1; } else { if((mm==1)||(mm==3)||(mm==5)||(mm==7)||(mm==8)||(mm==10)||(mm==12)) { if((dd>0)&&(dd<=31)) isValid=1; } else if((mm==4)||(mm==6)||(mm==9)||(mm==11)) { if((dd>0)&&(dd<=30)) isValid=1; } else { if(isLeapYear(yyyy)){ if((dd>0)&&dd<30) isValid=1; } else { if((dd>0)&&dd<29) isValid=1; } } } return isValid; } int calculateDayOfWeek(int dd,int mm,int yyyy) { if(isDateValid(dd,mm,yyyy)==-1) { return -1; } int days=0; int i; for(i=yyyy-1;i>=2006;i--) { days+=(365+isLeapYear(i)); } printf("days after years is %d\n",days); for(i=mm-1;i>0;i--) { if((i==1)||(i==3)||(i==5)||(i==7)||(i==8)||(i==10)) { days+=31; } else if((i==4)||(i==6)||(i==9)||(i==11)) { days+=30; } else { days+= (28+isLeapYear(i)); } } printf("days after months is %d\n",days); days+=dd; printf("days after days is %d\n",days); return ((days-1)%7); }
不在一行代码中,没有什么可以处理C标准库中的日期。 但是,基于Doomsday算法或类似算法编写函数会相当简单。
#include int main(void) { int n,y; int ly=0; int mon; printf("enter the date\n"); scanf("%d",&n); printf("enter the month in integer\n"); scanf("%d",&mon); mon=mon-1; printf("enter year\n"); scanf("%d",&y); int dayT; dayT=n%7; if((y%4==0&&y%100!=0)|(y%4==0&&y%100==0&&y%400==0)) { ly=y; printf("the given year is a leap year\n"); } char a[12]={6,2,2,5,0,3,5,1,4,6,2,4}; if(ly!=0) { a[0]=5; a[1]=1; } int m,p; m=a[mon]; int i,j=0,t=1; for(i=1600;i<=3000;i++) { i=i+99; if(i
}