Determine the day of the week by date (using Kimlarsson to calculate the formula)

Source: Internet
Author: User
Tags constant modulus printf




Kimlarsson calculation formula determines the day
of the week by the date calculateweekday (int y, int m,int d) {
	if (m==1| | m==2) m+=12,y--;
	int iweek = (d+2*m+3* (m+1)/5+y+y/4-y/100+y/400)%7;
	Switch (iweek) {case
		0:printf ("Monday \ n");
     	Case 1:printf ("Tuesday \ n"); break;
     	Case 2:printf ("Wednesday \ n"); break;
     	Case 3:printf ("Thursday \ n"); break;
     	Case 4:printf ("Friday \ n"); break;
     	Case 5:printf ("Saturday \ n"); break;
     	Case 6:printf ("Sunday \ n"); break;
	}
}
int main ()
{
	calculateweekday (2015,9,17);
	return 0;
}




The C language determines the day of the week according to the date (using the Kimlarsson calculation formula) The algorithm is as follows:
Kimlarsson Calculation formula
W= (d+2*m+3* (m+1)/5+y+y/4-y/100+y/400) MoD 7

In the formula, D represents the number of days in a date, m represents the number of months, and Y represents the number of years.

Note: There is a difference in the formula from the other formulas:

Consider January and February as the January or March and January or April of the previous year, as in the case of 2004-1-10:2003-13-10 is calculated by substituting the formula.
The year of the year as a reference, the year of January 1 for Monday </PRE><PRE> procedures as follows:

#include "stdio.h"

void Caculateweekday (int y,int m, int d)
{
if (m==1| | m==2) {
m+=12;
y--;
}
int iweek= (d+2*m+3* (m+1)/5+y+y/4-y/100+y/400)%7;
Switch (Iweek)
{
Case 0:printf ("Monday \ n"); Break
Case 1:printf ("Tuesday \ n"); Break
Case 2:printf ("Wednesday \ n"); Break
Case 3:printf ("Thursday \ n"); Break
Case 4:printf ("Friday \ n"); Break
Case 5:printf ("Saturday \ n"); Break
Case 6:printf ("Sunday \ n"); Break
}
}
void Main ()
{
int year=0,month=0,day=0;
printf ("Please enter date: \ n format: 1900,1,1\n");
Char temp = ' 1 ';
while (temp! = ' 0 ')
{
scanf ("%d,%d,%d", &amp;year,&amp;month,&amp;day);
scanf ("%c", &amp;temp);
Caculateweekday (Year,month,day);
printf ("Input 0 exit, others continue:");
scanf ("%c", &amp;temp);
}
}

Operating effect:
Please enter the date:
Format is: 1900,1,1
2008,4,29
Tuesday
Input 0 exit, others continue: D
2008,1,1
Tuesday
Input 0 exit, others continue: l
2008,8,8
Friday
Input 0 exit, others continue: 0
Please press any key to continue ...

Editor's note: The week used to calculate the actual date is no problem. The principle is calculated based on the number of weeks known to be January 1, 1. If the day of the week is agreed on in your topic, you should pay attention to whether the day of the week is the same as the actual week, and if so, you need to consider a few days apart.



If you feel that not enough fun, you can look at the following formula of the derivation process, so that we have a more profound understanding of the calendar

