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) { |
|
|
|
|
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); |
|
|
|
|
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)) |
|
|
|
|
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; |
|
|
|
|
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!=
, orswitch
conditions), values of different types might be equal.For
string
values, the empty string''
is a special case, in particular the following results might be unexpected: