upgrade/extend/fast/Date.php

227 lines
9.1 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace fast;
use DateTime;
use DateTimeZone;
/**
* 日期时间处理类
*/
class Date
{
const YEAR = 31536000;
const MONTH = 2592000;
const WEEK = 604800;
const DAY = 86400;
const HOUR = 3600;
const MINUTE = 60;
/**
* 计算两个时区间相差的时长,单位为秒
*
* $seconds = self::offset('America/Chicago', 'GMT');
*
* [!!] A list of time zones that PHP supports can be found at
* <http://php.net/timezones>.
*
* @param string $remote timezone that to find the offset of
* @param string $local timezone used as the baseline
* @param mixed $now UNIX timestamp or date string
* @return integer
*/
public static function offset($remote, $local = null, $now = null)
{
if ($local === null) {
// Use the default timezone
$local = date_default_timezone_get();
}
if (is_int($now)) {
// Convert the timestamp into a string
$now = date(DateTime::RFC2822, $now);
}
// Create timezone objects
$zone_remote = new DateTimeZone($remote);
$zone_local = new DateTimeZone($local);
// Create date objects from timezones
$time_remote = new DateTime($now, $zone_remote);
$time_local = new DateTime($now, $zone_local);
// Find the offset
$offset = $zone_remote->getOffset($time_remote) - $zone_local->getOffset($time_local);
return $offset;
}
/**
* 计算两个时间戳之间相差的时间
*
* $span = self::span(60, 182, 'minutes,seconds'); // array('minutes' => 2, 'seconds' => 2)
* $span = self::span(60, 182, 'minutes'); // 2
*
* @param int $remote timestamp to find the span of
* @param int $local timestamp to use as the baseline
* @param string $output formatting string
* @return string when only a single output is requested
* @return array associative list of all outputs requested
* @from https://github.com/kohana/ohanzee-helpers/blob/master/src/Date.php
*/
public static function span($remote, $local = null, $output = 'years,months,weeks,days,hours,minutes,seconds')
{
// Normalize output
$output = trim(strtolower((string)$output));
if (!$output) {
// Invalid output
return false;
}
// Array with the output formats
$output = preg_split('/[^a-z]+/', $output);
// Convert the list of outputs to an associative array
$output = array_combine($output, array_fill(0, count($output), 0));
// Make the output values into keys
extract(array_flip($output), EXTR_SKIP);
if ($local === null) {
// Calculate the span from the current time
$local = time();
}
// Calculate timespan (seconds)
$timespan = abs($remote - $local);
if (isset($output['years'])) {
$timespan -= self::YEAR * ($output['years'] = (int)floor($timespan / self::YEAR));
}
if (isset($output['months'])) {
$timespan -= self::MONTH * ($output['months'] = (int)floor($timespan / self::MONTH));
}
if (isset($output['weeks'])) {
$timespan -= self::WEEK * ($output['weeks'] = (int)floor($timespan / self::WEEK));
}
if (isset($output['days'])) {
$timespan -= self::DAY * ($output['days'] = (int)floor($timespan / self::DAY));
}
if (isset($output['hours'])) {
$timespan -= self::HOUR * ($output['hours'] = (int)floor($timespan / self::HOUR));
}
if (isset($output['minutes'])) {
$timespan -= self::MINUTE * ($output['minutes'] = (int)floor($timespan / self::MINUTE));
}
// Seconds ago, 1
if (isset($output['seconds'])) {
$output['seconds'] = $timespan;
}
if (count($output) === 1) {
// Only a single output was requested, return it
return array_pop($output);
}
// Return array
return $output;
}
/**
* 格式化 UNIX 时间戳为人易读的字符串
*
* @param int Unix 时间戳
* @param mixed $local 本地时间
*
* @return string 格式化的日期字符串
*/
public static function human($remote, $local = null)
{
$time_diff = (is_null($local) || $local ? time() : $local) - $remote;
$tense = $time_diff < 0 ? 'after' : 'ago';
$time_diff = abs($time_diff);
$chunks = [
[60 * 60 * 24 * 365, 'year'],
[60 * 60 * 24 * 30, 'month'],
[60 * 60 * 24 * 7, 'week'],
[60 * 60 * 24, 'day'],
[60 * 60, 'hour'],
[60, 'minute'],
[1, 'second']
];
$name = 'second';
$count = 0;
for ($i = 0, $j = count($chunks); $i < $j; $i++) {
$seconds = $chunks[$i][0];
$name = $chunks[$i][1];
if (($count = floor($time_diff / $seconds)) != 0) {
break;
}
}
return __("%d $name%s $tense", $count, ($count > 1 ? 's' : ''));
}
/**
* 获取一个基于时间偏移的Unix时间戳
*
* @param string $type 时间类型默认为day可选minute,hour,day,week,month,quarter,year
* @param int $offset 时间偏移量 默认为0正数表示当前type之后负数表示当前type之前
* @param string $position 时间的开始或结束默认为begin可选前(begin,start,first,front)end
* @param int $year 基准年默认为null即以当前年为基准
* @param int $month 基准月默认为null即以当前月为基准
* @param int $day 基准天默认为null即以当前天为基准
* @param int $hour 基准小时默认为null即以当前年小时基准
* @param int $minute 基准分钟默认为null即以当前分钟为基准
* @return int 处理后的Unix时间戳
*/
public static function unixtime($type = 'day', $offset = 0, $position = 'begin', $year = null, $month = null, $day = null, $hour = null, $minute = null)
{
$year = is_null($year) ? date('Y') : $year;
$month = is_null($month) ? date('m') : $month;
$day = is_null($day) ? date('d') : $day;
$hour = is_null($hour) ? date('H') : $hour;
$minute = is_null($minute) ? date('i') : $minute;
$position = in_array($position, array('begin', 'start', 'first', 'front'));
$baseTime = mktime(0, 0, 0, $month, $day, $year);
switch ($type) {
case 'minute':
$time = $position ? mktime($hour, $minute + $offset, 0, $month, $day, $year) : mktime($hour, $minute + $offset, 59, $month, $day, $year);
break;
case 'hour':
$time = $position ? mktime($hour + $offset, 0, 0, $month, $day, $year) : mktime($hour + $offset, 59, 59, $month, $day, $year);
break;
case 'day':
$time = $position ? mktime(0, 0, 0, $month, $day + $offset, $year) : mktime(23, 59, 59, $month, $day + $offset, $year);
break;
case 'week':
$weekIndex = date("w", $baseTime);
$time = $position ?
strtotime($offset . " weeks", strtotime(date('Y-m-d', strtotime("-" . ($weekIndex ? $weekIndex - 1 : 6) . " days", $baseTime)))) :
strtotime($offset . " weeks", strtotime(date('Y-m-d 23:59:59', strtotime("+" . (6 - ($weekIndex ? $weekIndex - 1 : 6)) . " days", $baseTime))));
break;
case 'month':
$_timestamp = mktime(0, 0, 0, $month + $offset, 1, $year);
$time = $position ? $_timestamp : mktime(23, 59, 59, $month + $offset, self::days_in_month(date("m", $_timestamp), date("Y", $_timestamp)), $year);
break;
case 'quarter':
$_month = date("m", mktime(0, 0, 0, (ceil(date('n', mktime(0, 0, 0, $month, $day, $year)) / 3) + $offset) * 3, $day, $year));
$time = $position ?
mktime(0, 0, 0, 1 + ((ceil(date('n', $baseTime) / 3) + $offset) - 1) * 3, 1, $year) :
mktime(23, 59, 59, (ceil(date('n', $baseTime) / 3) + $offset) * 3, self::days_in_month((ceil(date('n', $baseTime) / 3) + $offset) * 3, $year), $year);
break;
case 'year':
$time = $position ? mktime(0, 0, 0, 1, 1, $year + $offset) : mktime(23, 59, 59, 12, 31, $year + $offset);
break;
default:
$time = mktime($hour, $minute, 0, $month, $day, $year);
break;
}
return $time;
}
/**
* 获取指定年月拥有的天数
* @param int $month
* @param int $year
* @return false|int|string
*/
public static function days_in_month($month, $year)
{
if (function_exists("cal_days_in_month")) {
return cal_days_in_month(CAL_GREGORIAN, $month, $year);
} else {
return date('t', mktime(0, 0, 0, $month, 1, $year));
}
}
}