首页 >后端开发 >php教程 >在PHP和MySQL中与日期和时间合作

在PHP和MySQL中与日期和时间合作

Jennifer Aniston
Jennifer Aniston原创
2025-02-28 09:22:30765浏览

Working with Dates and Times in PHP and MySQL

在任何编程语言中处理日期和时间通常是一项简单琐碎的任务,直到需要支持时区。幸运的是,PHP拥有一套强大的日期/时间工具,可以帮助您处理各种时间相关问题:Unix时间戳、格式化日期以供人类阅读、显示带有时区的日期、计算现在到下个月第二个星期二之间的时间差等等。本文将介绍PHP的时间函数(time()mktime()date())及其面向对象对应项的基础知识,然后了解MySQL日期,并向您展示如何使它们与PHP完美配合。

主要收获

  • 利用PHP强大的日期和时间函数,如time()mktime()date(),有效处理Unix时间戳和格式化日期。
  • 利用PHP的DateTimeDateTimeZone对象进行面向对象的日期和时间操作,包括处理不同的时区。
  • 将日期存储在MySQL中作为Unix时间戳,以保持不同时区之间的一致性,并利用PHP的日期/时间函数进行转换和格式化。
  • 将服务器的默认时区设置为PHP配置中的UTC,以简化日期和时间管理并确保应用程序的一致性。

PHP日期和时间函数

本文的大部分内容将使用Unix时间,也称为POSIX时间或纪元时间。时间表示为自1970年1月1日午夜UTC以来经过的秒数。如果您对Unix时间的完整历史感兴趣,请查看维基百科上的Unix时间文章。UTC(协调世界时),也称为GMT,有时也称为Zulu时间,是0度经线的时间。世界上所有其他时区都表示为相对于此时间的正或负偏移量。使用UTC和Unix时间处理时间,在需要处理时区时会让您的生活更轻松。稍后我会详细介绍这一点,但现在让我们忽略时区问题,并查看一些时间函数。

获取当前Unix时间

time()不接受任何参数,并返回自Unix纪元以来的秒数。为了说明这一点,我将使用PHP交互式CLI shell。

<code class="language-bash">sean@beerhaus:~$ php -a
php > print time();
1324402770</code>

如果您需要Unix时间的数组表示,请使用getdate()函数。它接受一个可选的Unix时间戳参数,但如果没有提供,则默认为time()的值。

<code class="language-php">php > $unixTime = time();
php > print_r(getdate($unixTime));
Array
(
    [seconds] => 48
    [minutes] => 54
    [hours] => 12
    [mday] => 20
    [wday] => 2
    [mon] => 12
    [year] => 2011
    [yday] => 353
    [weekday] => Tuesday
    [month] => December
    [0] => 1324403688
)</code>

格式化Unix时间

Unix时间可以轻松格式化为人类希望阅读的任何字符串。date()用于将Unix时间戳格式化为人类可读的字符串,并接受一个格式化参数和一个可选的时间参数。如果没有提供可选的时间戳,则使用time()的值。

<code class="language-bash">sean@beerhaus:~$ php -a
php > print time();
1324402770</code>

“r”格式化字符串返回由RFC 2822指定的格式化时间。当然,您可以使用其他说明符来定义您自己的自定义格式。

<code class="language-php">php > $unixTime = time();
php > print_r(getdate($unixTime));
Array
(
    [seconds] => 48
    [minutes] => 54
    [hours] => 12
    [mday] => 20
    [wday] => 2
    [mon] => 12
    [year] => 2011
    [yday] => 353
    [weekday] => Tuesday
    [month] => December
    [0] => 1324403688
)</code>

有关可接受的格式化字符的完整列表,请参阅PHP文档中date()的页面。但是,当与mktime()strtotime()函数结合使用时,该函数变得更有用,正如您将在接下来的示例中看到的。

根据给定时间创建Unix时间

mktime()用于根据与日期的每个部分相对应的值列表(秒、分、小时、年等)创建Unix时间戳。它接受许多整数参数,以以下顺序设置日期的每个部分:

<code class="language-php">php > print date("r", $unixTime);
Tue, 20 Dec 2011 12:54:48 -0500</code>

如果启用了夏令时,则将isDST设置为1;如果没有启用,则设置为0;如果未知,则设置为-1(默认值)。

<code class="language-php">php > print date("m/d/y h:i:s a", $unixTime);
12/20/11 12:54:48 pm
php > print date("m/d/y h:i:s a");
12/20/11 01:12:11 pm
php > print date("jS of F Y", $unixTime);
20th of December 2011</code>

您可以看到,在处理使用用户自定义日期范围的数据库查询时,mktime()非常有用。例如,如果您在MySQL中将时间戳存储为整数(Unix时间)(预示着任何人吗?),则很容易设置一个常见的年至今查询范围。

