·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> php网站开发 >> php--常用的时间处理函数

php--常用的时间处理函数

作者:佚名      php网站开发编辑:admin      更新时间:2022-07-23
php--常用的时间处理函数

天地四方曰宇,往古来今曰宙

时间是世界的重要组成部分,不论花开花落,还是云卷云舒都有它的影子。

但它源起何处?又将去向何方?没人知道答案,也不需要答案,我们需要的只是一个相对的起点来标识时间,现今世界普遍采用公元纪年法来表示。

公元纪年法以耶稣诞生日记为公元1年(没有公元0年),中国处于汉平帝刘衎(不会读。。。)登基第二年即元始元年。

关于时间的另一个概念是unix时间戳,是从1970年1月1日开始所经过的秒数,不考虑闰秒,什么是闰秒参考这里。

下面就来说说php中时间的处理方法,以获取当前时间为例

1 <?php2     date_default_timezone_set('Asia/Shanghai');3     echo "now is ".date("Y-m-d H:i:s",time())."\n";4     echo "now is ".date("Y-m-d H:i:s",strtotime("now"))."\n";5     $date = new DateTime();6     echo "now is ".$date->format("Y-m-d H:i:s")."\n";7 ?>

时区设置

date_default_timezone_set用于设置时区,优先级别高于php.ini中设置的date.timezone属性,可设置的时区列表见这里,与之对应的是date_default_timezone_get获取由set函数设置的时区。

1 <?php2     date_default_timezone_set('Asia/Shanghai');3     $date_set = date_default_timezone_get();4     //如果与配置文件中的时区设置相同则设置为美国时区5     if($date_set == ini_get("date.timezone")){6         date_default_timezone_set('America/Los_Angeles');7     }8     echo date("Y-m-d H:i:s")."\n";9 ?>
获取UNIX时间戳

常用的方法有三种:time(),microtime(),strotime("now")

1 <?php2     error_reporting(E_ALL ^E_STRICT);3     echo "time is ".time()."\n";4     echo "strotime is ".strtotime("now")."\n";5     echo "mktime is ".mktime()."\n";6     echo "microtime is ".microtime()."\n";7     //参数设置为true返回浮点数表示的时间戳8     echo "in float microtime is ".microtime(true)."\n";9 ?>

mktime

mktime函数的参数全是关键字参数,关键字参数大家懂的可以从右到左省略,格式为时,分,秒,月,日,年

 1 <?php 2  3     //年默认2014 4     echo "mktime(10,10,10,10,12) is ".date("Y-m-d H:i:s",mktime(10,10,10,10,12))."\n"; 5  6     //这种写法会将2014当作月数,年还是默认的2014年 7     echo "mktime(10,10,10,10,2014) is ".date("Y-m-d H:i:s",mktime(10,10,10,10,2014))."\n"; 8  9     echo "mktime(10,10,10,10,32,2014) is ".date("Y-m-d H:i:s",mktime(10,10,10,10,32,2014))."\n";10 ?>

出现了一些很奇妙的事情,2014年2014月变成了2020年4月,2014年10月32号变成了11月1号,看,mktime自动计算了相差部分。乍看之下感觉很神奇,细想下来又在情理之中,毕竟日期的相互转换是通过unix时间戳进行的,我们可以通过mktime的实现源码管中窥豹一下。

