当前位置:  编程技术>php

php日期字符串比较实例

    来源: 互联网  发布时间:2014-08-30

    本文导语:  项目中有个功能是比较会员是否过期,review同事的代码,发现其写法比较奇葩,但线上竟也未出现bug。 实现:   代码示例: $expireTime = "2014-05-01 00:00:00"; $currentTime = date('Y-m-d H:i:s', time());   if($currentTime < $expireTime) {     return...

项目中有个功能是比较会员是否过期,review同事的代码,发现其写法比较奇葩,但线上竟也未出现bug。

实现:
 

代码示例:
$expireTime = "2014-05-01 00:00:00";
$currentTime = date('Y-m-d H:i:s', time());
 
if($currentTime < $expireTime) {
    return false;
} else {
    return true;
}

如果两个时间需要进行比较,通常是转换成unix时间戳,用两个int型的数字进行比较。该实现却特意将时间表示成string,然后对两个string进行比较运算。

撇开写法不谈,我很好奇的是php内部是如何进行比较的。

闲话少说,还是从源码开始跟踪。

编译期
在zend_language_parse.y中可以发现类似下述语法:
 

代码示例:
expr === expr    { zend_do_binary_op(ZEND_IS_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
expr !== expr    { zend_do_binary_op(ZEND_IS_NOT_IDENTICAL, &$$, &$1, &$3 TSRMLS_CC); }
expr ==  expr    { zend_do_binary_op(ZEND_IS_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
expr !=  expr    { zend_do_binary_op(ZEND_IS_NOT_EQUAL, &$$, &$1, &$3 TSRMLS_CC); }
expr =  expr    { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); }

很明显,此处编译成opcode用的便是zend_do_binary_op。
 

代码示例:
void zend_do_binary_op(zend_uchar op, znode *result, const znode *op1, const znode *op2 TSRMLS_DC) /* {{{ */
{
    zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
    opline->opcode = op;
    opline->result.op_type = IS_TMP_VAR;
    opline->result.u.var = get_temporary_variable(CG(active_op_array));
    opline->op1 = *op1;
    opline->op2 = *op2;
    *result = opline->result;
}
 

该函数并没有做什么特别的处理,仅仅是简单保存了opcode、操作数1和操作数2。

执行期
根据opcode,跳转到相应的处理函数:ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER。
 

代码示例:
static int ZEND_FASTCALL  ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
    zend_op *opline = EX(opline);
 
    zval *result = &EX_T(opline->result.u.var).tmp_var;
 
    compare_function(result,
        &opline->op1.u.constant,
        &opline->op2.u.constant TSRMLS_CC);
    ZVAL_BOOL(result, (Z_LVAL_P(result) < 0));
 
 
    ZEND_VM_NEXT_OPCODE();
}
 

注意到,两个zval的比较是利用compare_function来处理。
 

代码示例:
ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */
{
    int ret;
    int converted = 0;
    zval op1_copy, op2_copy;
    zval *op_free;
 
    while (1) {
        switch (TYPE_PAIR(Z_TYPE_P(op1), Z_TYPE_P(op2))) {
            case TYPE_PAIR(IS_LONG, IS_LONG):
                ...
            case TYPE_PAIR(IS_DOUBLE, IS_LONG):
                ...
            case TYPE_PAIR(IS_DOUBLE, IS_DOUBLE):
                ...
            ...
            // 两个字符串进行比较
            case TYPE_PAIR(IS_STRING, IS_STRING):
                zendi_smart_strcmp(result, op1, op2);
                return SUCCESS;
            ...
        }
    }
}
 

该函数例举了若干种情况,根据本文case,进入zendi_smart_strcmp一窥究竟:
 

代码示例:
ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */
{
    int ret1, ret2;
    long lval1, lval2;
    double dval1, dval2;
 
    // 尝试将字符串转成数字类型
    if ((ret1=is_numeric_string(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0)) &&
        (ret2=is_numeric_string(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0))) {
        // 进行数字之间的比较
        ...
    } else {
        // 无法全部转成数字
        // 则调用zend_binary_zval_strcmp
        // 本质为memcmp的一层封装
        Z_LVAL_P(result) = zend_binary_zval_strcmp(s1, s2);
        ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result)));
    }
}
 

那么“2014-05-01 00:00:00”能否转化成数字么?

还是得看下is_numeric_string的实现规则。
 

