首頁 後端開發 php教程 php 深入理解strtotime函数的使用详解_PHP教程

php 深入理解strtotime函数的使用详解_PHP教程

Jul 21, 2016 pm 03:10 PM
php strtotime 使用 函數 如何 深入 理解 計算 詳解

在前面的一文中, 我们提到strtotime函数在使用strtotime(”-1 month”)求上一个月的今天时会出一些状况,
因此也引出写这篇文章,本文包括如下内容:
•strtotime函数的一些用法
•strtotime函数的实现基本原理
•strtotime(”-1 month”)求值失败的原因
strtotime函数的一些用法
1、 strtotime(”JAN”)和strtotime(”January”)
这两个用法的效果是一样的,都是返回指定月份的今天,如果指定月份没有今天,则顺延到下一个月。 如在2011-03-31计算二月,代码:

复制代码 代码如下:

echo date("Y-m-d H:i:s", strtotime("feb", strtotime("2011-03-31")));

程序会输出: 2011-03-03 00:00:00。 从表象来看,这个结果也许不一定是我们想要的,但是这也算是一种解决方案,这种方案是由什么决定的呢? strtotime函数在执行月份的计算时只计算了月份,相当于直接将月份设置为指定的月份的值,而如jan,january都会有一个对应内部数值。
2、 first关键字
first是一个辅助型的关键字,它可以与星期,天等可以指定确认值的关键字组合使用,如求2011年的第一个星期天:
复制代码 代码如下:

echo date("Y-m-d H:i:s", strtotime("second sunday", strtotime("2011-01-01"))), "
"; 

在PHP的源码中,对于first与星期和天的组合使用是分开的,即first day对应一个处理操作, 在最终的C实现中,天的值指定为1,即time结构中的d字段指定为1,如下代码:
复制代码 代码如下:

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"))), "
"; 

程序会输出: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"))), "
"; 

程序会输出: 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"))), "
"; 

first、previous、last和this关键字在re文件中属于同一组。
5、 back和front关键字
这两个关键字是对一天中的小时的向前和向后操作,其调用格式如下:
复制代码 代码如下:

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

•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; 
     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; 
     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* be 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;

strtotime(”-1 month”)求值失败的原因
虽然strtotime(”-1 month”)这种方法对于后一个月比前一个月的天数的情况会求值失败,但是从其本质上来说,这并没有错。 PHP这样实现也无可厚非。只是我们的需求决定了我们不能使用这种方法,因此我们称其为求值失败。
我们来看它的实现过程,由于没有第二个参数,所以程序使用默认的当前时间。 第一个参数传入的是-1 month字符串,这个字符串所对应的re文件中的正则为:
复制代码 代码如下:

reltextunit = (('sec'|'second'|'min'|'minute'|'hour'|'day'|'fortnight'|'forthnight'|'month'|'year') 's'?) | 'weeks' | daytext; 
relnumber = ([+-]*[ /t]*[0-9]+); 
relative = relnumber space? (reltextunit | 'week' ); 

最终relative会对应一系列操作,程序会识别出前面的-1 和后面的month字符串,month对应一种操作类型:TIMELIB_MONTH 。 在此之后,根据识别出来的数字和操作类型执行操作,如下代码:
复制代码 代码如下:

case TIMELIB_MONTH:  s->time->relative.m += amount * relunit->multiplier; break; 

如上代码,则是直接记录月份的相对值减一。 但是对于类似于3月31号这样的情况,2月没有31号,程序会自动将日期计算到下一个月。

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/327115.htmlTechArticle在前面的 如何使用PHP计算上一个月的今天 一文中, 我们提到strtotime函数在使用strtotime(”-1 month”)求上一个月的今天时会出一些状况, 因此...
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

討論 CakePHP 討論 CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP 是 PHP 的開源框架。它旨在使應用程式的開發、部署和維護變得更加容易。 CakePHP 基於類似 MVC 的架構,功能強大且易於掌握。模型、視圖和控制器 gu

CakePHP 檔案上傳 CakePHP 檔案上傳 Sep 10, 2024 pm 05:27 PM

為了進行文件上傳,我們將使用表單助理。這是文件上傳的範例。

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

CakePHP 快速指南 CakePHP 快速指南 Sep 10, 2024 pm 05:27 PM

CakePHP 是一個開源MVC 框架。它使應用程式的開發、部署和維護變得更加容易。 CakePHP 有許多函式庫可以減少大多數常見任務的過載。

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

See all articles