PHP strtotime function usage, implementation principle and source code analysis, Strtotime function
SOURCE Location: \ext\date\php_date.c
Copy the Code code as follows:
/* {{{proto int strtotime (string time [, int now])
Convert string representation of date and time to a timestamp */
Php_function (Strtotime)
{
Char *times, *initial_ts;
int Time_len, Error1, Error2;
struct Timelib_error_container *error;
Long preset_ts = 0, ts;
Timelib_time *t, *now;
Timelib_tzinfo *tzi;
Tzi = Get_timezone_info (Tsrmls_c);
if (ZEND_PARSE_PARAMETERS_EX (Zend_parse_params_quiet, Zend_num_args () tsrmls_cc, "SL", X, &time_len, &preset_ TS)! = FAILURE) {
/* We have an initial timestamp */
now = Timelib_time_ctor ();
Initial_ts = Emalloc (25);
snprintf (Initial_ts, "@%ld UTC", preset_ts);
t = Timelib_strtotime (Initial_ts, strlen (initial_ts), NULL, Date_timezonedb, Php_date_parse_tzfile_wrapper); /* We ignore the error here, as this should never fail */
Timelib_update_ts (t, Tzi);
Now->tz_info = Tzi;
Now->zone_type = timelib_zonetype_id;
Timelib_unixtime2local (now, T->sse);
Timelib_time_dtor (t);
Efree (INITIAL_TS);
} else if (Zend_parse_parameters (Zend_num_args () tsrmls_cc, "S|l", X, &time_len, &preset_ts)! = FAILURE) {
/* We have no initial timestamp */
now = Timelib_time_ctor ();
Now->tz_info = Tzi;
Now->zone_type = timelib_zonetype_id;
Timelib_unixtime2local (now, (TIMELIB_SLL) time (NULL));
} else {
Return_false;
}
if (!time_len) {
Timelib_time_dtor (now);
Return_false;
}
t = Timelib_strtotime (times, Time_len, &error, Date_timezonedb, Php_date_parse_tzfile_wrapper);
Error1 = error->error_count;
Timelib_error_container_dtor (Error);
Timelib_fill_holes (t, now, Timelib_no_clone);
Timelib_update_ts (t, Tzi);
ts = timelib_date_to_int (t, &error2);
Timelib_time_dtor (now);
Timelib_time_dtor (t);
if (Error1 | | error2) {
Return_false;
} else {
Return_long (TS);
}
}
/* }}} */
The Strtotime function will be in a situation when it uses Strtotime ("-1 month") for one months today.
Therefore also leads to write this article, this article includes the following content:
1). Some uses of the Strtotime function
2). Basic principle of strtotime function implementation
3). Strtotime ("-1 month") The reason why the evaluation failed
Some uses of the Strtotime function
1, Strtotime ("JAN") and Strtotime ("January")
The effect of these two usages is the same, return to the specified month today, if the specified month is not today, then deferred to the next one months. As in 2011-03-31 for February, the code:
Copy the Code code as follows:
echo Date ("Y-m-d h:i:s", Strtotime ("Feb", Strtotime ("2011-03-31"));
The program will output: 2011-03-03 00:00:00. From the point of view, the result may not necessarily be what we want, but it is also a solution, and what is the decision? The Strtotime function calculates only the month when the month is executed, which is equivalent to setting the month directly to the value of the specified month, and for example, Jan,january has a corresponding internal value.
2. First keyword
First is an auxiliary keyword that can be used with the day of the week, Tian Deng can specify a keyword combination for the confirmation value, such as for a 2011-year-old Sunday:
Copy the Code code as follows:
echo Date ("Y-m-d h:i:s", Strtotime ("Second Sunday", Strtotime ("2011-01-01")), "
";
In PHP source code, for first and week and day combination of use is separate, that is, first day corresponding to a processing operation, in the final C implementation, the value of days is specified as 1, that is, the D field in the time structure is specified as 1, the following code:
Copy the Code code as follows:
Switch (time->relative.first_last_day_of) {
Case 1:/* First */
Time->d = 1;
Break
Case 2:/* Last */
time->d = 0;
time->m++;
Break
}
3, Previous and Next keywords
Similar to first, the previous keyword can be used in combination with the week, day, or the previous one weeks of the specified time. The code is as follows:
Copy the Code code as follows:
echo Date ("Y-m-d h:i:s", Strtotime ("Previous Sunday", Strtotime ("2011-02-01")), "
";
The program will output: 2011-01-30 00:00:00
Program for the previous Sunday of 2011-02-01.
The next keyword, in contrast to previous, represents the next one weeks or the following day.
4. Last key word
The last keyword can be either a previous or a final. If you ask for a date on Sunday:
Copy the Code code as follows:
echo Date ("Y-m-d h:i:s", Strtotime ("Last Sunday", Strtotime ("2011-02-05")), "
";
The program will output: 2011-01-30 00:00:00
When the program is last, its scenario is the last day of the month on which the specified date is, which is equivalent to the result of date ("T"). For the last day of February 2000:
Copy the Code code as follows:
echo Date ("Y-m-d h:i:s", Strtotime ("Last Day", Strtotime ("2000-02-01")), "
";
The first, previous, last, and this keywords belong to the same group in the re file.
5. Back and Front keywords
These two keywords are the forward and backward operations for the hours of the day, and their invocation format is as follows:
Copy the Code code as follows:
echo Date ("Y-m-d h:i:s", Strtotime ("Back of the", Strtotime ("2011-02-01")), "
";
echo Date ("Y-m-d h:i:s", Strtotime ("front of", Strtotime ("2011-02-01")), "
";
Back indicates that the time is set to a position of 15 minutes after one hours of the specified hour value. If it is 24, it is counted to 0:15 the next day.
The front represents the position of a time setting of 45 minutes for the first one hours of the specified hour value. If it's 0, it's 23:45 the day before.
The above code output: 2011-02-02 00:15:00 2011-02-01 23:45:00. Where back of and front of the array must be greater than or equal to 0 and less than or equal to 24.
The basic principle of strtotime function implementation
Official documentation for the Strtotime function: This function expects to accept a string containing the U.S. English date format and attempt to resolve it to a Unix timestamp (the number of seconds from January 1 1970 00:00:00 GMT) whose value is relative to the time given by the now parameter. If this parameter is not provided then the current time of the system is used.
This is a standard PHP built-in function that has existed since PHP4. The Strtotime function is loaded in an extended manner and has its full implementation in the Ext/date directory. As a standard built-in function, its definition format is also standard, as follows:
Copy the Code code as follows:
Php_function (Strtotime)
Processing input, for whether there is a second parameter has no processing
Invoke correlation function, implement string parsing and result calculation
return results
}
In the input processing, the first two parameters are identified and processed, if not, then the second parameter does not exist, if not, then an error, return false.
The first argument to the Strtotime function is a string, and for this string, because of its complexity, PHP uses its lexical parsing tools: re2c. In the/ext/date/lib directory, from the Parse_date.re file we can see its original re file. When the user passes in a string as a parameter, this string is handed to the program for processing, matching different handler functions for its string. As Strtotime ("Yesterday") is called, parsing the string will match the yesterday string, the corresponding function of this string is as follows:
Copy the Code code as follows:
' Yesterday '
{
Debug_output ("Yesterday");
Timelib_init;
Timelib_have_relative ();
Timelib_unhave_time ();
S->TIME->RELATIVE.D =-1;
Timelib_deinit;
return timelib_relative;
}
Here are a few key structures:
Copy the Code code as follows:
typedef struct SCANNER {
int FD;
Uchar *lim, *str, *ptr, *cur, *tok, *pos;
unsigned int line, Len;
struct Timelib_error_container *errors;
struct Timelib_time *time;
Const TIMELIB_TZDB *TZDB;
} Scanner;
typedef struct TIMELIB_TIME {
Timelib_sll y, M, D; /* year, Month, day */
Timelib_sll h, I, S; /* Hour, MInute, Second */
Double F; /* fraction */
int z; /* GMT offset in minutes */
Char *tz_abbr; /* Timezone abbreviation (display only) */
Timelib_tzinfo *tz_info; /* Timezone Structure */
signed int DST; /* Flag If we were parsing a DST zone */
Timelib_rel_time relative;
TIMELIB_SLL SSE; /* Seconds since Epoch * *
unsigned int have_time, have_date, Have_zone, have_relative, Have_weeknr_day;
unsigned int sse_uptodate; /*!0 If the SSE member is up to date with the Date/time members */
unsigned int tim_uptodate; /*!0 If the date/time members is up to date with the SSE member */
unsigned int is_localtime; /* 1 If the current struct represents localtime, 0 if it's in GMT */
unsigned int zone_type; /* 1 time offset,
* 3 TimeZone identifier,
* 2 TimeZone abbreviation */
} timelib_time;
typedef struct TIMELIB_REL_TIME {
Timelib_sll y, M, D; /* years, Months and days */
Timelib_sll h, I, S; /* Hours, MInutes and Seconds */
int weekday; /* Stores the day in ' next Monday ' */
int weekday_behavior; /* 0:the current day should *not* is counted when advancing forwards; 1:the *should* Be counted */
int first_last_day_of;
int invert; /* Whether The difference should be inverted */
TIMELIB_SLL days; /* Contains The number of *days*, instead of y-m-d differences * *
Timelib_special Special;
unsigned int have_weekday_relative, have_special_relative;
} timelib_rel_time;
S->TIME->RELATIVE.D = 1; means that the relative number of days of the current time is-1. This is only the intermediate result of intermediate lexical parsing, but the final result is calculated by these intermediate results.
Strtotime ("-1 month") Reason for evaluation failure
Although Strtotime ("-1 month") This approach fails to evaluate the number of days in the last one months compared to the first one months, it is not, in essence, a mistake. PHP's implementation is understandable. It's just that our needs determine that we can't use this method, so we call it evaluation failure.
Let's take a look at its implementation, because there is no second argument, so the program uses the default current time. The first parameter is passed to the -1 month string, which corresponds to the regular in the re file:
Copy the Code code as follows:
Reltextunit = ((' sec ' | ' Second ' | ' Min ' | ' Minute ' | ' Hour ' | ' Day ' | ' Fortnight ' | ' Forthnight ' | ' Month ' | ' Year ') ' s '?) | ' Weeks ' | Daytext;
Relnumber = ([+-]*[\t]*[0-9]+);
relative = Relnumber space? (Reltextunit | ' Week ');
The final relative will correspond to a series of actions, the program will recognize the previous-1 and subsequent month string, month corresponds to an operation type: Timelib_month. After that, the following code is performed based on the identified numbers and operation types:
Copy the Code code as follows:
Case TIMELIB_MONTH:S->TIME->RELATIVE.M + = Amount * relunit->multiplier; Break
As in the code, the relative value of the month is recorded directly minus one. However, for a situation similar to March 31, there is no number 31st in February, and the program automatically calculates the date to the next one months.
http://www.bkjia.com/PHPjc/953146.html www.bkjia.com true http://www.bkjia.com/PHPjc/953146.html techarticle PHP strtotime function usage, implementation principle and source code analysis, Strtotime function source location: \EXT\DATE\PHP_DATE.C Copy code code as follows:/* {{proto int strtotime (string time [ , I ...