文章目錄
日期和時間信息在PHP內部都是以64位數字存儲的,它可以覆蓋當前時間前後2920億年的時間,這個範圍之廣,足以滿足現有應用的實際需要。
時區設置
日期和時間函數依賴於服務器的時間設置,服務器的時間設置默認是格林威治時間(零時區時間)。如果不特意設置時間爲特定時區時間,那麼通過PHP有關函數獲取到的時間爲零時區的時間,比北京時間少8個小時。
時區劃分
時區的劃分是一個地理概念。從本初子午線開始向東和向西各有12個時區。北京時間是東八區,美國太平洋時間是西八區。
時區設置
時區設置方法主要有以下兩種
- 修改
php.ini
文件的設置。找到";date.timezone="
選項,將其值修改爲"date.timezone = Asia/Hong_kong"
,這樣系統默認時間爲東八區的時間。或者可以設置date.timezone=PRC
,設置完成後,保存配置文件並重啓服務器即可生效。 - 在應用程序中使用函數
date_default_timezone_set()
函數,把時區設置爲date_default_timezone_set("Asia/Hong_Kong")
。
PHP7日期和時間函數
關於UNIX時間戳
時間戳是一個字符序列,是指格林威治時間1970年01月01日00時00分00秒(北京時間1970年01月01日08時00分00秒)起至現在的總毫秒數。
獲取當前日期和時間
time()
函數
該函數返回從Unix紀元(格林威治時間1970年1月1日00:00:00)到當前時間的秒數。
time(void):int
【示例】
<?php
$t1 = time(); // 獲取當前時間戳
echo "當前時間戳爲:" . $t1; // 輸出當前時間戳
?>
程序輸出結果:
當前時間戳爲:1583334387
類似的函數還有gmmktime()
、mktime()
。
mktime([ int $hour = date("H")[, int $minute = date("i")[, int $second = date("s")[, int $month = date("n")[, int $day = date("j")[, int $year = date("Y")[, int $is_dst = -1]]]]]]] ) : int
根據給出的參數返回 Unix 時間戳,如果參數非法,本函數返回FALSE
。時間戳是一個長整數,包含了從 Unix 紀元到給定時間的秒數。參數可以從右向左省略,任何省略的參數會被設置成本地日期和時間的當前值。
gmmktime()
與mktime()
完全一樣,只除了返回值是格林威治標準時的時間戳。
microtime()
函數
該函數返回當前Unix時間戳以及微秒數。該函數僅在支持gettimeofday()
系統調用的操作系統下可用。
microtime([bool $get_as_float]):mixed
如果調用時不帶可選參數,本函數以"msec sec"
格式返回一個字符串,其中sec
是自Unix紀元起到現在的描述,msec
是微秒部分。字符串的兩部分都是以秒爲單位返回的。如果給出了get_as_float
參數並且其值等價於TRUE,將返回一個浮點數。
【示例】
<?php
// 不設置任何參數,則默認獲得msce sec格式字符串
echo microtime();
echo "<br />";
// 設置參數爲true,返回一個浮點數
echo microtime(true);
?>
程序輸出結果:
0.31818200 1583335900
1583335900.3182
getdate()
函數
該函數返回一個根據timestamp
得出的包含有日期信息的關聯數組array
。如果沒有給出時間戳則認爲是當前本地時間(此時和time()
函數值相同)。
getdate([int $timestamp=time()]):array
【示例】
<?php
// 獲取當前日期時間數組
$today = getdate();
echo "<pre>";
var_dump($today);
?>
程序輸出結果:
getdate()
函數返回關聯數組鍵名含義:
鍵名 | 說明 | 返回值例子 |
---|---|---|
seconds | 秒的數字表示 | 0到59 |
minutes | 分鐘的數字表示 | 0到59 |
hours | 小時的數字表示 | 0到23 |
mday | 月份中第幾天的數字表示 | 1到31 |
wday | 星期中的第幾天的數字表示 | 0(週日)到6(週六) |
mon | 月份的數字表示 | 1到12 |
year | 4爲數字表示的完整年份 | 如:1999或2020 |
yday | 一年中第幾天的數字表示 | 0到365 |
weekday | 星期幾的完成文本表示 | Monday到Sunday |
month | 月份的完整文本表示 | January到December |
0 | 自從UNIX紀元開始至今的秒數,和time()的返回值以及用於date()的值類似 | 系統相關,典型值爲-2147483648~2147483147 |
常用時間處理方法
格式化時間顯示
可以使用date()函數對獲取的時間進行格式化處理,語法如下:
date(string $format[, int $timestamp]):string
返回將整數timestamp
按照給定的格式字串而產生的字符串。如果沒有給出時間戳則使用本地當前時間。
格式化字符串中可以識別的format
參數如下表:
format字符 | 說明 | 返回值例子 |
---|---|---|
d | 月份中的第幾天,有前導零的2位數字 | 01到31 |
D | 星期中的第幾天,文本表示,3個字母 | Mon到Sun |
月份中的第幾天,沒有前導零 | 1到31 | |
l(L的小寫字母) | 星期幾,完整的文本格式 | Sunday到Saturday |
N | ISO-8601格式數字表示的星期中的第幾天(PHP5.1.0新增) | 1(表示星期一)到7(表示星期天) |
S | 每月天數後面的英文後綴,2個字符 | st,nd,rd或者th。可以和j一起用 |
w(小寫) | 星期中的第幾天,數字表示 | 0(表示星期天)到6(表示星期六) |
z(小寫) | 年份中的第幾天 | 0到365 |
星期 | — | — |
W(大寫) | ISO-8601格式年份中的第幾周,每週從星期一開始(PHP4.1.0新增) | 如:42(當年的第42周) |
月 | — | — |
F | 月份,完整的文本格式 | January到December |
m | 數字表示的月份,有前導零 | 01到12 |
M | 三個字母縮寫小時的月份 | Jan到Dec |
n | 數字表示的月份,沒有前導零 | 1到12 |
t | 指定的月份有幾天 | 28到31 |
年 | — | — |
L | 是否爲閏年 | 如果是閏年爲1,否則爲0 |
o(小寫) | ISO-8601格式年分數字。這和Y的值相同,只除了如果ISO的星期數(W)屬於前一年或下一年,則用那一年。(PHP5.10新增) | 如:1999或2020 |
Y | 4爲數字完整表示的年份 | 如:1999或2020 |
y | 2爲數字表示的年份 | 如:99或20 |
時間 | — | — |
a | 小寫的上午和下午值 | am或pm |
A | 大寫的上午和下午值 | AM或PM |
B | Swatch Internet標準時 | 000到999 |
g | 小時,12小時格式,沒有前導零 | 1到12 |
G | 小時,24小時格式,沒有前導零 | 0到23 |
h | 小時,12小時格式,有前導零 | 01到12 |
H | 小時,24小時格式,有前導零 | 00到23 |
i | 有前導零的分鐘數 | 00到59> |
s | 秒數,有前導零 | 00到59> |
u | 毫秒(PHP5.2.2新增)。需要注意的是date()函數總是返回000000因爲它只接受integer參數,而DateTime::format()才支持毫秒 | 如:654321 |
時區 | — | — |
e | 時區標識(PHP5.1.0)新增 | 如:UTC,GMT,Atlantic/Azores |
I(大寫) | 是否爲夏令時 | 如果是夏令時爲1,否則爲0 |
O(大寫) | 與格林威治時間相差的小時數 | 如:+0200 |
P | 與格林威治時間(GMT)的差別,小時和分鐘之間有冒號分隔(PHP5.1.3新增) | 如:+02:00 |
T | 本機所在的時區 | 如:EST,MDT |
Z | 時差偏移量的秒數。UTC西邊的時區偏移量總是負的,UTC東邊的時區偏移量總是正的。 | -43200到43200 |
完整的日期 | — | — |
c(小寫) | ISO 8601格式的日期(PHP5新增) | 2004-02-12T15:19:21+00:00 |
r | RFC 822格式的日期 | 如:Thu,21 Dec 2000 16:01:07+0200 |
U(大寫) | 從Unix紀元開始至今的秒數 | 同time() |
如果格式字符串中有不能識別的字符將原樣顯示。
【示例】
<?php
// 設定要用的時區
date_default_timezone_set("PRC");
// 輸出類似Monday
echo date("l");
echo "<br />";
// 輸出類似Thursday 05th of March 2020 01:03:57 AM
echo date('l dS \of F Y h:i:s A');
echo "<br />";
// 輸出March 5, 2020 is on a Thursday
echo "March 5, 2020 is on a ".date("l");
echo "<br />";
/* 在格式參數中使用常量 */
//輸出類似Thu, 05 Mar 2020 01:03:57 +0800
echo date(DATE_RFC2822);
echo "<br />";
// 輸出類似2020-03-05T01:03:57+08:00
echo date(DATE_ATOM);
echo "<br />";
// 輸出類似2020-03-05 01:03:57
echo date('Y-m-d H:i:s');
?>
程序輸出結果:
計算兩個日期間的時間差
計算日期的時間差需要先把兩個日期轉換成時間戳再計算。
【示例】
<?php
// 2020年1月1日19點30分0秒
$start = mktime(19, 30, 0, 1, 1, 2020);
// 2020年3月5日7點30分0秒
$end = mktime(7, 30, 0, 3, 5, 2020);
$diff_seconds = $end - $start;
// 一週的秒數是7*24*60*60=604800秒
$diff_weeks = floor($diff_seconds / 604800);
// 一天的秒數是24*60*60=86400秒
$diff_days = floor($diff_seconds / (24*60*60));
$diff_hours = floor($diff_seconds / (60*60));
$diff_minutes = floor($diff_seconds / 60);
echo "2020年1月1日19點30分0秒和2020年3月5日7點30分0秒之間相差$diff_seconds 秒,$diff_weeks 個星期,$diff_days 天,$diff_hours 小時,$diff_minutes 分鐘";
?>
程序輸出結果:
2020年1月1日19點30分0秒和2020年3月5日7點30分0秒之間相差5486400 秒,9 個星期,63 天,1524 小時,91440 分鐘
從字符串中解析日期和時間
在PHP中可以使用strtotime()
函數將任何英文文本的日期描述解析爲UNIX時間戳,語法如下:
strtotime(string $time[, int $now=time()]):int
該函數預期接受一個包含美國英語日期格式的字符串並嘗試將其解析爲 Unix 時間戳,其值相對於 now
參數給出的時間,如果沒有提供此參數則用系統當前時間。
【示例】
<?php
echo strtotime("now"),"<br/>";
echo strtotime("10 September 2020"), "<br />";
echo strtotime("+1 day"), "<br />";
echo strtotime("+1 week"), "<br />";
echo strtotime("+1 week 2 days 4 hours 2 seconds"), "<br />";
echo strtotime("next Thursday"), "<br />";
echo strtotime("last Monday"), "<br />";
?>
程序輸出結果:
日期的加減運算
可以使用strtotime()
來計算一些日期時間間隔。
【示例】
<?php
$start = 'last Monday';
$interval = strtotime("$start + 4 days");
echo "現在\$interval 表示上週的". date("l", $interval);
?>
程序輸出結果:
現在$interval 表示上週的Friday
如果日期使用時間戳表示,並且時間間隔也可以用秒來表示,就可以從時間戳中減去時間間隔。
【示例】
<?php
$start = time();
echo "現在是:" . date('Y-m-d', $start);
$interval = 7 * 24 * 3600; // 一週
$end = $start - $interval;
echo "<br />";
echo "上一週的今天是:" . date('Y-m-d', $end);
?>
程序輸出結果:
現在是:2020-03-05
上一週的今天是:2020-02-27
輸出格式化時間戳的日期和時間
可以使用strftime()
把時間戳格式化爲日期和時間,格式如下:
strftime( string $format[, int $timestamp = time()] ) : string
其中,$format
決定了如何把其後面的時間戳格式化並輸出。如果$timestamp
爲空,則使用系統當前時間戳。
format
夠識別的格式字串有以下標記:
格式 | 描述 | 返回值示例 |
---|---|---|
日 | — | — |
%a | 當前區域星期幾的簡寫 | Sun到Sat |
%A | 當前區域星期幾的全稱 | Sunday到Saturday |
%d | 月份中的第幾天,十進制數字 | 01到31 |
%e | 月份中的第幾天,十進制數字,一位的數字錢會加一個空格。 | 1到31 |
%j | 年份中的第幾天,帶前導零的三位十進制數 | 001到366 |
%u | 符合ISO-8601星期幾的十進制數表達[1, 7],1表示星期一 | 1到7 |
%w | 星期中的第幾天,星期天爲0 | 0到6 |
周 | — | — |
%U | 本年的第幾周,從第一週的第一個星期天作爲第一天開始 | 1到13 |
%V | 本年的第幾周的ISO-8601:1988格式 | 01-53 |
%W | 本年的第幾週數,從個第一週的第一個星期一作爲第一天開始 | 1-46 |
月 | — | — |
%b | 當前區域月份的簡寫 | Jan到Dec |
%B | 當前區域月份的全稱 | January到December |
%h | 當前區域月份的簡寫(%b的別名) | Jan到Dec |
%m | 兩位數的月份 | 01-12 |
年 | — | — |
%C | 兩位數顯示世紀(年份除以100,截成整數) | 19是20世紀 |
%g | 2位數的年份,符合ISO-8601:1988星期數(參見%V)。和%V的格式和值一樣,只除了如果ISO星期數屬於前一年或後一年,則使用那一年。 | 如:2009年1月6日那一週是09。 |
%G | %g的完整四位數版本 | 如:2009年1月3日那一週是2008。 |
%y | 兩位數顯示年份 | 如:09是2009,79是1979 |
%Y | 四位數顯示年份 | 比如:2020 |
時間 | — | — |
%H | 以24小時格式顯示兩位小時數 | 00到23 |
%I | 以12小時格式顯示兩位小時數 | 01到12 |
%l(小寫的’L’) | 以12小時格式顯示小時數,單個數字前含空格 | 1到12 |
%M | 兩位的分鐘數 | 00到59 |
%p | 執行時間的謝謝“AM”和“PM” | 如:00:31是AM,22:23是PM |
%P | 指定時間的小寫“am”或“pm” | 如:00:31是am,22:23是pm |
%r | 和"%I:%M:%S %p"一樣 | 如:21:34:17 是 09:34:17 PM |
%R | 和 “%H:%M” 一樣 | 如: 12:35 AM 是 00:35,4:44 PM 是 16:44 |
%S | 兩位數字表示秒 | 00 到 59 |
%T | 和 “%H:%M:%S” 一樣 | 如: 09:34:17 PM 是 21:34:17 |
%X | 前區域首選的時間表示法,不包括日期 | 如: 03:59:16 或 15:59:16 |
%z | 從 UTC 的時區偏移 或 簡寫(由操作系統決定) | 如: 東部時間是 -0500 或 EST |
%Z | %z 沒有給出的 UTC 的時區偏移 或 簡寫(由操作系統決定) | 如: -0500 或 EST 是東部時間 |
時間和日期戳 | — | — |
%c | 當前區域首選的日期時間表達 | 如: 2009 年 2 月 5 日上午 12:45:10 是 Tue Feb 5 00:45:10 2009 |
%D | 和 “%m/%d/%y” 一樣 | 如: 2009 年 2 月 5 日是 02/05/09 |
%F | 和"%Y-%m-%d"一樣(常用於數據庫時間戳) | 如:2009 年 2 月 5 日是 2009-02-05 |
%s | Unix紀元的時間戳(和 time() 函數一樣) | 如: 1979 年 9 月 10 日上午 8 點 40 分 00 秒是 305815200 |
%x | 當前區域首選的時間表示法,不包括時間 | 如: 2009 年 2 月 5 日是 02/05/09 |
其他 | — | — |
%n | 換行符("\n") | — |
%t | Tab 字符("\t") | — |
%% | 文字上的百分字符("%") | — |
【示例】
<?php
// 設置時區
date_default_timezone_set("PRC");
// 打印格式化日期時間
echo(strftime("%b %d %Y %X", mktime(20,0,0,3,6,20)));
echo("<br />");
// 打印格式化的格林威治日期時間
echo(gmstrftime("%b %d %Y %X", mktime(20,0,0,3,6,20)));
echo("<br />");
// 打印當前日期、時間和時區
echo(gmstrftime("it is %a on %b %d, %Y, %X time zone: %Z", time()));
?>
程序運行結果:
Mar 06 2020 20:00:00
Mar 06 2020 12:00:00
it is Thu on Mar 05, 2020, 17:47:13 time zone: 中國標準時間
注意:strftime和gmstrftime中的格式化字符串都不能有中文。
這個函數裏%e修飾符不支持Windows。爲了得到這個值可以用%#d修飾符代替。
%P修飾符不支持Mac OS X
顯示本地化的日期和時間
使用setlocale()
函數配合strftime()
函數可以實現日期時間本地化。
setlocale()
函數格式如下:
setlocale(int $category, string $local[, string $...]):string
setlocale(int $category, array $local):string
其中$local
是一個字符串或數組,字符串值或數組元素值類似於:language_COUNTRY.chareacterset
,如想把本地化設置爲美國,按照此格式爲en_US.utf8
,如果想設爲英國,值爲en_GB.utf8
,中國爲zh_CN.gb2312
或者zh_CN.utf8
,$category
值是指7個不同的本地化目錄,其值如下表所示。
目錄 | 含義 |
---|---|
LC_ALL | 所有的設置 |
LC_COLLATE | 字符串比較 |
LC_CTYPE | 字符串的分類與轉換 |
LC_MONETARY | 貨幣表示規則 |
LC_NUMERIC | 對於小數點的分隔 |
LC_TIME | 時間與格式 |
LC_MESSAGES | 系統響應 (如果PHP使用libintl編譯) |
【示例】
<?php
header("Content-Type: text/html;charset=gb2312");
// 設置時區爲中國時區
date_default_timezone_set("Asia/Hong_Kong");
// 設置時間的本地化顯示方式爲中國
setlocale(LC_TIME, "zh_CN.gb2312");
// 輸出所在的時區
echo strftime("%Z");
程序輸出結果:
中國標準時間
驗證日期
PHP提供了checkdate()
函數來檢驗日期和時間的有效性,其格式如下:
checkdate(int $month, int $day, int $year):bool
該函數檢查由參數構成的日期的合法性,如果每個參數都正確定義了則會被認爲是有效的。
參數:
- month:值是從1到12.
- day:在給定的month所應該具有的天數範圍內,閏年已經考慮進去了。
- year:值是從1到32767
返回值:
如果給出的日期是有效的則返回TRUE,否則返回FALSE。
【示例】
<?php
var_dump(checkdate(1, 31, 2020));
var_dump(checkdate(2, 30, 2020));
?>
程序輸出結果:
bool(true) bool(false)
日期和時間在PHP和MySQL數據格式之間的轉換
日期和時間在MySQL中是按照ISO8601格式存儲的。這種格式要求以年份打頭,如2020-03-06。從MySQL讀取的默認格式也是這種格式。國人會對這種格式比較熟悉,但是,西方的表達方法中經常把年份放在月份和日期的後面,如March 08, 2020。所以,在接觸到國際,特別是符合英語使用習慣的項目時,需要把ISO8601格式的日期和時間加以覈實的轉換。
MySQL提供了把日期和時間轉換爲符合ISO8601標準的兩個函數,DATE_FORMAT()
和UNIX_TIMESTAMP()
。
【MySQL示例】
// 獲取當前時間
SELECT NOW(); // 2020/3/6 14:22:51
// 時間日期格式轉換成時間戳格式
SELECT UNIX_TIMESTAMP(NOW()); // 1539238930
// 時間戳格式轉換成時間日期格式
SELECT FROM_UNIXTIME(1539238971);
// 將當前時間轉換爲不同格式的字符串
SELECT DATE_FORMAT(NOW(),'%b %d %Y %h:%i %p')
SELECT DATE_FORMAT(NOW(),'%m-%d-%Y')
SELECT DATE_FORMAT(NOW(),'%d %b %y')
SELECT DATE_FORMAT(NOW(),'%d %b %Y %T:%f')
【PHP示例】
// 獲取當前時間戳
time();
// 時間戳格式轉換成時間日期格式
date('Y-m-d H:i:s', time());
// 時間日期格式轉換成時間戳格式
strtotime('2020-03-05 14:24:06');