dedalozzo /
tool-bag
| 1 | <?php |
||||
| 2 | |||||
| 3 | /** |
||||
| 4 | * @file TimeHelper.php |
||||
| 5 | * @brief This file contains the TimeHelper class. |
||||
| 6 | * @details |
||||
| 7 | * @author Filippo F. Fadda |
||||
| 8 | */ |
||||
| 9 | |||||
| 10 | |||||
| 11 | namespace ToolBag\Helper; |
||||
| 12 | |||||
| 13 | |||||
| 14 | /** |
||||
| 15 | * @brief This class contains routines to handle time. |
||||
| 16 | * @nosubgrouping |
||||
| 17 | */ |
||||
| 18 | class TimeHelper { |
||||
| 19 | |||||
| 20 | /** @name Time Periods */ |
||||
| 21 | //!@{ |
||||
| 22 | const TODAY = "today"; |
||||
| 23 | const YESTERDAY = "yesterday"; |
||||
| 24 | const THIS_WEEK = "this-week"; |
||||
| 25 | const LAST_WEEK = "last-week"; |
||||
| 26 | const THIS_MONTH = "this-month"; |
||||
| 27 | const LAST_MONTH = "last-month"; |
||||
| 28 | const THIS_YEAR = "this-year"; |
||||
| 29 | const LAST_YEAR = "last-year"; |
||||
| 30 | const ALL_TIME = "all-time"; |
||||
| 31 | //!@} |
||||
| 32 | |||||
| 33 | |||||
| 34 | /** @name Time Periods Array */ |
||||
| 35 | //!@{ |
||||
| 36 | public static $periods = array( // Cannot use [] syntax otherwise Doxygen generates a warning. |
||||
| 37 | self::ALL_TIME => NULL, |
||||
| 38 | self::THIS_YEAR => NULL, |
||||
| 39 | self::LAST_YEAR => NULL, |
||||
| 40 | self::THIS_MONTH => NULL, |
||||
| 41 | self::LAST_MONTH => NULL, |
||||
| 42 | self::THIS_WEEK => NULL, |
||||
| 43 | self::LAST_WEEK => NULL, |
||||
| 44 | self::TODAY => NULL, |
||||
| 45 | self::YESTERDAY => NULL |
||||
| 46 | ); |
||||
| 47 | //!@} |
||||
| 48 | |||||
| 49 | |||||
| 50 | /** |
||||
| 51 | * @brief Returns an associative array with the elapsed time, from the provided timestamp, in days, hours, minutes and |
||||
| 52 | * seconds. |
||||
| 53 | * @param string $timestamp A timestamp in seconds/microseconds. |
||||
| 54 | * @param string $micro When `true` the timestamp is expressed in microseconds otherwise in seconds. |
||||
| 55 | * @return array An associative array |
||||
| 56 | */ |
||||
| 57 | public static function since($timestamp, $micro = FALSE) { |
||||
| 58 | $microsecondsInASecond = 1000000; |
||||
| 59 | $secondsInAMinute = 60; |
||||
| 60 | $secondsInAnHour = 60 * $secondsInAMinute; |
||||
| 61 | $secondsInADay = 24 * $secondsInAnHour; |
||||
| 62 | |||||
| 63 | if ($micro) { |
||||
|
0 ignored issues
–
show
|
|||||
| 64 | // Gets the current timestamp in microseconds. |
||||
| 65 | $now = microtime(TRUE); |
||||
| 66 | |||||
| 67 | // Subtracts from the current timestamp the last timestamp server was started. |
||||
| 68 | $microseconds = ($now * $microsecondsInASecond) - (float)$timestamp; |
||||
| 69 | |||||
| 70 | // Converts microseconds in seconds. |
||||
| 71 | $seconds = floor($microseconds / $microsecondsInASecond); |
||||
| 72 | } |
||||
| 73 | else { |
||||
| 74 | // Calculates difference in seconds. |
||||
| 75 | $seconds = time() - $timestamp; |
||||
| 76 | } |
||||
| 77 | |||||
| 78 | // Extracts days. |
||||
| 79 | $days = (int)floor($seconds / $secondsInADay); |
||||
| 80 | |||||
| 81 | // Extracts hours. |
||||
| 82 | $hourSeconds = $seconds % $secondsInADay; |
||||
| 83 | $hours = (int)floor($hourSeconds / $secondsInAnHour); |
||||
| 84 | |||||
| 85 | // Extracts minutes. |
||||
| 86 | $minuteSeconds = $hourSeconds % $secondsInAnHour; |
||||
| 87 | $minutes = (int)floor($minuteSeconds / $secondsInAMinute); |
||||
| 88 | |||||
| 89 | // Extracts the remaining seconds. |
||||
| 90 | $remainingSeconds = $minuteSeconds % $secondsInAMinute; |
||||
| 91 | $seconds = (int)ceil($remainingSeconds); |
||||
| 92 | |||||
| 93 | $time = []; |
||||
| 94 | $time['days'] = $days; |
||||
| 95 | $time['hours'] = $hours; |
||||
| 96 | $time['minutes'] = $minutes; |
||||
| 97 | $time['seconds'] = $seconds; |
||||
| 98 | |||||
| 99 | return $time; |
||||
| 100 | } |
||||
| 101 | |||||
| 102 | |||||
| 103 | /** |
||||
| 104 | * @brief Checks if the provided string represents a period of time and returns it if exists otherwise returns `false`. |
||||
| 105 | * @param string $str A human readable period of time. |
||||
| 106 | * @return int|bool If the period of time exists returns it, else returns `false`. In case `$str` is `null`, returns |
||||
| 107 | * `all_time`. |
||||
| 108 | */ |
||||
| 109 | public static function period($str) { |
||||
| 110 | return is_null($str) ? self::ALL_TIME : ArrayHelper::key($str, self::$periods); |
||||
|
0 ignored issues
–
show
|
|||||
| 111 | } |
||||
| 112 | |||||
| 113 | |||||
| 114 | /** |
||||
| 115 | * @brief Returns a measure of the time passed since the provided timestamp. In case is passed more than a day, |
||||
| 116 | * returns a human readable date. |
||||
| 117 | * @param int $timestamp A timestamp in seconds. |
||||
| 118 | * @param bool $showTime When `true` returns also the time passed in case of an event occurred in the past. |
||||
| 119 | * @return string |
||||
| 120 | */ |
||||
| 121 | public static function when($timestamp, $showTime = TRUE) { |
||||
| 122 | $today = date('Ymd'); |
||||
| 123 | |||||
| 124 | // Today. |
||||
| 125 | if ($today == date('Ymd', $timestamp)) { |
||||
| 126 | $time = self::since($timestamp); |
||||
| 127 | |||||
| 128 | if ($time['hours'] > 1) |
||||
| 129 | return sprintf('%d hours ago', $time['hours']); |
||||
| 130 | elseif ($time['hours'] == 1) |
||||
| 131 | return "one hour ago"; |
||||
| 132 | elseif ($time['minutes'] > 1) |
||||
| 133 | return sprintf('%d minutes ago', $time['minutes']); |
||||
| 134 | elseif ($time['minutes'] == 1) |
||||
| 135 | return "one minute ago"; |
||||
| 136 | elseif ($time['seconds'] > 1) |
||||
| 137 | return sprintf('%d seconds ago', $time['seconds']); |
||||
| 138 | else // $time['seconds'] == 1 |
||||
| 139 | return "one second ago"; |
||||
| 140 | } |
||||
| 141 | // Yesterday. |
||||
| 142 | elseif (strtotime('-1 day', $today) == date('Ymd', $timestamp)) |
||||
|
0 ignored issues
–
show
$today of type string is incompatible with the type integer expected by parameter $now of strtotime().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 143 | return "yesterday"; |
||||
| 144 | // In the past. |
||||
| 145 | else |
||||
| 146 | return $showTime ? date('d/m/Y H:i', $timestamp) : date('d/m/Y', $timestamp); |
||||
| 147 | } |
||||
| 148 | |||||
| 149 | |||||
| 150 | /** |
||||
| 151 | * @brief Given a constant representing a period, returns a formatted string. |
||||
| 152 | * @param int $periodInTime A period in time. |
||||
| 153 | * @param string $prefix A string prefix. |
||||
| 154 | * @param string $postfix A string postfix. |
||||
| 155 | * @return string |
||||
| 156 | */ |
||||
| 157 | public static function aWhileBack($periodInTime, $prefix = "", $postfix = "") { |
||||
| 158 | $date = new \DateTime(); |
||||
| 159 | |||||
| 160 | switch ($periodInTime) { |
||||
| 161 | case self::TODAY: |
||||
| 162 | $format = $date->format("Ymd"); |
||||
| 163 | break; |
||||
| 164 | case self::YESTERDAY: |
||||
| 165 | $date->modify('yesterday'); |
||||
| 166 | $format = $date->format("Ymd"); |
||||
| 167 | break; |
||||
| 168 | case self::THIS_WEEK: |
||||
| 169 | $format = $date->format("Y_W"); |
||||
| 170 | break; |
||||
| 171 | case self::LAST_WEEK; |
||||
| 172 | $date->modify('last week'); |
||||
| 173 | $format = $date->format("Y_W"); |
||||
| 174 | break; |
||||
| 175 | case self::THIS_MONTH; |
||||
| 176 | $format = $date->format("Ym"); |
||||
| 177 | break; |
||||
| 178 | case self::LAST_MONTH; |
||||
| 179 | $date->modify('last month'); |
||||
| 180 | $format = $date->format("Ym"); |
||||
| 181 | break; |
||||
| 182 | case self::THIS_YEAR; |
||||
| 183 | $format = $date->format("Y"); |
||||
| 184 | break; |
||||
| 185 | case self::LAST_YEAR: |
||||
| 186 | $date->modify('last year'); |
||||
| 187 | $format = $date->format("Y"); |
||||
| 188 | break; |
||||
| 189 | default: // EVER |
||||
| 190 | $format = ""; |
||||
| 191 | } |
||||
| 192 | |||||
| 193 | return empty($format) ? $format : $prefix.$format.$postfix; |
||||
|
0 ignored issues
–
show
|
|||||
| 194 | } |
||||
| 195 | |||||
| 196 | |||||
| 197 | /** |
||||
| 198 | * @brief Given a constant representing a period, returns a range of timestamps (minimum and maximum) for that period. |
||||
| 199 | * @param int $periodInTime A period in time. |
||||
| 200 | * @param[out] \DateTime $minTimestamp The minimum date in the period. |
||||
| 201 | * @param[out] \DateTime $maxTimestamp The maximum date in the period. |
||||
| 202 | */ |
||||
| 203 | public static function minMaxInPeriod($periodInTime, &$minTimestamp, &$maxTimestamp) { |
||||
| 204 | switch ($periodInTime) { |
||||
| 205 | case self::TODAY: |
||||
| 206 | $minTimestamp = strtotime('midnight'); |
||||
| 207 | $maxTimestamp = time(); |
||||
| 208 | break; |
||||
| 209 | case self::YESTERDAY: |
||||
| 210 | $minTimestamp = strtotime('yesterday'); |
||||
| 211 | $maxTimestamp = strtotime('midnight') - 1; |
||||
| 212 | break; |
||||
| 213 | case self::THIS_WEEK: |
||||
| 214 | $minTimestamp = strtotime('last monday'); |
||||
| 215 | $maxTimestamp = time(); |
||||
| 216 | break; |
||||
| 217 | case self::LAST_WEEK; |
||||
| 218 | $minTimestamp = strtotime('Monday last week'); |
||||
| 219 | $maxTimestamp = strtotime('Monday this week') - 1; |
||||
| 220 | break; |
||||
| 221 | case self::THIS_MONTH; |
||||
| 222 | $minTimestamp = strtotime('first day of this month midnight'); |
||||
| 223 | $maxTimestamp = time(); |
||||
| 224 | break; |
||||
| 225 | case self::LAST_MONTH; |
||||
| 226 | $minTimestamp = strtotime('first day of last month midnight'); |
||||
| 227 | $maxTimestamp = strtotime('first day of this month midnight') - 1; |
||||
| 228 | break; |
||||
| 229 | case self::THIS_YEAR; |
||||
| 230 | $minTimestamp = strtotime('first day of January midnight'); |
||||
| 231 | $maxTimestamp = time(); |
||||
| 232 | break; |
||||
| 233 | case self::LAST_YEAR: |
||||
| 234 | $minTimestamp = strtotime('first day of January last year midnight'); |
||||
| 235 | $maxTimestamp = strtotime('first day of January this year midnight') - 1; |
||||
| 236 | break; |
||||
| 237 | default: // EVER |
||||
| 238 | $minTimestamp = 0; |
||||
| 239 | $maxTimestamp = new \stdClass(); |
||||
| 240 | } |
||||
| 241 | } |
||||
| 242 | |||||
| 243 | |||||
| 244 | /** |
||||
| 245 | * @brief Given a period of time (an year, a month or a day), calculates the date limits for that period. |
||||
| 246 | * @param[out] \DateTime $minDate The minimum date in the period. |
||||
| 247 | * @param[out] \DateTime $maxDate The maximum date in the period. |
||||
| 248 | * @param string $year An year. |
||||
| 249 | * @param string $month (optional) A month. |
||||
| 250 | * @param string $day (optional) A day. |
||||
| 251 | */ |
||||
| 252 | public static function dateLimits(&$minDate, &$maxDate, $year, $month = NULL, $day = NULL) { |
||||
| 253 | $aDay = (is_null($day)) ? 1 : (int)$day; |
||||
| 254 | $aMonth = (is_null($month)) ? 1 : (int)$month; |
||||
| 255 | $aYear = (int)$year; |
||||
| 256 | |||||
| 257 | $minDate = (new \DateTime())->setDate($aYear, $aMonth, $aDay)->modify('midnight'); |
||||
| 258 | $maxDate = clone($minDate); |
||||
| 259 | |||||
| 260 | if (isset($day)) |
||||
| 261 | $maxDate->modify('tomorrow')->modify('last second'); |
||||
| 262 | elseif (isset($month)) |
||||
| 263 | $maxDate->modify('last day of this month')->modify('last second'); |
||||
| 264 | else |
||||
| 265 | $maxDate->setDate($aYear, 12, 31)->modify('last second'); |
||||
| 266 | } |
||||
| 267 | |||||
| 268 | } |
In PHP, under loose comparison (like
==, or!=, orswitchconditions), values of different types might be equal.For
stringvalues, the empty string''is a special case, in particular the following results might be unexpected: