Analysis of mktime Algorithm in Linux source code

Source: Internet
Author: User
Analysis of mktime Algorithm in Linux source code

Http://yuxu9710108.blog.163.com/blog/static/23751534201071111843396/

Analysis of mktime Algorithm in Linux source code

We know that the system time read from CMOS is not of the time_t type, but is similar to struct TM, and is stored separately.

Then, to convert it to the time_t type that is easy to process by the system, the algorithm needs to be converted.

We all know that our calendars are still relatively complex. It may be difficult to handle them if we have a month or a year rather than a year.

However, the Linux source code uses only a few lines to complete this complex conversion (Gauss algorithm), which is amazing. Let's talk about the source code first:

Unsigned long
Mktime (const unsigned int year0, const unsigned int mon0,
Const unsigned int day, const unsigned int hour,
Const unsigned int min, const unsigned int Sec)
{
Unsigned int MON = mon0, year = year0;

/* 1 .. 12-> 11, 12, 1 .. 10 */
If (0> = (INT) (Mon-= 2 )){
Mon + = 12;/* puts Feb last since it has Leap Day */
Year-= 1;
}

Return (unsigned long)
(Year/4-year/100 + year/400 + 367 * Mon/12 + day) +
Year x 365-719499
) * 24 + hour/* now have hours */
) * 60 + min/* now have minutes */
) * 60 + sec;/* finally seconds */
}

It looks dazzling, with no clue. Next let's analyze the algorithm in detail.

Let's look at the return sentence without looking at the previous one. The formula has the following structure as a whole:

T = (x * 24 + hour) * 60 + min) * 60 + Sec

This indicates that the algorithm first calculates the number of days X starting from January 1, January 1, 1970, and then obtains the specific time value T.

Therefore, we focus on how to calculate the number of days X. That is, x = year/4-year/100 + year/400 + 367 * Mon/12 + day + year * 365-719499.

First, you can split it:

Y = year/4-year/100 + year/400
Z = 367 * Mon/12
W = year * 365 + day
X = Y + Z + w-719499

Y is very simple. It calculates the number of all leap years from the first year of the year to the year you want. We can see from the W formula that the algorithm assumes that all years are normal years (365 days), plus the additional days of the leap year (formula Y ).

So far, it has been relatively simple. The key is what happened to the constant 719499 In the Z and X formulas. It seems inexplicable. What is the relationship between them and the IF judgment before the return statement?

First of all, we need to clarify that constant 719499 is not the number of days since January 1, as many people have said.

If you don't believe it, you can write a script to get the correct number: 719162 days.

Obviously, 719162 is related to 719499. We focus on the if statement:

If (0> = (INT) (Mon-= 2 )){
Mon + = 12;/* puts Feb last since it has Leap Day */
Year-= 1;
}

Obviously, it wants to treat January and February as the last two months at the end of the previous year, and set March as the first month of the year. In this way, we can minimize the impact of a leap year.

According to this assumption, let's look at what the Z formula was like in January 1, 0001, and see what the Y + Z + W was like:

MON = January is changed to 0001 BC of the previous year (November;
Year minus one is changed to 0, so y = 0;
Z = 367*11/12 = 336;
W = 1 + 0*365 = 1;
Y + Z + W = 337.

337 is equal to 719499-719162! In other words, it is done to correct the above assumptions! Then these formulas are changed:

Y = year/4-year/100 + year/400
Z = 367 * Mon/12
V = z-337
W = year * 365 + day
X = y ++ W + V-719162

Let's look at style Z. This style does not show any name on the surface. The number 367 is obviously quite strange. Let's take a look at Mon and see what values this formula calculates:

Mon Z
1 30
2 61
3 91
4 122
5 152
6 183
7 214
8 244
9 275
10 305
11 336
12 367

What does it seem to see? Let's take a look at the subtraction of the adjacent two mon Z:

Mon DZ
1 30
2 31
3 30
4 31
5 30
6 31
7 31
8 30
9 31
10 30
11 31
12 31

Smell something. It's like the monthly or monthly rule. Let's recall what the if statement did. It changed January 2 to November and December, and March to January! Let's take a look:

Mon org-mon DZ
1 3 30
2 4 31
3 5 30
4 6 31
5 7 30
6 8 31
7 9 31
8 10 30
9 11 31
10 12 30
11 1 31
12 2 31

Why should it have been the first 30 days of the month of the new month?

Well, let's think about this principle. If Today is July 22, January 1, can you say that you have already passed 31 days this year? Apparently not. We can't include it in January.

We can see from January 1, April that if today is a fool's day, we are 31 days away from January 1, March 1.

As mentioned above, we assume that a year begins in March and ends in February of the following year. According to this rule, the entire formula contains only March. Theoretically, it should be 0!

But it does not matter. We can subtract it, and it becomes:

Z = 367 * Mon/12-30
V = z-307

Let's look back at the W formula, year * 365, but according to the above theory, we should not add the year that has not been completed. So here we subtract it and merge it with the V formula:

V = z + 58
W = (year-1) * 365 + day

We remember that the year of this algorithm began in March, so we did not calculate the number of days in January and February in the first year of the year: 31 + 28 = 59 days: (the year of the first year of the current year is a normal year)

V = z + 59-1

So what is the last subtraction of 1? Still the principle above. If it hasn't been done today, it should not be included!

To sum up, the entire algorithm is clear. What is hard to understand is that the assumptions starting in March and 367 * Mon/12 will generate a sequence similar to the size of the month.

Finally, sort out and list these statements as the end of this article:

Y = (year-1) * 365 + year/4-year/100 + year/400
M = 367 * Mon/12-30 + 59
D = day-1
X = Y + M + D-719162
T = (x * 24 + hour) * 60 + min) * 60 + Sec

Related Article

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.