Below we are completely according to their own ideas from simple to complex step to deduce ...   
    
    
  Before derivation, there are two provisions: ① with Y, M, D, W respectively, the Day of the week (W=0-6 representative Sunday-Saturday ② We start from January 1, 00 A.D. Sunday First, consider only the first 7 days, that is, D = 1---7 transform to W = 0---6 very intuitive to get: W = d-1 Two, expansion To the whole January of the concept of model 7 We all know, there is nothing much to say. But it can also be seen from our usual calendars, where each column in the calendar is a 7-arithmetic progression, and the weeks of 1, 8, 15, 22 are the same.    
    
          So the formula for the whole January is as follows: W = (d-1)% 7---------Formula ⑴ Three, year-to-month expansion due to monthly expansion is more troublesome, so the annual expansion in front of said ① we do not consider leap years, assuming that each year is 365 days.   
          Since 365 is 7 of 52 times times more than 1 days, the first day of each year and the last day of the week are the same. That is, the first day of the next year is one day behind the first day of the previous year.     
    
          This is an important conclusion, every year, the formula ⑴ will have a day of error, because we are starting from 0 years, so only need to simply add years to correct the expansion of the error caused by the year, the formula is as follows: W = (d-1 + y)% 7 ② taking leap years into account each leap year will be one more day, resulting in a one-day error in the latter.   
          If we are going to calculate the week of January 1, 2005, we have to consider how many leap years in the previous 2004-year period, plus this error can be calculated correctly.   
          According to the definition of leap year (can be 4 whole but not divisible by 100 or can be 400 whole), calculate the number of leap years: Y/4-y/100 + y/400. Since we are going to calculate the number of leap years before the year that is currently being computed,1, get the following formula: W = [D-1+y + (y-1)/4-(y-1)/100+ (y-1)/400]% 7-----Formula ⑵ Now, we got a yearly   
    
          Extended Formula ⑵, use this formula can calculate any year of January Thursday, extended to other months to consider this question quite a turn of mind, and then the previous method bold leave to find a breakthrough. ① Now we assume that each month is 28 days, and do not consider leap years with this hypothesis, the calculation of the week is too simple, because 28 is exactly 7 of the integer times, every month the week is the same, the formula ⑵ for any one months applies:) ② But the assumption is ultimately assumed , first January is not 28 days, this will result in February calculation error.   
          January is more than 28 days more than 3 days, that is, the formula ⑵ based on the February week should be postponed 3 days.   
          For March, the delay was also 3 days (February, exactly 28 days, no effect on the March calculation).   
          And so on, the calculation for each month adds the cumulative error of the preceding months.   
    
          Note that the error only affects the calculation of the following month, because December is the last one months, so do not consider the December error days, in the same vein, the January error days is 0, because there is no month before affecting it.   
  From this, think of creating an error table to correct every month's calculation.       ================================================== Monthly Error Cumulative modulus 7 1 3 0 0 2         0 3 3 3 3 3 3 4 2 6 6 5 3 8 1 6 2 11 4 7 3 13 6 8 3 16        2 9 2 19 5 10 3 21 0 11 2 24 3 1   
    
          2-26 5 (Leap year February will have a day of error, but we do not consider it now) ================================================== We will use an array of the last error table on the basis of the formula ⑵ can be extended to other months of the formula e[] = {0,3,3,6,1,4,6,2,5,0,3,5 } w = [D-1+y + e[m-1] + (y-1)/4-(y-1)/100+ (y-1)/400]% 7--Formula ⑶③ above error table we didn't Consider leap years, if it is a leap year, February will be a day of error, will affect the calculation of the subsequent 3-12 months, we temporarily in the programming to correct this situation, the increase of the qualification is if it is a leap years, and the calculation of the month after February, the need to add a day of error.   
          The approximate code is this: w = (d-1 + y + e[m-1] + (Y-1)/4-(Y-1)/100 + (y-1)/400);   if (m>2 && (y%4==0 && y%100!=0 | |   
          y%400==0) && y!=0) ++w;   
            
          W%= 7;   
          Now, the week of any day can be calculated correctly.   
    
          Note: 0 years is not a leap year, although most do not use this condition, but we start from 00 A.D., so this condition is not less.   
  ④ improvements        In Formula ⑶, the Child (y-1)/4-(y-1)/100+ (y-1)/400 that calculates the number of leap years is not included in the current year, and if the year is included, it is implemented if it is a leap year, W automatically adds 1. The effect is that if it was a leap year, 1, February of calculation will be more than one day error, we also fixed in the programming.   The code is as follows W = (d-1 + y + e[m-1] + Y/4-y/100 + y/400);   ----Formula ⑷if (m<3 && (y%4==0 && y%100!=0 | |   
          y%400==0) && y!=0)--w;   
            
          W%= 7;   
          Compared to the previous piece of code, we simplify the calculation of W.   
            
          You can actually further merge the constant-1 into the error table, but we will not do so for the time being.   
    
  At this point, we have a phased algorithm that can calculate the week of any day.   public class Week {public static void main (string[] args) {int y =   
                  2005;   
                  int m = 4;   
                    
                  int d = 25;   
                  int e[] = new int[]{0,3,3,6,1,4,6,2,5,0,3,5};   
                  int w = (d-1+e[m-1]+y+ (y>>2)-y/100+y/400); if (m< 3 && ((y&3) ==0 && y%100!=0 | |   
                  y%400==0) && y!=0) {--w;   
                    
                  } w%= 7;   
          System.out.println (w);   
          }} v. Simplification now we derive our own algorithm for calculating the week, but we cannot call it a formula.   
          The so-called formula, should be given after the date of the day can be manually calculated, but our current algorithm needs to remember an error table in order to calculate, so can only be called an algorithm, is not a formula. Below, we try to eliminate this error table ... ============================= conditional expression for eliminating leap year judgments ================== =========== due to the error generated in the leap year in February, the calculation of the subsequent months is affected. If February were the last of a year, it would not have an effect on the calculation of other months.   
          It may have been reminiscent of the article at the beginning of the formula why 1, February converted to the previous year's 13, 1 April Calculated it: This is the idea, we will 1, February as the last year of 13, 1 April to see. This results in two problems that need to be addressed: 1> the first day of the year is March 1, we have to re-deduce the calculation formula of W 2> error table has also changed, need a new calculation ① push   The 1> is calculated using the previous algorithm 0 March 1 is week 3 first 7 days, d = 1---7 ===> w   
  = 3----2                  Get w = (d+2)% 7 This applies equally to the entire March 2> expansion to March of each year [D + 2 + y + (y-1)/4-(Y-1)/100 + (Y-1)/400]% 7② error Table = =       ================================================ Monthly Error Cumulative modulus 7 3 3 0 0 4         2 3 3 5 3 5 5 6 2 8 1 7 3   
  10 3 8 3 13 6 9 2 16 2 10 3 18 4         11 2 21 0 12 3 23 2 13 3 26 5 14-   29 1 ==================================================③ Get the formula extended to other months e[]   
          = {0,3,5,1,3,6,2,4,0,2,5,1} w = [d+2 + e[m-3] +y+ (y-1)/4-(y-1)/100+ (y-1)/400]% 7 (3 <= m &lt= 14) We're still simplifying the y-1 equation w = [d+2 + e[m-3] +y+y/4-y/100+y/400]% 7 (3 <= M <= 14) This equation if it is a leap year, will Gaocheng more than 1 error but we will 1, February to the previous year's 13, 1 April, the year to reduce 1, so this   
          The error is automatically eliminated, so the following algorithm is obtained: int e[] = new int[]{0,3,5,1,3,6,2,4,0,2,5,1};   
                  if (M < 3) {m + = 12;   
          --y;   } int w = (d+2 + e[m-3] +y+ (Y/4)-y/100+y/400)% 7; -----Formula ⑸ We can see that the formula ⑸ is almost the same as the formula ⑷, except that the difference between the difference between the day of the error and a constant is caused by a different week of the starting date, 0 January 1 Sunday, 0 3rd 1st, Wednesday, three days of difference,   
    
          So the constant also changed from 1 to 2.   
    
    
          Now, we have successfully eliminated the tedious leap-year condition judgment. ============================= Elimination Error Table ============================= if there is a function mapping between M and E,   
    
          so that e[m-3] = f (m) we can use F (m) to replace the sub-item in the formula ⑸ E[m-3], also eliminate the error table. Because the error table has only 12 items, and each item can be added minus 7n  To make adjustments, this functional relationship can be pieced together. But this process can be extremely boring, I do not want to deduce it myself now, I want to use the results of predecessors.   
    
          The so-called walnuts, posterity:) The formula in the beginning of the article 2*m+3* (m+1)/5 This child has aroused my interest after many trials, I run the following code   for (M=1;   m<=14;   
          ++m) System.out.print (( -1+2*m+3* (m+1)/5)%7 + "");   
    
          System.out.println ();   My goodness, the output coincides with my error table. 2 4 0 3 5 1 3 6 2 4 0 2 5 1 Press any   
    
          Key to continue ...   
    
          The above is the output, look at the following 12 items, and my error table exactly match!!! Now simply, put f (m) =-1 + 2*m + m+1/5 generation into Formula ⑸, get w = (d+1+2*m+3* (m+1)/5+y+ (Y/4)-y/100+y   
    
          /400)% 7----equation 6 constraints: m=1,m=2 when m=m+12,y=y-1;   
    
          Now, we get the general calculation of the week formula, and "complete" is based on their own ideas deduced (that function mapping relationship does not count), as long as the understanding of the derivation of the steps, even if one day forget the formula, can be re-deduced! One might notice that the formula ⑹ a constant 1 from the formula at the beginning of the article, because the original formula uses the number 0--6 to represent Monday through Sunday, and I use 0--6 to represent Sunday through Saturday.   
    
    As a matter of fact, you can change the expression to whatever you like, simply by changing the constant.
  Six, the correctness of the validation formula. One months of the date is continuous, as long as there is a day, the relationship between the mold 7 is not wrong, so only one day in one months to verify that you can, a day to test 12 days.   
          Since scaling up to year and month only has to do with whether the leap years are related, it is necessary to validate at least one common year and one leap, which is at least 24 times validated.   
  I chose 2005 and 2008 to verify the 1th number of each month.   
                  The test code is as follows: Class Test {public int getweek (int y, int m, int d) {   
                          if (m<3) {m + = 12;   
                  --y;   
                  } int w = (d+1+2*m+3* (m+1)/5+y+ (y>>2)-y/100+y/400)% 7;   
          Return w;   
                  }} public class Week {public static void main (string[] args) {   
                  int y = 2005;   
                  int m = 1;   
                    
                  int d = 1;   
                  Test T = new Test ();   
 String week[] = new string[]{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"                 };   for (y=2005;   y<=2008;   y+=3) {for (m=1;   m<=12; ++M) {String str = y + "-" + M + "-" + D + "\ T" + we   
                                  Ek[t.getweek (y,m,d)];   
                          System.out.println (str);   
    
  }}}} perpetual calendar, check the output of the program, completely correct. Vii. something our derivation of this formula is based on the 0 March 1, which can be calculated for the date after that date.   
    
          But whether it can be extended to BC (13 in the 1 before A.D., 1 April). Although I was correct in January and February, and 1 (y=-1) December, I did not expect to extend it to BC in the derivation of this formula, so the above derivation process did not have enough theoretical basis to prove its applicability to BC.   
    
          (negative numbers are modeled in different compilers, such as C + +, as if processing is not entirely correct). The other is a bit of controversy over the existence of 0 years, a compromise that is 0 years old, but nothing has happened and its duration is 0. There are still 10 days in the Gligorij calendar in Rome (October 5, 1582 to 14 lasts 0), and 11 days (September 3, 1752 to 13th) in the British calendar are absent. Interested friends can look here: but what we do is the numerical calculation, regardless of whether the day exists, the duration is 24 hours or 23 hours or even 0 hours, as long as the number exists, there is one weeks corresponding to it.   
          So this formula is still applicable. If you want to calculate a time period, you must consider this problem. 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.