2011-05-19 80 views
13

有沒有一種方法可以在一行C代碼中找出給定日期的星期幾?C程序找到給定日期的星期幾

例如

由於19-05-2011(DD-MM-YYYY)給我週四

+0

我相信你總是需要一些錨,即對於你知道星期幾的日期,例如「@ 1900年1月1日是星期一」in @ maerics的答案。我想其他建議的算法有這樣一個固定內置 – davka 2011-05-19 12:48:31

+0

檢查此鏈接。它還包含了如何完成計算的解釋。希望能幫助到你。 http://cprogramming.language-tutorial.com/2012/01/program-to-find-day-of-given-date-in-c.html – 2012-03-04 20:38:23

+2

參見[Zeller的同意](http://en.wikipedia。 org/wiki/Zeller%27s_congruence)來計算星期幾。我不知道在C中的行長度有任何限制,所以你可以重新格式化任何程序,以適應一行... – 2011-05-19 12:08:16

回答

14

一行代碼的可能性不大,但strptime function可以用來解析您的日期格式和struct tm參數可以用於查詢其tm_wday成員在系統上自動修改這些字段(例如一些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)。

0

不在一行代碼,沒有什麼關於處理C標準庫的日期。儘管如此,編寫一個基於Doomsday算法的函數或類似的函數會相當簡單。

+0

我只是想要的代碼,沒有內置函數,說我們有變量日,月,年。我想如果我們可以做些像((01-01-01)的日子+(迄今爲止的天數))%7 – theReverseFlick 2011-05-19 05:18:58

5

下面是基於wikipedia's article about Julian Day

#include <stdio.h> 

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; 
} 

C99的版本,通過在WD()函數,它可以壓縮到286字符單行:)

去除的 return線的拼接和空間

編輯:版本2(3行)---避免可能出現的有關通過使自動數組元素返回靜態的複雜性。

#include <stdio.h> 

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; 
} 
+0

很酷。我猜JND公式使用了一些其他日期的週日內置知識,例如公元前4713年1月1日?我不認爲你可以做到這一點 – davka 2011-05-19 12:45:12

+0

是的,當然。最主要的是能夠爲連續的日期生成一個連續的值。一旦你得到了這個,通過調整計算的'-32045'部分來「調整」這個值到一個已知的日期。您可以使用具有不同調整值的相同公式並創建「davka日數」:-) – pmg 2011-05-19 14:21:40

+1

爲什麼地球上代碼中行末端的所有反斜槓?它們都不是必需的;這不是一個宏,它不是一個字符串常量。 – 2014-06-25 23:04:41

0

這一個工程:我把2006年1月作爲參考。(這是一個星期日)

enter code here 

INT isLeapYear(INT年){

 if(((year%4==0)&&(year%100!=0))||((year%400==0))) 
     return 1; 
    else 
     return 0; 

} 

INT isDateValid(INT DD,INT毫米,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);     


       }` 
1

T他是我的執行。它很短,包括錯誤檢查。如果你想在01-01-1900之前的日期,你可以很容易地改變錨到公曆日期的開始日期。

#include <stdio.h> 

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; 
} 
0
#include<stdio.h> 
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<month ; i++) 
     { 
       day += day_tab[leap][year]; 
     } 
     return day; 
} 
18

作爲還報道通過Wikipedia,1990年邁克爾Keith和湯姆Craver發表的表達以最小化進入一個自包含的功能用於轉換公曆日期到的數值一天所需的擊鍵次數星期。

表達確實保持既不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; 

表達式使用逗號操作,如在this answer討論。

享受!;-)

+4

它是如何工作的? – 2016-03-17 00:00:17

1
/* 
Program to calculate the day on a given date by User 
*/ 

#include<stdio.h> 
#include<conio.h> 
#include<process.h> 
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;i<mm-1;i++) 
     { 
     odd1=odd1+montharr[i]; 
     } 
    todd=odd1+dd; 
    if(todd>7) 
     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(); 
} 
1

我想出了答案:

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, 
// i.e 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; 
} 

這些定義(匹配struct tmtime.h):

#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 
1
#include<stdio.h> 
#include<math.h> 
#include<conio.h> 
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; 
} 

OUTPUT: 輸入年月日2012

輸入月02

輸入日期29

日期:29/2/2012

平日=週三

+0

看起來不止一行C代碼給我。 – alexis 2014-10-11 12:38:16

1

超高效的班輪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; 
} 

來源-here ↗

詳細信息 - here ↗

-2
#include<stdio.h> 
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<y) 
    { 

     if(t==1) 
     { 
     p=5;t++; 
     } 
     else if(t==2) 
     { 
      p=3; 
      t++; 
     } 
     else if(t==3) 
     { 
      p=1; 
      t++; 
     } 
     else 
     { 
      p=0; 
      t=1; 
     } 

}} 
int q,r,s; 
q=y%100; 
r=q%7; 
s=q/4; 
int yTerm; 
yTerm=p+r+s; 
int w=dayT+m+yTerm; 
w=w%7; 
if(w==0) 
printf("SUNDAY"); 
else if(w==1) 
printf("MONDAY"); 
else if(w==2) 
printf("TUESDAY"); 
else if(w==3) 
printf("WEDNESDAY"); 
else if(w==4) 
printf("THURSDAY"); 
else if(w==5) 
printf("FRIDAY"); 
else 
printf("SATURDAY"); 
return 0; 

}

+0

請進行編輯以解釋您的代碼。目前這是一個代碼轉儲。當提供答案時,請解釋你的答案爲什麼是正確的。 – 2017-01-18 14:42:14

+0

https://www.youtube.com/results?search_query=how+to+find+the+day+of+the+week+for+any+date此鏈接將提供所有的東西來理解這個程序.... 。那就是基礎算法 – 2017-03-06 14:21:46

+0

@SurajSunny:請考慮編輯您的答案,以包含youtube鏈接中提供的信息摘要。堆棧溢出期望您的答案獨立於任何鏈接。請參閱https://meta.stackoverflow.com/q/8259 – Matt 2017-03-08 09:23:49