C программа для поиска дня недели с заданной датой - PullRequest
13 голосов
/ 19 мая 2011

Есть ли способ узнать дату недели по заданной дате всего в одной строке кода C?

Например

Учитывая 19-05-2011 (дд-мм-гггг)) дает мне четверг

Ответы [ 15 ]

23 голосов
/ 20 января 2014

Как сообщает также Википедия , в 1990 году Майкл Кит и Том Крейвер опубликовали выражение для сведения к минимуму количества нажатий клавиш, необходимых для ввода автономной функции для преобразования григорианской даты в числовой деньweek.

Выражение не сохраняет ни 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;  

В выражении используется оператор запятой , как обсуждалось в этого ответа .

Наслаждайтесь!; -)

16 голосов
/ 19 мая 2011

Однострочник маловероятен, но функция strptime может использоваться для анализа вашего формата даты, а аргумент 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;
}

Или вы можете закодировать эти правила, чтобы сделать некоторую арифметику в действительно длинной одной строке:

  • 1 января 1900 года был понедельник.
  • Тридцать дней - сентябрь, апрель, июнь и ноябрь; у всех остальных тридцать один, кроме одного февраля, в котором двадцать восемь, дождь или блеск, а в високосные годы двадцать девять.
  • Високосный год наступает в любой год, равномерно делимый на 4, но не на столетие, если он не делится на 400.

РЕДАКТИРОВАТЬ: обратите внимание, что это решение работает только для дат после эпохи UNIX (1970-01-01T00: 00: 00Z).

6 голосов
/ 19 мая 2011

Вот версия C99, основанная на статье в википедии о Юлианском дне

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

Удалив сплайсинг и пробелы из строки return в функции wd (), его можно сжать в одну строку длиной 286 символов:)

1 голос
/ 11 октября 2014
#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;
}

ВЫХОД: введите год 2012

Введите месяц 02

Введите дату 29

Дата: 29/2 / 2012

будний день = среда

1 голос
/ 15 мая 2014

Ответ, который я придумал:

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 tm из time.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 голос
/ 13 мая 2014
/*
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 голос
/ 04 декабря 2011

Это моя реализация.Это очень короткий и включает в себя проверку ошибок.Если вам нужны даты до 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 голосов
/ 03 мая 2018

за день недели, годы 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() */
0 голосов
/ 24 апреля 2018

Вот простой код, который я создал в c, который должен решить вашу проблему:

#include <conio.h>

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;   
}
0 голосов
/ 18 января 2017
#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;

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...