代码示例:
static inline zend_uchar is_numeric_string(const char *str, int length, long *lval, double *dval, int allow_errors)
{
    const char *ptr;
    int base = 10, digits = 0, dp_or_e = 0;
    double local_dval;
    zend_uchar type;
 
    if (!length) {
        return 0;
    }
 
    /* trim掉字符串开头的空白部分 */
    while (*str == ' ' || *str == 't' || *str == 'n' || *str == 'r' || *str == 'v' || *str == 'f') {
        str++;
        length--;
    }
    ptr = str;
 
    if (*ptr == '-' || *ptr == '+') {
        ptr++;
    }
 
    if (ZEND_IS_DIGIT(*ptr)) {
        /* 判断是否为16进制    */
        if (length > 2 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) {
            base = 16;
            ptr += 2;
        }
 
        /* 忽略后续的若干0 */
        while (*ptr == '0') {
            ptr++;
        }
 
        /* 计算数字的位数,并决定是整型还是浮点 */
        for (type = IS_LONG; !(digits >= MAX_LENGTH_OF_LONG && (dval || allow_errors == 1)); digits++, ptr++) {
check_digits:
            if (ZEND_IS_DIGIT(*ptr) || (base == 16 && ZEND_IS_XDIGIT(*ptr))) {
                continue;
            } else if (base == 10) {
                if (*ptr == '.' && dp_or_e < 1) {
                    goto process_double;
                } else if ((*ptr == 'e' || *ptr == 'E') && dp_or_e < 2) {
                    const char *e = ptr + 1;
 
                    if (*e == '-' || *e == '+') {
                        ptr = e++;
                    }
                    if (ZEND_IS_DIGIT(*e)) {
                        goto process_double;
                    }
                }
            }
 
            break;
        }
 
        if (base == 10) {
            if (digits >= MAX_LENGTH_OF_LONG) {
                dp_or_e = -1;
                goto process_double;
            }
        } else if (!(digits < SIZEOF_LONG * 2 || (digits == SIZEOF_LONG * 2 && ptr[-digits]

    
 
 

您可能感兴趣的文章:

  • php将标准字符串格式时间转换成unix时间戳_strtotime
  • php判断字符串是否存在 php字符串检测代码
  • php使用strip_tags从字符串中去除html标记
  • php逐字拆分字符串 php字符串拆分实例
  • php将html特殊字符转换成html字符串的函数:htmlspecialchars()介绍及代码举例
  • php如何截取字符串后四位
  • php将unix时间戳转换成字符串时间函数(date)
  • php判断字符串在另一个字符串位置的方法
  • php生成指定位数(长度)的随机字符串
  • php二维数组转换为字符串示例
  • php截取字符串(无乱码 utf8)
  • php压缩函数(gzcompress gzuncompress)压缩字符串
  • php 判断字符串是否包含html标签
  • php通过数组实现多条件查询实现方法(字符串分割)
  • php字符串分割函数explode实例
  • php判断字符与字符串的包含方法属性
  • php如何判断字符串是否存在
  • PHP生成自定义长度随机字符串的函数分享
  • php字符串查找 查找字符最后一次出现位置
  • php查找字符串中http地址
  • php中文字符串截取函数示例
  • php像数组一样存取和修改字符串字符
  • PHP中比较两个字符串找出第一个不同字符位置例子
  • Solaris、Apache和Php字符集问题
  • PHP获取一个字符串中间一部分字符的方法
  • php正则表达式转义字符的例子
  • PHP替换字符串(只替换首个字符串)
  • php mysql转义特殊字符函数
  • php特殊字符转义函数
  • php表单提交特殊字符过滤方法
  • php mysql转义特殊字符的函数有哪些?
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • php session_id()函数介绍及代码实例
  • php 小数点取法实例总结
  • php生成透明背景图片实例
  • php防止sql注入代码实例
  • php解析json数据实例
  • php定界符<<<使用技巧和实例
  • php读取sqlite数据库入门实例
  • PHP文件锁定写入实例解析
  • php读取mysql数据库入门实例
  • php生成excel列序号代码实例
  • php将unix时间戳转换成字符串时间函数(date) iis7站长之家
  • PHP接收二进制流并生成文件(实例)
  • php读取mysql入门实例
  • php根据身份证号码计算年龄的实例代码
  • PHP递归函数返回值使用实例
  • php实例分享之html转为rtf格式
  • php文件锁定写入实例教程
  • PHP创建桌面快捷方式的实例代码
  • php 强制下载文件实例代码
  • php mailto配置实例
  • php如何判断图片颜色类型?实例教程
  • 修改配置真正解决php文件上传大小限制问题(nginx+php)
  • IIS7配置PHP图解(IIS7+PHP_5.2.17/PHP_5.3.5)
  • PHP 5.4.19 和 PHP 5.5.3 发布及下载地址
  • php输入流php://input使用示例(php发送图片流到服务器)
  • 修改配置真正解决php文件上传大小限制问题(apache+php)
  • PHP转换器 HipHop for PHP
  • PHP去除html标签,php标记及css样式代码参考
  • PHP 框架 Pop php
  • PHP 'ext/soap/php_xml.c'不完整修复存在多个任意文件泄露漏洞
  • PHP的JavaScript框架 PHP.JS




  • 特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3