PHP strtotime函数用法、实现原理和源码分析(2)


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和next关键字

与first类似,previous关键字可以与星期,天组合使用,表示指定时间的前一个星期几或前一天。如下所示代码:

复制代码 代码如下:


echo date("Y-m-d H:i:s", strtotime("previous sunday", strtotime("2011-02-01"))), "<br />";


程序会输出:2011-01-30 00:00:00
程序求2011-02-01的前一个星期天。

next关键字与previous相反,它表示下一个星期几或后一天。

4、 last关键字

last关键字既可以作为上一个,也可以作为最后一个。如求上一个星期天的日期:

复制代码 代码如下:


echo date("Y-m-d H:i:s", strtotime("last sunday", strtotime("2011-02-05"))), "<br />";


程序会输出: 2011-01-30 00:00:00

当程序作为最后时,其应用场景是指定日期所在月的最后一天,相当于date(“t”)的结果。如求2000年2月的最后一天:

复制代码 代码如下:


echo date("Y-m-d H:i:s", strtotime("last day", strtotime("2000-02-01"))), "<br />";


first、previous、last和this关键字在re文件中属于同一组。

5、 back和front关键字

这两个关键字是对一天中的小时的向前和向后操作,其调用格式如下:

复制代码 代码如下:


echo date("Y-m-d H:i:s", strtotime("back of 24", strtotime("2011-02-01"))), "<br />";
echo date("Y-m-d H:i:s", strtotime("front of 24", strtotime("2011-02-01"))), "<br />";


back表示将时间设置指定小时值的后一个小时的15分的位置。如果是24点,则算到第二天的0点15分。
front表示将时间设置指定小时值的前一个小时的45分的位置。如果是0点,则算前一天的23点45分。
上面的代码输出:2011-02-02 00:15:00 2011-02-01 23:45:00。 其中back of和front of后接的数组必须大于等于0并且小于等于24。

strtotime函数的实现基本原理
官方文档对于strtotime函数的说明是这样的:本函数预期接受一个包含美国英语日期格式的字符串并尝试将其解析为 Unix 时间戳 (自 January 1 1970 00:00:00 GMT 起的秒数),其值相对于 now 参数给出的时间,如果没有提供此参数则用系统当前时间。

这是一个标准PHP内置函数,从PHP4起就已经存在。strtotime函数是以一个扩展的方式加载进来的,在ext/date目录下有其全部实现。 作为一个标准的内置函数,其定义格式也是标准的,如下:

复制代码 代码如下:


PHP_FUNCTION(strtotime)
    //  处理输入,对于是否有第二个参数有没的处理

//  调用相关函数,实现字符串的解析和结果计算

//  返回结果
}


在输入处理中,先识别两个参数都存在的情况并进行处理,如果不是此种状态,则处理第二个参数不存在的情况, 如果都没有,则报错,返回FALSE。

strtotime函数的第一个参数是一个字符串,对于这个字符串,由于其复杂性,PHP使用了其词法解析一样的工具:re2c。在/ext/date/lib目录下,从parse_date.re文件我们可以看到其原始的re文件。 当用户以参数的形式传入一个字符串,此字符串将交给此程序处理,针对其字符串的不同,匹配不同的处理函数。 如strtotime(“yesterday”)调用,分析字符串时,将匹配yesterday字符串,此字符串对应函数如下:

复制代码 代码如下:


'yesterday'
{
    DEBUG_OUTPUT("yesterday");
    TIMELIB_INIT;
    TIMELIB_HAVE_RELATIVE();
    TIMELIB_UNHAVE_TIME();

s->time->relative.d = -1;
    TIMELIB_DEINIT;
    return TIMELIB_RELATIVE;
}


这里有几个关键的结构体:

复制代码 代码如下:


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;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/5c4c9da180586cca461acbd7b54929e6.html