<code>mktime(hour, minute, second, month, day, year, isDST)</code>

将英文日期解析为Unix时间

几乎神奇的函数strtotime()将日期/时间格式的字符串作为其第一个参数,以及用作转换基础的Unix时间戳。请参阅文档以了解可接受的日期格式。

<code class="language-php">php > print date("r", mktime(12, 0, 0, 1, 20, 1987));
Tue, 20 Jan 1987 12:00:00 -0500
php > print date("r", mktime(0, 0, 0, date("n"), date("j"), date("Y")));
Tue, 20 Dec 2011 00:00:00 -0500
php > print date("r", mktime(23, 59, 59, date("n"), date("j"), date("Y")));
Tue, 20 Dec 2011 23:59:59 -0500</code>

PHP的DateTime和DateTimeZone对象

PHP的DateTime对象是处理日期和时区的面向对象方法。构造方法接受时间的字符串表示,非常类似于上面的strtotime(),有些人可能会觉得这更容易使用。如果没有提供参数,则默认值为“now”。

<code class="language-php"><?php $startTime = mktime(0, 0, 0, 1, 1, date("y"));
$endTime   = mktime(0, 0, 0, date("m"), date("d"), date("y"));</code>

DateTimeformat()方法与上面的date()函数的工作方式相同,并接受所有相同的格式化字符。DateTime对象还带有一些有用的常量,可以将其馈送到format()方法。

<code class="language-php">php > print strtotime("now");
1324407707
php > print date("r", strtotime("now"));
Tue, 20 Dec 2011 14:01:51 -0500
php > print strtotime("+1 week");
1325012569
php > print date("r", strtotime("+1 week"));
Tue, 27 Dec 2011 14:03:03 -0500
php > print date("r", strtotime("next month"));
Fri, 20 Jan 2012 14:04:20 -0500
php > print date("r", strtotime("next month", mktime(0, 0, 0)));
Fri, 20 Jan 2012 00:00:00 -0500
php > print date("r", strtotime("next month", mktime(0, 0, 0, 1, 31)));
Thu, 03 Mar 2011 00:00:00 -0500</code>

可以在DateTime文档页面上找到完整的常量列表。由于我们很快就会处理时区,让我们为PHP提供一个默认时区。在您的php.ini配置文件(我有一个用于CLI,一个用于Apache)中,找到如下所示的部分:

<code class="language-php">php > $dt = new DateTime("now"); 
php > print $dt->format("r");
Tue, 20 Dec 2011 16:28:32 -0500
php > $dt = new DateTime("December 31 1999 12:12:12 EST");
php > print $dt->format("r");
Fri, 31 Dec 1999 12:12:12 -0500</code>

当没有为date.timezone赋予值时,PHP将尽力确定在服务器上设置的系统时区。您可以使用date_default_timezone_get()检查PHP正在使用哪个值。

<code class="language-bash">sean@beerhaus:~$ php -a
php > print time();
1324402770</code>

让我们将服务器的时区设置为UTC时间(date.timezone = UTC)并保存配置文件。您必须重新启动Apache或CLI shell才能查看更改。PHP DateTime对象包括一个内部DateTimeZone类实例来跟踪时区。当您创建DateTime的新实例时,内部DateTimeZone应设置为在php.ini中提供的默认值。

<code class="language-php">php > $unixTime = time();
php > print_r(getdate($unixTime));
Array
(
    [seconds] => 48
    [minutes] => 54
    [hours] => 12
    [mday] => 20
    [wday] => 2
    [mon] => 12
    [year] => 2011
    [yday] => 353
    [weekday] => Tuesday
    [month] => December
    [0] => 1324403688
)</code>

可以在时区文档页面上找到可接受的时区名称的完整列表。您现在可以看到当两个DateTime对象被赋予不同的时区时,时间差异。例如,这是一个将UTC转换为America/New_York(EST)时间的示例。

<code class="language-php">php > print date("r", $unixTime);
Tue, 20 Dec 2011 12:54:48 -0500</code>

请注意12月份的-0500偏移量。如果您将时间值更改为夏季日期,例如7月1日,您会发现它知道夏令时(EDT)。

<code class="language-php">php > print date("m/d/y h:i:s a", $unixTime);
12/20/11 12:54:48 pm
php > print date("m/d/y h:i:s a");
12/20/11 01:12:11 pm
php > print date("jS of F Y", $unixTime);
20th of December 2011</code>

将日期与MySQL和PHP一起使用

