1<?php 2/** 3 * Copyright 2004-2017 Horde LLC (http://www.horde.org/) 4 * 5 * See the enclosed file LICENSE for license information (LGPL). If you 6 * did not receive this file, see http://www.horde.org/licenses/lgpl21. 7 * 8 * @author Chuck Hagenbuch <chuck@horde.org> 9 * @category Horde 10 * @license http://www.horde.org/licenses/lgpl21 LGPL 11 * @package Date 12 */ 13 14/** 15 * Horde Date wrapper/logic class, including some calculation 16 * functions. 17 * 18 * @author Chuck Hagenbuch <chuck@horde.org> 19 * @category Horde 20 * @copyright 2004-2017 Horde LLC 21 * @license http://www.horde.org/licenses/lgpl21 LGPL 22 * @package Date 23 */ 24class Horde_Date_Utils 25{ 26 /** 27 * Returns whether a year is a leap year. 28 * 29 * @param integer $year The year. 30 * 31 * @return boolean True if the year is a leap year. 32 */ 33 public static function isLeapYear($year) 34 { 35 return ($year % 4 == 0 && $year % 100 != 0) || $year % 400 == 0; 36 } 37 38 /** 39 * Returns the date of the year that corresponds to the first day of the 40 * given week. 41 * 42 * @param integer $week The week of the year to find the first day of. 43 * @param integer $year The year to calculate for. 44 * 45 * @return Horde_Date The date of the first day of the given week. 46 */ 47 public static function firstDayOfWeek($week, $year) 48 { 49 return new Horde_Date(sprintf('%04dW%02d', $year, $week)); 50 } 51 52 /** 53 * Returns the number of days in the specified month. 54 * 55 * @param integer $month The month 56 * @param integer $year The year. 57 * 58 * @return integer The number of days in the month. 59 */ 60 public static function daysInMonth($month, $year) 61 { 62 static $cache = array(); 63 if (!isset($cache[$year][$month])) { 64 try { 65 $date = new DateTime(sprintf($year < 0 ? '%05d-%02d-01' : '%04d-%02d-01', $year, $month)); 66 } catch (Exception $e) { 67 throw new Horde_Date_Exception($e); 68 } 69 $cache[$year][$month] = $date->format('t'); 70 } 71 return $cache[$year][$month]; 72 } 73 74 /** 75 * Returns a relative, natural language representation of a timestamp 76 * 77 * @todo Wider range of values ... maybe future time as well? 78 * @todo Support minimum resolution parameter. 79 * 80 * @param mixed $time The time. Any format accepted by Horde_Date. 81 * @param string $date_format Format to display date if timestamp is 82 * more then 1 day old. 83 * @param string $time_format Format to display time if timestamp is 1 84 * day old. 85 * 86 * @return string The relative time (i.e. 2 minutes ago) 87 */ 88 public static function relativeDateTime($time, $date_format = '%x', 89 $time_format = '%X') 90 { 91 $date = new Horde_Date($time); 92 93 $delta = time() - $date->timestamp(); 94 if ($delta < 60) { 95 return sprintf(Horde_Date_Translation::ngettext("%d second ago", "%d seconds ago", $delta), $delta); 96 } 97 98 $delta = round($delta / 60); 99 if ($delta < 60) { 100 return sprintf(Horde_Date_Translation::ngettext("%d minute ago", "%d minutes ago", $delta), $delta); 101 } 102 103 $delta = round($delta / 60); 104 if ($delta < 24) { 105 return sprintf(Horde_Date_Translation::ngettext("%d hour ago", "%d hours ago", $delta), $delta); 106 } 107 108 if ($delta > 24 && $delta < 48) { 109 $date = new Horde_Date($time); 110 return sprintf(Horde_Date_Translation::t("yesterday at %s"), $date->strftime($time_format)); 111 } 112 113 $delta = round($delta / 24); 114 if ($delta < 7) { 115 return sprintf(Horde_Date_Translation::t("%d days ago"), $delta); 116 } 117 118 if (round($delta / 7) < 5) { 119 $delta = round($delta / 7); 120 return sprintf(Horde_Date_Translation::ngettext("%d week ago", "%d weeks ago", $delta), $delta); 121 } 122 123 // Default to the user specified date format. 124 return $date->strftime($date_format); 125 } 126 127 /** 128 * Tries to convert strftime() formatters to date() formatters. 129 * 130 * Unsupported formatters will be removed. 131 * 132 * @param string $format A strftime() formatting string. 133 * 134 * @return string A date() formatting string. 135 */ 136 public static function strftime2date($format) 137 { 138 $replace = array( 139 '/%a/' => 'D', 140 '/%A/' => 'l', 141 '/%d/' => 'd', 142 '/%e/' => 'j', 143 '/%j/' => 'z', 144 '/%u/' => 'N', 145 '/%w/' => 'w', 146 '/%U/' => '', 147 '/%V/' => 'W', 148 '/%W/' => '', 149 '/%b/' => 'M', 150 '/%B/' => 'F', 151 '/%h/' => 'M', 152 '/%m/' => 'm', 153 '/%C/' => '', 154 '/%g/' => '', 155 '/%G/' => 'o', 156 '/%y/' => 'y', 157 '/%Y/' => 'Y', 158 '/%H/' => 'H', 159 '/%I/' => 'h', 160 '/%i/' => 'g', 161 '/%M/' => 'i', 162 '/%p/' => 'A', 163 '/%P/' => 'a', 164 '/%r/' => 'h:i:s A', 165 '/%R/' => 'H:i', 166 '/%S/' => 's', 167 '/%T/' => 'H:i:s', 168 '/%X/e' => 'Horde_Date_Utils::strftime2date(Horde_Nls::getLangInfo(T_FMT))', 169 '/%z/' => 'O', 170 '/%Z/' => '', 171 '/%c/' => '', 172 '/%D/' => 'm/d/y', 173 '/%F/' => 'Y-m-d', 174 '/%s/' => 'U', 175 '/%x/e' => 'Horde_Date_Utils::strftime2date(Horde_Nls::getLangInfo(D_FMT))', 176 '/%n/' => "\n", 177 '/%t/' => "\t", 178 '/%%/' => '%' 179 ); 180 181 return preg_replace(array_keys($replace), array_values($replace), $format); 182 } 183 184} 185