SOURCE Location: extdatephp_date.c
The code is as follows |
Copy Code |
/* {{{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", ×, &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", ×, &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); } } /* }}} */ |
Strtotime function in the use of Strtotime ("-1 month") for one months today, there will be some situation,
So it also leads to writing this article, which includes the following:
Some usages of strtotime function
The realization principle of strtotime function
Strtotime ("-1 month") The reason for the evaluation failure
Some usages of strtotime function
1, Strtotime ("the") and Strtotime ("January")
The effects of these two usages are the same, which are returned today for the specified month, and are postponed to the next one months if the specified month is not today. In 2011-03-31, as calculated in February, the code:
echo Date ("Y-m-d h:i:s", Strtotime ("Feb", Strtotime ("2011-03-31"));
The program will output: 2011-03-03 00:00:00. On the surface, the result may not necessarily be what we want, but it is a solution, so what is the decision? The Strtotime function calculates the month only when the month is calculated, which is equivalent to setting the month directly to the value of the specified month, whereas Jan,january will have a corresponding internal value.
2, the single keyword
First is an auxiliary keyword that can be used in combination with the week, day can specify the value of the keyword combinations, such as a 2011-year of one Sunday:
echo Date ("Y-m-d h:i:s", Strtotime ("Second Sunday", Strtotime ("2011-01-01")), "<br/>";
In the PHP source code, for the combination of the week and day is separate, that is, a processing operation, in the final C implementation, the value of the day is specified as 1, that is, the D field in the time structure is specified as 1, the following code:
Switch (time->relative.first_last_day_of) {
Case 1:/* A/*
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 and day, representing the one weeks or days before the specified time. As shown in the following code:
echo Date ("Y-m-d h:i:s", Strtotime ("Previous Sunday", Strtotime ("2011-02-01")), "<br/>";
Program output: 2011-01-30 00:00:00
The procedure is to ask for a Sunday before 2011-02-01.
The next keyword, in contrast to previous, represents the next one weeks or the following day.
4, last keyword
The last keyword can be either previous or final. If you ask for the date of the last Sunday:
echo Date ("Y-m-d h:i:s", Strtotime ("Last Sunday", Strtotime ("2011-02-05")), "<br/>";
Program output: 2011-01-30 00:00:00
When the program is last, the scenario is the last day of the month on which the specified date is, equivalent to the result of date ("T"). For the last day of February 2000:
echo Date ("Y-m-d h:i:s", Strtotime ("Last Day", Strtotime ("2000-02-01")), "<br/>";
The 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 of the hour of the day, and the calling format is as follows:
echo Date ("Y-m-d h:i:s", Strtotime ("Back of", Strtotime ("2011-02-01")), "<br/>";
echo Date ("Y-m-d h:i:s", Strtotime ("front of", Strtotime ("2011-02-01")), "<br/>";
Back indicates the position of the one hour after the time setting specifies the hour value of 15 points. If it is 24 o ' 0:15, Count to the next day.
Front represents the position of 45 points in the first one hours of the specified hour value for the time setting. 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 realization principle of strtotime function
Official documentation for the Strtotime function, this function expects to accept a string containing the U.S. English date format and tries to resolve it to a Unix timestamp (the number of seconds since January 1 1970 00:00:00 GMT), with a value relative to the time given by the now parameter, If this parameter is not supplied, the current time of the system is used.
This is a standard PHP built-in function that already exists from PHP4. The Strtotime function is loaded in an extended way and has its full implementation in the Ext/date directory. As a standard built-in function, its definition format is also standard, as follows:
Php_function (Strtotime)
Processing input, if there is no processing for the second parameter
Call correlation function to implement parsing and result calculation of string
return results
}
In the input processing, first identify the existence of two parameters and processing, if not this state, processing the second parameter does not exist, if none, then the error, return false.
The first parameter of the Strtotime function is a string, and because of its complexity, PHP uses the same tools as its lexical parsing: re2c. In the/ext/date/lib directory, we can see the original re file from the Parse_date.re file. When the user passes in a string as a parameter, this string is handed to the program to handle, matching different handler functions for its string. As Strtotime ("Yesterday") calls, parsing a string matches the yesterday string, which corresponds to the following function:
The code is as follows |
Copy Code |
' 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:
The code is as follows |
Copy Code |
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 was up to date with the Date/time members * * unsigned int tim_uptodate; /*!0 If the date/time members are up to date with the SSE member */ unsigned int is_localtime; /* 1 If the current struct represents localtime, 0 if it was 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 current day *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 is-1 for the current time. This is only the intermediate result of intermediate lexical parsing, but the final result is computed through these intermediate results.
Strtotime ("-1 month") Evaluate the reason for the failure
Although Strtotime ("-1 Month") This method fails to evaluate the number of days in the last one months over the previous one months, it is inherently not wrong. There is nothing wrong with PHP being implemented like this. It's just that our needs dictate that we can't use this method, so we call it the evaluation failure.
We look at its implementation and, because there is no second argument, the program uses the default current time. The first parameter passes in a -1 month string, and the regular in the re file corresponding to this string is:
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 corresponds to a series of actions, and the program recognizes the preceding-1 and subsequent MONTH strings, MONTH the corresponding type of operation: Timelib_month. After that, the action is performed based on the number and type of actions identified, the following code:
Case timelib_month: S->TIME->RELATIVE.M + + amount * relunit-> multiplier; Break
, the previous code is the direct record of the relative value of the month minus one. However, for cases similar to those of March 31, there was no number 31st in February, and the program automatically calculated the date to the next one months.