如果您在任何级别使用过MySQL,您可能已经注意到开箱即用的DATETIME类型。它看起来和闻起来像一个日期,如果您说它是一个日期,那么您是对的。但是,一旦您将其从MySQL中SELECT到PHP中,您实际上拥有的只是一个看起来像日期的字符串。它没有时区意识,并且在人类需要查看它之前就已经格式化好供人类使用了。是的,我知道MySQL有很多日期格式化函数,但我们也已经在使用PHP了,正如您所看到的,PHP在处理日期格式方面非常出色。为什么我们还要从数据库中直接格式化它呢?我们可能需要应用一些不同的转换和格式。最好只在人类即将看到日期时才格式化日期。

<code>mktime(hour, minute, second, month, day, year, isDST)</code>

运行这个简单的脚本,您可以看到您从DATETIME字段获得的只是一个格式化的字符串,没有时区信息。

<code class="language-php">php > print date("r", mktime(12, 0, 0, 1, 20, 1987));
Tue, 20 Jan 1987 12:00:00 -0500
php > print date("r", mktime(0, 0, 0, date("n"), date("j"), date("Y")));
Tue, 20 Dec 2011 00:00:00 -0500
php > print date("r", mktime(23, 59, 59, date("n"), date("j"), date("Y")));
Tue, 20 Dec 2011 23:59:59 -0500</code>

DATETIME值是运行MySQL的服务器的本地时间,无论该服务器的时区是什么。如果您所做的所有事情都只涉及一个时区中的一个服务器,那么DATETIME可能适合您的大部分需求,而且我非常羡慕您。那么,如何使用PHP和MySQL处理日期和时区呢?将日期存储为Unix时间戳。您已经知道Unix时间是自1970年1月1日UTC以来的秒数,因此这为您提供了一个恒定的时区,并且您可能已经注意到PHP的许多日期/时间函数都是基于Unix时间戳的。在使用MySQL时,我通常创建将日期存储为INTEGER UNSIGNED的表列。插入日期时,您可以使用PHP的time()或MySQL的UNIX_TIMESTAMP()

<code class="language-php"><?php $startTime = mktime(0, 0, 0, 1, 1, date("y"));
$endTime   = mktime(0, 0, 0, date("m"), date("d"), date("y"));</code>

如果您希望MySQL格式化日期,您可以这样做。但是时间将位于运行MySQL的服务器的时区中,我建议您在到达Web应用程序的模板/视图级别并准备好让人眼看到它之前,不要进行任何类型的格式化。

<code class="language-bash">sean@beerhaus:~$ php -a
php > print time();
1324402770</code>

在任何跨越时区的应用程序中,您通常都会有一个表来跟踪用户的自定义时区设置,然后将其读入$_SESSION值。假设您有一个如下所示的会话条目:

<code class="language-php">php > $unixTime = time();
php > print_r(getdate($unixTime));
Array
(
    [seconds] => 48
    [minutes] => 54
    [hours] => 12
    [mday] => 20
    [wday] => 2
    [mon] => 12
    [year] => 2011
    [yday] => 353
    [weekday] => Tuesday
    [month] => December
    [0] => 1324403688
)</code>

您可以轻松地将存储的Unix时间(以UTC为单位)转换为特定用户的时区中的任何日期。

<code class="language-php">php > print date("r", $unixTime);
Tue, 20 Dec 2011 12:54:48 -0500</code>

这将导致日期“Mon, 16 Jan 2012 12:03:49 -0600”。-0600告诉您它比UTC落后6小时,UTC的偏移量为0。如果我们将时区设置为America/Los_Angeles,则生成的日期将是:

<code class="language-php">php > print date("m/d/y h:i:s a", $unixTime);
12/20/11 12:54:48 pm
php > print date("m/d/y h:i:s a");
12/20/11 01:12:11 pm
php > print date("jS of F Y", $unixTime);
20th of December 2011</code>

而America/New_York将产生:

<code>mktime(hour, minute, second, month, day, year, isDST)</code>

总结

处理日期和时区是许多程序员日常生活中的一部分,但是当您可以使用PHP强大且易于使用的日期库时,无需担心。您已经了解了如何获取Unix时间戳、如何将日期格式化为任何可以想象的格式、如何将日期的英文表示解析为时间戳、如何将一段时间添加到时间戳以及如何在时区之间进行转换。如果本文有两个主要要点,那就是1)坚持使用Unix时间,以及2)在使用PHP和MySQL时,坚持使用UTC作为所有日期的基础时区。基于UTC的所有时间的想法不仅适用于PHP和MySQL;它在任何语言中都被认为是最佳实践。如果您发现自己正在使用其他语言工作,那么您很有可能会对自己说:“该死的,他们为什么不能像PHP那样做?”

图片来自Yakobchuk Vasyl / Shutterstock

(此处应添加关于在PHP中处理日期和时间的常见问题的FAQ部分,类似于输入文本中的FAQ部分。 由于篇幅限制,我没有在此处添加。)

以上是在PHP和MySQL中与日期和时间合作的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn