C Progtwig para encontrar el día de la semana dada la fecha

¿Hay alguna forma de averiguar el día de la semana en una sola línea de código C?

Por ejemplo

Dado 19-05-2011 (dd-mm-aaaa) me da jueves

No es probable una línea única, pero la función strptime se puede usar para analizar su formato de fecha y el argumento struct tm se puede consultar para su miembro tm_wday en sistemas que modifican esos campos automáticamente (por ejemplo, algunas implementaciones 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; } 

O podrías codificar estas reglas para hacer algo de aritmética en una sola línea larga:

  • 1 de enero de 1900 fue un lunes.
  • Treinta días tienen septiembre, abril, junio y noviembre; el rest tiene treinta y uno, salvo febrero solo, que tiene veintiocho, llueva o truene, y en los años bisiestos, veintinueve.
  • Un año bisiesto ocurre en cualquier año divisible por 4, pero no en un siglo a menos que sea divisible por 400.

EDITAR: tenga en cuenta que esta solución solo funciona para las fechas posteriores a la época UNIX (1970-01-01T00: 00: 00Z).

Como también informa Wikipedia , en 1990 Michael Keith y Tom Craver publicaron una expresión para minimizar el número de teclas necesarias para ingresar a una función independiente para convertir una fecha gregoriana en un día numérico de la semana.

La expresión no conserva ni y ni d , y devuelve un índice basado en cero que representa el día, comenzando con el domingo, es decir, si el día es lunes, la expresión devuelve 1 .

Un ejemplo de código que usa la expresión sigue:

 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; 

La expresión usa el operador de coma , como se explica en esta respuesta .

¡Disfrutar! 😉

Aquí hay una versión C99 basada en el artículo de wikipedia sobre Julian Day

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

Al eliminar el empalme y los espacios de la línea de return en la función wd (), se puede compactar con una sola línea de 286 caracteres 🙂


Edición: versión 2 (3 líneas): evite posibles complicaciones al devolver un elemento de una matriz automática, al hacerlo estático.

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

Esta es mi implementación. Es muy corto e incluye comprobación de errores. Si desea fechas anteriores al 01-01-1900, puede cambiar fácilmente el anclaje a la fecha de inicio del calendario gregoriano.

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

La respuesta que se me ocurrió:

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

con estos define (matching struct tm of 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 
 #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; } 

PRODUCTO: Ingrese el año 2012

Ingrese el mes 02

Ingrese la fecha 29

Fecha: 29/2/2012

día laborable = miércoles

Super Efficient One Liner C Code para encontrar el día de la semana

 int dayOfWeek(int y, int m, int d) { return ((y-=m<3)+y/4-y/100+y/400+"-bed=pen+mad."[m]+d)%7; } 

Fuente- aquí ↗

Detalles- aquí ↗

 #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 

Aquí hay un código simple que he creado en c que debería solucionar su problema:

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

Para el día de la semana, años 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() */ 

Este funciona: tomé enero de 2006 como referencia. (Es un domingo)

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

No en una línea de código, no hay nada para lidiar con las fechas en la biblioteca estándar de C. Sin embargo, sería bastante simple escribir una función basada en el algoritmo Doomsday, o similar.

 #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 

}