icanboogie/datetime

扩展PHP DateTime和DateTimeZone类的功能

v2.0.0 2022-06-23 18:41 UTC

README

Release Code Coverage Packagist

此包扩展了PHP DateTimeDateTimeZone 类的功能,简化了时间、时区和时区位置的处理。获取时间的UTC或本地表示、格式化时间到预定义的格式、访问如日、月、年、季度等常见属性都变得特别简单。此外,所有实例都可以用作字符串。

安装

composer require icanboogie/datetime

使用方法

假设现在是巴黎的 "2013-02-03 21:03:45"。

<?php

use ICanBoogie\DateTime;

date_default_timezone_set('EST'); // set local time zone to Eastern Standard Time

$time = new DateTime('now', 'Europe/Paris');

echo $time;                             // 2013-02-03T21:03:45+0100
echo $time->utc;                        // 2013-02-03T20:03:45Z
echo $time->local;                      // 2013-02-03T15:03:45-0500
echo $time->utc->local;                 // 2013-02-03T15:03:45-0500
echo $time->utc->is_utc;                // true
echo $time->utc->is_local;              // false
echo $time->local->is_utc;              // false
echo $time->local->is_local;            // true
echo $time->is_dst;                     // false

echo $time->as_rss;                     // Sun, 03 Feb 2013 21:03:45 +0100
echo $time->as_db;                      // 2013-02-03 21:03:45

echo $time->as_time;                    // 21:03:45
echo $time->utc->as_time;               // 20:03:45
echo $time->local->as_time;             // 15:03:45
echo $time->utc->local->as_time;        // 15:03:45

echo $time->quarter;                    // 1
echo $time->week;                       // 5
echo $time->day;                        // 3
echo $time->minute;                     // 3
echo $time->is_monday;                  // false
echo $time->is_saturday;                // true
echo $time->is_today;                   // true
echo $time->tomorrow;                   // 2013-02-04T00:00:00+0100
echo $time->tomorrow->is_future;        // true
echo $time->yesterday;                  // 2013-02-02T00:00:00+0100
echo $time->yesterday->is_past;         // true
echo $time->monday;                     // 2013-01-28T00:00:00+0100
echo $time->sunday;                     // 2013-02-03T00:00:00+0100

echo $time->timestamp;                  // 1359921825
echo $time;                             // 2013-02-03T21:03:45+0100
$time->timestamp += 3600 * 4;
echo $time;                             // 2013-02-04T01:03:45+0100

echo $time->zone;                       // Europe/Paris
echo $time->zone->offset;               // 3600
echo $time->zone->location;             // FR,48.86667,2.33333
echo $time->zone->location->latitude;   // 48.86667
$time->zone = 'Asia/Tokyo';
echo $time;                             // 2013-02-04T09:03:45+0900

$time->hour += 72;
echo "Rendez-vous in 72 hours: $time";  // Rendez-vous in 72 hours: 2013-02-07T05:03:45+0900

空日期也受支持

<?php

use ICanBoogie\DateTime;

$time = new DateTime('0000-00-00', 'utc');
// or
$time = DateTime::none();

echo $time->is_empty;                   // true
echo $time->as_date;                    // 0000-00-00
echo $time->as_db;                      // 0000-00-00 00:00:00
echo $time;                             // ""

致谢

DateTime类的实现大量受到了Ruby的 Time 类的启发。

星期几

<?php

use ICanBoogie\DateTime;

$time = new DateTime('2014-01-06 11:11:11', 'utc'); // a monday at 11:11:11 UTC

echo $time->monday;                          // 2014-01-06T00:00:00Z
echo $time->tuesday;                         // 2014-01-07T00:00:00Z
echo $time->wednesday;                       // 2014-01-08T00:00:00Z
echo $time->thursday;                        // 2014-01-09T00:00:00Z
echo $time->friday;                          // 2014-01-10T00:00:00Z
echo $time->saturday;                        // 2014-01-11T00:00:00Z
echo $time->sunday;                          // 2014-01-12T00:00:00Z

$time->monday->is_monday;                    // true
$time->tuesday->is_tuesday;                  // true
$time->wednesday->is_wednesday;              // true
$time->thursday->is_thursday;                // true
$time->friday->is_friday;                    // true
$time->saturday->is_saturday;                // true
$time->sunday->is_sunday;                    // true

$time->monday->is_tuesday;                   // false
$time->tuesday->is_wednesday;                // false
$time->wednesday->is_thursday;               // false
$time->thursday->is_friday;                  // false
$time->friday->is_saturday;                  // false
$time->saturday->is_sunday;                  // false
$time->sunday->is_monday;                    // false

