PHP strtotime function usage, implementation principle and source code analysis _php Skills

Source: Internet
Author: User
Tags current time echo date php source code

SOURCE Location: \ext\date\php_date.c

Copy 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);
}
}
/* }}} */


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:

1). Some usages of strtotime function
2). Principle of realization of strtotime function
3). 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:

Copy 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. 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:

Copy Code code as follows:

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:
Copy Code code as follows:

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:

Copy Code code as follows:

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:

Copy Code code as follows:

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:

Copy Code code as follows:

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:

Copy Code code 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 now parameter The time out, 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:

Copy Code code 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:

Copy 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 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 are up to date with the Date/time memb ERS */
    unsigned int   tim_uptodate;/*!0 If the date/time members are up to date with th E SSE member */
    unsigned int   is_localtime/*  1 If the current struct represents LocalTime, 0 if it is in GMT */
    unsigned int   zone_type;   /*  1 ti Me 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-&GT;TIME-&GT;RELATIVE.D =-1 means that the relative days of the current time are-1. This is only the intermediate result of intermediate lexical parsing, but the final result is computed through these intermediate results.

Strtotime ("-1 month") The reason for the evaluation failure

Although Strtotime ("-1 Month") This method fails for the last one months compared to the number of days in the first 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, because there is no second argument, so the program uses the default current time. The first argument passes in a -1 month string, and the regular in the re file corresponding to this string is:

Copy 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 operations, the program will recognize the preceding-1 and subsequent MONTH strings, MONTH corresponding to one type of operation: Timelib_month. After that, the following code is executed based on the number and type of action identified:
Copy Code code as follows:

Case TIMELIB_MONTH:S->TIME->RELATIVE.M + = Amount * relunit->multiplier; Break

As the code above, it is the direct record of the month relative value 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.

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.