# How to use the DateTime class (Dealing with Conversions, Formatting, Diffs, and Time zones)
每个人都必须在编程的某些时候处理日期/时间格式,时区,奇怪的时间格式等。 PHP几乎没有办法解决这些问题,其中最值得注意的是PHP内置的
但是,
这篇文章是为了帮助那些想要了解更多关于
请注意:
本文不会解决
以下大部分信息可以从PHP的
如果您正在尝试使用Dates / Times进行更高级的操作,例如创建
1.如何将字符串转换为可修改的日期/时间?
编程中最困难的事情之一是尝试使最终用户输入可用。然而,当涉及日期和时间时,
怎么样
1 | $datetime = new DateTime($datetime_string); |
从那里,您可以使用以下任何方法来修改时间:
要查看
示例 - 解释最终用户输入
假设您的表单允许用户说出他们想要约会的日期,但此输入不是具有强制格式的日期选择器,而是纯文本输入。
典型的最终用户会在这个输入中添加类似这样的内容,并且当被要求支持时,典型的程序员将以下列方式做出响应:
过了一段时间,你要么强迫一个特定的格式(你应该总是这样做)或者在你糟糕的表格设计中哭泣。但是,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // 2000-12-31 00:00:00.000000 new DateTime('12/31/2000'); // 2000-12-31 00:00:00.000000 new DateTime('2000-12-31'); // 2000-12-31 00:00:00.000000 new DateTime('Today'); // 2001-01-01 00:00:00.000000 new DateTime('Tomorrow'); // 2001-01-03 00:00:00.000000 new DateTime('wednesday next week'); |
但是,像大多数事情一样,
1 2 3 4 5 | try { new DateTime('31/12/2000'); } catch (Exception $e) { echo $e->getMessage(); } |
输出:
1 | DateTime::__construct(): Failed to parse time string (31/12/2000) at position 0 (3): Unexpected character |
示例 - 修改日期/时间
您可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $datetime = new DateTime('2001-01-01'); // 2001-01-04 00:00:00.000000 $datetime->modify('+3 days'); // 2001-02-04 00:00:00.000000 $datetime->modify('+1 month'); // 2001-02-03 23:59:00.000000 $datetime->modify('-60 seconds'); // 2001-02-02 00:00:00.000000 $datetime->modify('yesterday'); // 2001-02-02 18:00:00.000000 $datetime->modify('6pm'); |
但是,由于解析它有点效率低下。如果要修改1000的日期/时间并且需要更好的性能,请使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | $datetime = new DateTime('2001-01-01'); // 2001-06-01 00:00:00.000000 $datetime->setDate(2001, 6, 1); // 2001-06-01 06:30:00.000000 $datetime->setTime(6, 30, 0); // No sane person should ever do the below when they could just add 10,000 // seconds, but it's a good way to test how fast your system will handle // updating DateTime. $timestamp = $datetime->getTimestamp(); foreach (range(1, 10000) as $i) { $timestamp++; $datetime->setTimestamp($timestamp); } // 2001-06-01 09:16:40.000000 |
2.如何格式化日期/时间字符串?
通常需要取1个日期/时间字符串并将其格式化为另一个日期/时间字符串,或者甚至只需采用现有日期/时间并更新它。
怎么样
1 2 3 | $datetime = new DateTime; $format = 'Y-m-d H:i:s'; echo $datetime->format($format); |
我们只会使用这些示例中提供的一小部分格式化选项,因此我强烈建议您查看有关格式化日期/时间以及预定义的DateTime常量的文档。
注意:请注意,如果您尝试转义可能是PHP字符串转义字符的字符,则可能会出现意外结果。
结果不正确
1 2 | // output: Da e 2000-12-31 echo $datetime->format("\D\a\t\e\: Y-m-d").PHP_EOL; |
正确的结果
1 2 3 4 5 | // output: Date 2000-12-31 echo $datetime->format("\D\a\\t\e\: Y-m-d").PHP_EOL; // output: Date 2000-12-31 echo $datetime->format('\D\a\t\e\: Y-m-d').PHP_EOL; |
例子
这些是您可能需要的一些常见格式:
SQL日期/时间
1 2 3 4 5 6 7 8 | // output: 2000-12-31 echo $datetime->format('Y-m-d').PHP_EOL; // output: 23:59:59 echo $datetime->format('H:i:s').PHP_EOL; // output: 2000-12-31 23:59:59 echo $datetime->format('Y-m-d H:i:s').PHP_EOL; |
最终用户可读日期/时间
1 2 3 4 5 6 7 8 9 10 11 | // output: 12/31/2000 echo $datetime->format('n/j/Y').PHP_EOL; // output: 11:59pm echo $datetime->format('g:ia').PHP_EOL; // output: 12/31/2000 at 11:59pm echo $datetime->format('n/j/Y \a\t g:ia').PHP_EOL; // output: Sunday the 31st of December 2000 at 11:59:59 PM echo $datetime->format('l \t\h\e jS \o\f F Y \a\t g:i:s A').PHP_EOL; |
日期/时间与时区
1 2 3 4 5 6 7 8 9 10 11 | date_default_timezone_set('America/New_York'); $datetime = new DateTime('2000-12-31 23:59:59'); // output: 2000-12-31 23:59:59 America/New_York echo $datetime->format('Y-m-d H:i:s e').PHP_EOL; // output: 2000-12-31 23:59:59 EST echo $datetime->format('Y-m-d H:i:s T').PHP_EOL; // output: 2000-12-31 23:59:59 -0500 echo $datetime->format('Y-m-d H:i:s O').PHP_EOL; |
3.如何获得2次之间的差异?
通常需要知道2个日期/时间之间的时间差异。使用
如何(与例子)
场景1:您只需要知道
在这种情况下,您可以直接比较
1 2 3 4 5 6 7 |
场景2:您需要
这适用于大多数情况,但是从
1 2 3 4 5 6 | $datetime1 = new DateTime('2000-01-01 00:00:00.000000'); $datetime2 = new DateTime('2001-02-03 04:05:06.789012'); $diff = $datetime1->diff($datetime2); // output: 1 Years, 1 Months, 2 Days, 4 Hours, 5 Minutes, 6 Seconds echo $diff->format('%y Years, %m Months, %d Days, %h Hours, %i Minutes, %s Seconds'); |
场景3:您需要以另一种方式表达的
这将在任何上下文中工作,代价是一些额外的代码。
1 2 3 4 5 6 7 | $interval = 60 * 60 * 24; // 1 day in seconds $datetime1 = new DateTime('2000-01-01'); $datetime2 = new DateTime; $diff = $datetime2->getTimestamp() - $datetime1->getTimestamp(); // output: It has been 6956 days since 2000-01-01! printf('It has been %s days since %s!', floor($diff / $interval), $datetime1->format('Y-m-d')); |
4.我如何计算时区?
在处理编程时间方面,到目前为止最糟糕的部分是处理时区。幸运的是,这是
怎么样
1 2 3 4 5 | // These 2 lines are functionally identical $datetime = new DateTime('2001-01-01 00:00:00', new DateTimeZone('UTC')); // recommended, may be faster $datetime = new DateTime('2001-01-01 00:00:00 UTC'); $datetime->setTimezone(new DateTimeZone('EST')); |
我建议查看PHP支持的时区的完整列表以及
例
假设您希望向最终用户显示客户支持热线在其时区中打开的时间。 使用
1 2 3 4 5 6 7 8 9 | $support_opens = new DateTime('08:00:00', new DateTimeZone('America/New_York')); $customer_timezones = array('America/New_York', 'America/Chicago', 'America/Denver', 'America/Phoenix', 'America/Los_Angeles', 'America/Anchorage', 'America/Adak', 'Pacific/Honolulu'); echo"Today we open at the following times:".PHP_EOL; foreach ($customer_timezones as $timezone) { $support_opens->setTimezone(new DateTimeZone($timezone)); echo '* '.$support_opens->format('g:ia \f\o \t\h\e e').' time zone'.PHP_EOL; } |
输出:
1 2 3 4 5 6 7 8 9 | Today we open at the following times: * 8:00am for the America/New_York time zone * 7:00am for the America/Chicago time zone * 6:00am for the America/Denver time zone * 6:00am for the America/Phoenix time zone * 5:00am for the America/Los_Angeles time zone * 4:00am for the America/Anchorage time zone * 3:00am for the America/Adak time zone * 3:00am for the Pacific/Honolulu time zone |
注意:如果在日期/时间字符串和第二个参数中都提供时区,则将忽略参数时区。
1 2 3 4 | $datetime = new DateTime('2001-01-01 00:00:00 EST', new DateTimeZone('UTC')); // output: 2001-01-01 00:00:00 EST echo $datetime1->format('Y-m-d H:i:s'); |
好。