$time->monday->weekday;                      // 1
$time->tuesday->weekday;                     // 2
$time->wednesday->weekday;                   // 3
$time->thursday->weekday;                    // 4
$time->friday->weekday;                      // 5
$time->saturday->weekday;                    // 6
$time->sunday->weekday;                      // 7

now()right_now()

DateTime::now() 返回一个包含当前本地时间和本地时区的新实例。后续调用返回相同的时间,即使它们相差几分钟。实际上,now 指的是 REQUEST_TIME 或,如果不可用,则是指方法首次被调用的第一个时间。

另一方面,DateTime::right_now() 返回一个包含 真实 当前本地时间和本地时区的新实例。

以下示例演示了差异

<?php

use ICanBoogie\DateTime;

$now = DateTime::now();

sleep(2);

$now == DateTime::now();         // true
$now == DateTime::right_now();   // false

比较DateTime实例

DateTime 实例使用标准的比较操作进行比较

<?php

use ICanBoogie\DateTime;

$d1 = DateTime::now();
$d2 = DateTime::now();

$d1 == $d2; // true
$d1 >= $d2; // true
$d1 <= $d2; // true
$d1 != $d2; // false
$d1 > $d2;  // false
$d1 < $d2;  // false

$d2->second++;
$d1 != $d2; // true
$d1 < $d2;  // true
$d2 > $d1;  // true
$d1 == $d2; // false
$d1 >= $d2; // false
$d2 <= $d1; // false

要确定一个实例是否在两个其他实例之间,只需进行两次比较即可

<?php

use ICanBoogie\DateTime;

$now = DateTime::now();

$now > $now->yesterday && $now < $now->tomorrow; // true

要确定哪个实例是最新的或最晚的,只需使用PHP的 min()max() 函数即可

<?php

use ICanBoogie\DateTime;

$now = DateTime::now();
$yesterday = $now->yesterday;
$tomorrow = $now->tomorrow;

$yesterday === min($now, $yesterday, $tomorrow); // true
$tomorrow  === max($now, $yesterday, $tomorrow); // true

DateTime和JSON

从v1.1.0开始,DateTime 实例实现了 JsonSerializable 接口 并被序列化为ISO-8601字符串。

<?php

use ICanBoogie\DateTime;

$date = new DateTime("2014-10-23 13:50:10", "Europe/Paris");

echo json_encode([ 'date' => $date ]);
// {"date":"2014-10-23T13:50:10+0200"}

更改多个属性

使用 change() 方法可以一次性更改多个属性。

注意:超出范围的值将添加到其父值。

<?php

use ICanBoogie\DateTime;

$date = DateTime::now()->change([ 'year' => 2015, 'month' => 5, 'hour' => 12 ]);

使用 $cascade 参数,设置小时会将分钟和秒重置为0,设置分钟会将秒重置为0。

<?php

use ICanBoogie\DateTime;

echo DateTime::from("2015-05-05 12:13:14")->change([ 'hour' => 13 ], true);   // 2015-05-05 13:00:00

使用更改后的属性创建新的实例

with() 方法与 change() 方法类似,因为它也用于一次性定义多个属性,但区别在于该方法创建了一个新的实例,而不会修改原始实例。

<?php

use ICanBoogie\DateTime;

$now = DateTime::now();
$next_year = $now->with([ 'year' => $now->year + 1 ]);

spl_object_hash($now) == spl_object_hash($next_year);   // false

本地化格式化

本地化格式化超出了本包的范围,但仍可以向 DateTime 类提供一个 localizer 来本地化其实例,但当然结果取决于实现。

以下示例演示了如何使用ICanBoogie/CLDR本地化实例,该库使用Unicode的通用区域数据存储库来格式化DateTime实例。

<?php

use ICanBoogie\CLDR\Repository;
use ICanBoogie\DateTime;

// …

/* @var Repository $repository */

DateTime::$localizer = function(DateTime $instance, $locale) use ($repository) {

	return $repository->locales[$locale]->localize($instance);

};

$date = DateTime::from('2015-05-05 23:21:05', 'UTC');

echo $date->localize('fr')->format('long');   // mardi 5 mai 2015 23:13:05 UTC
echo $date->localize('fr')->as_medium;        // 5 mai 2015 23:13:05

持续集成

该项目由GitHub actions持续进行测试。

Tests

贡献

请参阅CONTRIBUTING以获取详细信息。

许可证

ICanBoogie/DateTimeBSD-3-Clause许可证下发布。