该函数源码位于ext/date/php_date.c 在1500行实现,篇幅所限只贴部分代码,兴趣的朋友可以下下来自己看,地址在这里.

 1 PHPAPI void php_mktime(INTERNAL_FUNCTION_PARAMETERS, int gmt) 2 { 3     zend_long hou = 0, min = 0, sec = 0, mon = 0, day = 0, yea = 0, dst = -1; 4     timelib_time *now; 5     timelib_tzinfo *tzi = NULL; 6     zend_long ts, adjust_seconds = 0; 7     int error; 8  9     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lllllll", &hou, &min, &sec, &mon, &day, &yea, &dst) == FAILURE) {10         RETURN_FALSE;11     }12     /* Initialize structure with current time */13     now = timelib_time_ctor();14     if (gmt) {15         timelib_unixtime2gmt(now, (timelib_sll) time(NULL));16     } else {17         tzi = get_timezone_info(TSRMLS_C);18         now->tz_info = tzi;19         now->zone_type = TIMELIB_ZONETYPE_ID;20         timelib_unixtime2local(now, (timelib_sll) time(NULL));21     }22     /* Fill in the new data */23     switch (ZEND_NUM_ARGS()) {24         case 7:25             /* break intentionally missing */26         case 6:27             if (yea >= 0 && yea < 70) {28                 yea += 2000;29             } else if (yea >= 70 && yea <= 100) {30                 yea += 1900;31             }32             now->y = yea;33             /* break intentionally missing again */34         case 5:35             now->d = day;36             /* break missing intentionally here too */37         case 4:38             now->m = mon;39             /* and here */40         case 3:41             now->s = sec;42             /* yup, this break isn't here on purpose too */43         case 2:44             now->i = min;45             /* last intentionally missing break */46         case 1:47             now->h = hou;48             break;49         default:50             php_error_docref(NULL TSRMLS_CC, E_STRICT, "You should be using the time() function instead");51     }52     /* Update the timestamp */53     if (gmt) {54         timelib_update_ts(now, NULL);55     } else {56         timelib_update_ts(now, tzi);57     }58     /* Support for the dePRecated is_dst parameter */59     if (dst != -1) {60         php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "The is_dst parameter is deprecated");61         if (gmt) {62             /* GMT never uses DST */63             if (dst == 1) {64                 adjust_seconds = -3600;65             }66         } else {67             /* Figure out is_dst for current TS */68             timelib_time_offset *tmp_offset;69             tmp_offset = timelib_get_time_zone_info(now->sse, tzi);70             if (dst == 1 && tmp_offset->is_dst == 0) {71                 adjust_seconds = -3600;72             }73             if (dst == 0 && tmp_offset->is_dst == 1) {74                 adjust_seconds = +3600;75             }76             timelib_time_offset_dtor(tmp_offset);77         }78     }79     /* Clean up and return */80     ts = timelib_date_to_int(now, &error);81     ts += adjust_seconds;82     timelib_time_dtor(now);83 84     if (error) {85         RETURN_FALSE;86     } else {87         RETURN_LONG(ts);88     }89 }
View Code

阅读这段代码需知道一个重要的结构体timelib_time,在ext/date/lib/timelib_structs.h中声明

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 are up to date with the sse member */    unsigned int   is_localtime; /*  1 if the current struct represents localtime, 0 if it is in GMT */    unsigned int   zone_type;    /*  1 time offset,                                  *  3 TimeZone identifier,                                  *  2 TimeZone abbreviation */} timelib_time;

现在来看看mktime,56行的timelib_update_ts函数位于ext/date/lib/tm2unixtime.c文件中,其作用是根据now中的日期信息计算相应的秒数并存入now->sse,来看看

 1 void timelib_update_ts(timelib_time* time, timelib_tzinfo* tzi) 2 { 3     timelib_sll res = 0; 4  5     do_adjust_special_early(time); 6     do_adjust_relative(time); 7     do_adjust_special(time); 8     res += do_years(time->y); 9     res += do_months(time->m, time->y);10     res += do_days(time->d);11     res += do_time(time->h, time->i, time->s);12     time->sse = res;13 14     res += do_adjust_timezone(time, tzi);15     time->sse = res;16 17     time->sse_uptodate = 1;18     time->have_relative = time->relative.have_weekday_relative = time->relative.have_special_relative = 0;19 }

8-11行计算相应时间类型的秒数,到这里已可了解mktime自动增减日期的原理,让我们看看do_days是如何实现的。day-1应该不难理解,mktime前面需要传入小时分钟等参数,在处理具体的某一天时默认为当天的0点0分0秒,所以要比实际的天数少一天。do_months,do_years等机制都相同,不再细述。

static timelib_sll do_days(timelib_ull day){    return ((day - 1) * SECS_PER_DAY);}

当日期处理完成,我们回到php_date.c,在80行处通过timelib_date_to_int函数将now->sse返回,该函数位于ext/date/lib/timelib.c,具体的代码就不贴了。

strto