Nav apraksta
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Yzncms [ 御宅男工作室 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2018 http://yzncms.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: fastadmin: https://www.fastadmin.net/
  10. // +----------------------------------------------------------------------
  11. // +----------------------------------------------------------------------
  12. // | 日期时间类
  13. // +----------------------------------------------------------------------
  14. namespace util;
  15. use DateTime;
  16. use DateTimeZone;
  17. /**
  18. * 日期时间处理类
  19. */
  20. class Date
  21. {
  22. const YEAR = 31536000;
  23. const MONTH = 2592000;
  24. const WEEK = 604800;
  25. const DAY = 86400;
  26. const HOUR = 3600;
  27. const MINUTE = 60;
  28. /**
  29. * 计算两个时区间相差的时长,单位为秒
  30. *
  31. * $seconds = self::offset('America/Chicago', 'GMT');
  32. *
  33. * [!!] A list of time zones that PHP supports can be found at
  34. * <http://php.net/timezones>.
  35. *
  36. * @param string $remote timezone that to find the offset of
  37. * @param null $local timezone used as the baseline
  38. * @param mixed $now UNIX timestamp or date string
  39. *
  40. * @return integer
  41. * @throws \Exception
  42. */
  43. public static function offset($remote, $local = null, $now = null)
  44. {
  45. if ($local === null) {
  46. // Use the default timezone
  47. $local = date_default_timezone_get();
  48. }
  49. if (is_int($now)) {
  50. // Convert the timestamp into a string
  51. $now = date(DateTime::RFC2822, $now);
  52. }
  53. // Create timezone objects
  54. $zone_remote = new DateTimeZone($remote);
  55. $zone_local = new DateTimeZone($local);
  56. // Create date objects from timezones
  57. $time_remote = new DateTime($now, $zone_remote);
  58. $time_local = new DateTime($now, $zone_local);
  59. // Find the offset
  60. $offset = $zone_remote->getOffset($time_remote) - $zone_local->getOffset($time_local);
  61. return $offset;
  62. }
  63. /**
  64. * 计算两个时间戳之间相差的时间
  65. *
  66. * $span = self::span(60, 182, 'minutes,seconds'); // array('minutes' => 2, 'seconds' => 2)
  67. * $span = self::span(60, 182, 'minutes'); // 2
  68. *
  69. * @param int $remote timestamp to find the span of
  70. * @param int $local timestamp to use as the baseline
  71. * @param string $output formatting string
  72. * @return string when only a single output is requested
  73. * @return array associative list of all outputs requested
  74. * @from https://github.com/kohana/ohanzee-helpers/blob/master/src/Date.php
  75. */
  76. public static function span($remote, $local = null, $output = 'years,months,weeks,days,hours,minutes,seconds')
  77. {
  78. // Normalize output
  79. $output = trim(strtolower((string) $output));
  80. if (!$output) {
  81. // Invalid output
  82. return false;
  83. }
  84. // Array with the output formats
  85. $output = preg_split('/[^a-z]+/', $output);
  86. // Convert the list of outputs to an associative array
  87. $output = array_combine($output, array_fill(0, count($output), 0));
  88. // Make the output values into keys
  89. extract(array_flip($output), EXTR_SKIP);
  90. if ($local === null) {
  91. // Calculate the span from the current time
  92. $local = time();
  93. }
  94. // Calculate timespan (seconds)
  95. $timespan = abs($remote - $local);
  96. if (isset($output['years'])) {
  97. $timespan -= self::YEAR * ($output['years'] = (int) floor($timespan / self::YEAR));
  98. }
  99. if (isset($output['months'])) {
  100. $timespan -= self::MONTH * ($output['months'] = (int) floor($timespan / self::MONTH));
  101. }
  102. if (isset($output['weeks'])) {
  103. $timespan -= self::WEEK * ($output['weeks'] = (int) floor($timespan / self::WEEK));
  104. }
  105. if (isset($output['days'])) {
  106. $timespan -= self::DAY * ($output['days'] = (int) floor($timespan / self::DAY));
  107. }
  108. if (isset($output['hours'])) {
  109. $timespan -= self::HOUR * ($output['hours'] = (int) floor($timespan / self::HOUR));
  110. }
  111. if (isset($output['minutes'])) {
  112. $timespan -= self::MINUTE * ($output['minutes'] = (int) floor($timespan / self::MINUTE));
  113. }
  114. // Seconds ago, 1
  115. if (isset($output['seconds'])) {
  116. $output['seconds'] = $timespan;
  117. }
  118. if (count($output) === 1) {
  119. // Only a single output was requested, return it
  120. return array_pop($output);
  121. }
  122. // Return array
  123. return $output;
  124. }
  125. /**
  126. * 格式化 UNIX 时间戳为人易读的字符串
  127. *
  128. * @param int $remote Unix 时间戳
  129. * @param mixed $local 本地时间
  130. *
  131. * @return string 格式化的日期字符串
  132. */
  133. public static function human($remote, $local = null)
  134. {
  135. $time_diff = (is_null($local) || $local ? time() : $local) - $remote;
  136. $tense = $time_diff < 0 ? '后' : '前';
  137. $time_diff = abs($time_diff);
  138. $chunks = [
  139. [60 * 60 * 24 * 365, '年'],
  140. [60 * 60 * 24 * 30, '月'],
  141. [60 * 60 * 24 * 7, '周'],
  142. [60 * 60 * 24, '天'],
  143. [60 * 60, '小时'],
  144. [60, '分钟'],
  145. [1, '秒'],
  146. ];
  147. $name = 'second';
  148. $count = 0;
  149. for ($i = 0, $j = count($chunks); $i < $j; $i++) {
  150. $seconds = $chunks[$i][0];
  151. $name = $chunks[$i][1];
  152. if (($count = floor($time_diff / $seconds)) != 0) {
  153. break;
  154. }
  155. }
  156. return $count . $name . $tense;
  157. }
  158. /**
  159. * 获取一个基于时间偏移的Unix时间戳
  160. *
  161. * @param string $type 时间类型,默认为day,可选minute,hour,day,week,month,quarter,year
  162. * @param int $offset 时间偏移量 默认为0,正数表示当前type之后,负数表示当前type之前
  163. * @param string $position 时间的开始或结束,默认为begin,可选前(begin,start,first,front),end
  164. * @param int $year 基准年,默认为null,即以当前年为基准
  165. * @param int $month 基准月,默认为null,即以当前月为基准
  166. * @param int $day 基准天,默认为null,即以当前天为基准
  167. * @param int $hour 基准小时,默认为null,即以当前年小时基准
  168. * @param int $minute 基准分钟,默认为null,即以当前分钟为基准
  169. * @return int 处理后的Unix时间戳
  170. */
  171. public static function unixtime($type = 'day', $offset = 0, $position = 'begin', $year = null, $month = null, $day = null, $hour = null, $minute = null)
  172. {
  173. $year = is_null($year) ? date('Y') : $year;
  174. $month = is_null($month) ? date('m') : $month;
  175. $day = is_null($day) ? date('d') : $day;
  176. $hour = is_null($hour) ? date('H') : $hour;
  177. $minute = is_null($minute) ? date('i') : $minute;
  178. $position = in_array($position, ['begin', 'start', 'first', 'front']);
  179. $baseTime = mktime(0, 0, 0, $month, $day, $year);
  180. switch ($type) {
  181. case 'minute':
  182. $time = $position ? mktime($hour, $minute + $offset, 0, $month, $day, $year) : mktime($hour, $minute + $offset, 59, $month, $day, $year);
  183. break;
  184. case 'hour':
  185. $time = $position ? mktime($hour + $offset, 0, 0, $month, $day, $year) : mktime($hour + $offset, 59, 59, $month, $day, $year);
  186. break;
  187. case 'day':
  188. $time = $position ? mktime(0, 0, 0, $month, $day + $offset, $year) : mktime(23, 59, 59, $month, $day + $offset, $year);
  189. break;
  190. case 'week':
  191. $weekIndex = date("w", $baseTime);
  192. $time = $position ?
  193. strtotime($offset . " weeks", strtotime(date('Y-m-d', strtotime("-" . ($weekIndex ? $weekIndex - 1 : 6) . " days", $baseTime)))) :
  194. strtotime($offset . " weeks", strtotime(date('Y-m-d 23:59:59', strtotime("+" . (6 - ($weekIndex ? $weekIndex - 1 : 6)) . " days", $baseTime))));
  195. break;
  196. case 'month':
  197. $_timestamp = mktime(0, 0, 0, $month + $offset, 1, $year);
  198. $time = $position ? $_timestamp : mktime(23, 59, 59, $month + $offset, self::days_in_month(date("m", $_timestamp), date("Y", $_timestamp)), $year);
  199. break;
  200. case 'quarter':
  201. $quarter = ceil(date('n', $baseTime) / 3) + $offset;
  202. $month = $quarter * 3;
  203. $offset_year = ceil($month / 12) - 1;
  204. $year = $year + $offset_year;
  205. $month = $month - ($offset_year * 12);
  206. $time = $position ?
  207. mktime(0, 0, 0, $month - 2, 1, $year) :
  208. mktime(23, 59, 59, $month, self::days_in_month($month, $year), $year);
  209. break;
  210. case 'year':
  211. $time = $position ? mktime(0, 0, 0, 1, 1, $year + $offset) : mktime(23, 59, 59, 12, 31, $year + $offset);
  212. break;
  213. default:
  214. $time = mktime($hour, $minute, 0, $month, $day, $year);
  215. break;
  216. }
  217. return $time;
  218. }
  219. /**
  220. * 获取指定年月拥有的天数
  221. * @param int $month
  222. * @param int $year
  223. * @return false|int|string
  224. */
  225. public static function days_in_month($month, $year)
  226. {
  227. if (function_exists("cal_days_in_month")) {
  228. return cal_days_in_month(CAL_GREGORIAN, $month, $year);
  229. } else {
  230. return date('t', mktime(0, 0, 0, $month, 1, $year));
  231. }
  232. }
  233. }