日期和时间函数依赖于服务器的时间设置,服务器的时间设置默认是格林威治时间(零时区时间)。如果不特意设置时间为特定时区时间,那么通过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")
。时间戳是一个字符序列,是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数。
time()
函数该函数返回从Unix纪元(格林威治时间1970年1月1日00:00:00)到当前时间的秒数。
time(void):int
【示例】
$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,将返回一个浮点数。
【示例】
// 不设置任何参数,则默认获得msce sec格式字符串
echo microtime();
echo "
";
// 设置参数为true,返回一个浮点数
echo microtime(true);
?>
程序输出结果:
0.31818200 1583335900
1583335900.3182
getdate()
函数该函数返回一个根据timestamp
得出的包含有日期信息的关联数组array
。如果没有给出时间戳则认为是当前本地时间(此时和time()
函数值相同)。
getdate([int $timestamp=time()]):array
【示例】
// 获取当前日期时间数组
$today = getdate();
echo ""
;
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() |
如果格式字符串中有不能识别的字符将原样显示。
【示例】
// 设定要用的时区
date_default_timezone_set("PRC");
// 输出类似Monday
echo date("l");
echo "
";
// 输出类似Thursday 05th of March 2020 01:03:57 AM
echo date('l dS \of F Y h:i:s A');
echo "
";
// 输出March 5, 2020 is on a Thursday
echo "March 5, 2020 is on a ".date("l");
echo "
";
/* 在格式参数中使用常量 */
//输出类似Thu, 05 Mar 2020 01:03:57 +0800
echo date(DATE_RFC2822);
echo "
";
// 输出类似2020-03-05T01:03:57+08:00
echo date(DATE_ATOM);
echo "
";
// 输出类似2020-03-05 01:03:57
echo date('Y-m-d H:i:s');
?>
程序输出结果:
计算日期的时间差需要先把两个日期转换成时间戳再计算。
【示例】
// 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
参数给出的时间,如果没有提供此参数则用系统当前时间。
【示例】
echo strtotime("now"),"
";
echo strtotime("10 September 2020"), "
";
echo strtotime("+1 day"), "
";
echo strtotime("+1 week"), "
";
echo strtotime("+1 week 2 days 4 hours 2 seconds"), "
";
echo strtotime("next Thursday"), "
";
echo strtotime("last Monday"), "
";
?>
程序输出结果:
可以使用strtotime()
来计算一些日期时间间隔。
【示例】
$start = 'last Monday';
$interval = strtotime("$start + 4 days");
echo "现在\$interval 表示上周的". date("l", $interval);
?>
程序输出结果:
现在$interval 表示上周的Friday
如果日期使用时间戳表示,并且时间间隔也可以用秒来表示,就可以从时间戳中减去时间间隔。
【示例】
$start = time();
echo "现在是:" . date('Y-m-d', $start);
$interval = 7 * 24 * 3600; // 一周
$end = $start - $interval;
echo "
";
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") | — |
%% | 文字上的百分字符("%") | — |
【示例】
// 设置时区
date_default_timezone_set("PRC");
// 打印格式化日期时间
echo(strftime("%b %d %Y %X", mktime(20,0,0,3,6,20)));
echo("
");
// 打印格式化的格林威治日期时间
echo(gmstrftime("%b %d %Y %X", mktime(20,0,0,3,6,20)));
echo("
");
// 打印当前日期、时间和时区
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编译) |
【示例】
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
该函数检查由参数构成的日期的合法性,如果每个参数都正确定义了则会被认为是有效的。
参数:
返回值:
如果给出的日期是有效的则返回TRUE,否则返回FALSE。
【示例】
var_dump(checkdate(1, 31, 2020));
var_dump(checkdate(2, 30, 2020));
?>
程序输出结果:
bool(true) bool(false)
日期和时间在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');