forked from backdrop-contrib/facetapi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
facetapi.date.inc
311 lines (279 loc) · 8.71 KB
/
facetapi.date.inc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
<?php
/**
* @file
* Date handling functions.
*/
/**
* Helper function to convert dates from Unix timestamps into ISO 8601 format.
*
* @param $timestamp
* An integer containing the Unix timestamp being converted.
* @param $gap
* A string containing the gap, see FACETAPI_DATE_* constants for valid
* values. Defaults to FACETAPI_DATE_SECOND.
*
* @return
* A string containing the date in ISO 8601 format.
*/
function facetapi_isodate($timestamp, $gap = FACETAPI_DATE_SECOND) {
switch ($gap) {
case FACETAPI_DATE_SECOND:
$format = FACETAPI_DATE_ISO8601;
break;
case FACETAPI_DATE_MINUTE:
$format = 'Y-m-d\TH:i:00\Z';
break;
case FACETAPI_DATE_HOUR:
$format = 'Y-m-d\TH:00:00\Z';
break;
case FACETAPI_DATE_DAY:
$format = 'Y-m-d\T00:00:00\Z';
break;
case FACETAPI_DATE_MONTH:
$format = 'Y-m-01\T00:00:00\Z';
break;
case FACETAPI_DATE_YEAR:
$format = 'Y-01-01\T00:00:00\Z';
break;
default:
$format = FACETAPI_DATE_ISO8601;
break;
}
return gmdate($format, $timestamp);
}
/**
* Return a date gap one increment smaller than the one passed.
*
* @param $gap
* A string containing the gap, see FACETAPI_DATE_* constants for valid
* values.
* @param $min_gap
* A string containing the the minimum gap that can be returned, defaults to
* FACETAPI_DATE_SECOND. This is useful for defining the smallest increment
* that can be used in a date drilldown.
*
* @return
* A string containing the smaller date gap, NULL if there is no smaller gap.
* See FACETAPI_DATE_* constants for valid values.
*/
function facetapi_get_next_date_gap($gap, $min_gap = FACETAPI_DATE_SECOND) {
// Array of numbers used to determine whether the next gap is smaller than
// the minimum gap allowed in the drilldown.
$gap_numbers = array(
FACETAPI_DATE_YEAR => 6,
FACETAPI_DATE_MONTH => 5,
FACETAPI_DATE_DAY => 4,
FACETAPI_DATE_HOUR => 3,
FACETAPI_DATE_MINUTE => 2,
FACETAPI_DATE_SECOND => 1,
);
// Gets gap numbers for both the gap and minimum gap, checks if the next gap
// is within the limit set by the $min_gap parameter.
$gap_num = isset($gap_numbers[$gap]) ? $gap_numbers[$gap] : 6;
$min_num = isset($gap_numbers[$min_gap]) ? $gap_numbers[$min_gap] : 1;
return ($gap_num > $min_num) ? array_search($gap_num - 1, $gap_numbers) : $min_gap;
}
/**
* Determines the best search gap to use for an arbitrary date range.
*
* Generally, we use the maximum gap that fits between the start and end date.
* If they are more than a year apart, 1 year; if they are more than a month
* apart, 1 month; etc.
*
* This function uses Unix timestamps for its computation and so is not useful
* for dates outside that range.
*
* @param int $start_time
* A string containing the start date as an ISO date string.
* @param int $end_time
* A string containing the end date as an ISO date string.
* @param string|NULL $min_gap
* (Optional) The minimum gap that should be returned.
*
* @return string
* A string containing the gap, see FACETAPI_DATE_* constants for valid
* values. Returns FALSE of either of the dates cannot be converted to a
* timestamp.
*/
function facetapi_get_timestamp_gap($start_time, $end_time, $min_gap = NULL) {
$time_diff = $end_time - $start_time;
switch (TRUE) {
// NOTE: 31536000 == 60 * 60 * 24 * 365
case ($time_diff >= 31536000):
$gap = FACETAPI_DATE_YEAR;
break;
case ($time_diff >= 86400 * gmdate('t', $start_time)):
$gap = FACETAPI_DATE_MONTH;
break;
case ($time_diff >= 86400):
$gap = FACETAPI_DATE_DAY;
break;
case ($time_diff >= 3600):
$gap = FACETAPI_DATE_HOUR;
break;
case ($time_diff >= 60):
$gap = FACETAPI_DATE_MINUTE;
break;
default:
$gap = FACETAPI_DATE_SECOND;
break;
}
// Return the calculated gap if a minimum gap was not passed of the calculated
// gap is a larger interval than the minimum gap.
if (null === $min_gap || facetapi_gap_compare($gap, $min_gap) >= 0) {
return $gap;
}
else {
return $min_gap;
}
}
/**
* Converts ISO date strings to Unix timestamps, passes values to the
* facetapi_get_timestamp_gap() function to calculate the gap.
*
* @param $start_date
* A string containing the start date as an ISO date string.
* @param $end_date
* A string containing the end date as an ISO date string.
* @param string|NULL $min_gap
* (Optional) The minimum gap that should be returned.
*
* @return string
* A string containing the gap, see FACETAPI_DATE_* constants for valid
* values. Returns FALSE of either of the dates cannot be converted to a
* timestamp.
*
* @see facetapi_get_timestamp_gap()
*/
function facetapi_get_date_gap($start_date, $end_date, $min_gap = NULL) {
$range = array(strtotime($start_date), strtotime($end_date));
if (!in_array(FALSE, $range, TRUE)) {
return facetapi_get_timestamp_gap($range[0], $range[1], $min_gap);
}
return FALSE;
}
/**
* Returns a formatted date based on the passed timestamp and gap.
*
* This function assumes that gaps less than one day will be displayed in a
* search context in which a larger containing gap including a day is already
* displayed. So, HOUR, MINUTE, and SECOND gaps only display time information,
* without date.
*
* @param $timestamp
* An integer containing the Unix timestamp.
* @param $gap
* A string containing the gap, see FACETAPI_DATE_* constants for valid
* values, defaults to YEAR.
*
* @return
* A gap-appropriate display date used in the facet link.
*/
function facetapi_format_timestamp($timestamp, $gap = FACETAPI_DATE_YEAR) {
switch ($gap) {
case FACETAPI_DATE_MONTH:
return format_date($timestamp, 'custom', 'F Y', 'UTC');
case FACETAPI_DATE_DAY:
return format_date($timestamp, 'custom', 'F j, Y', 'UTC');
case FACETAPI_DATE_HOUR:
return format_date($timestamp, 'custom', 'g A', 'UTC');
case FACETAPI_DATE_MINUTE:
return format_date($timestamp, 'custom', 'g:i A', 'UTC');
case FACETAPI_DATE_SECOND:
return format_date($timestamp, 'custom', 'g:i:s A', 'UTC');
default:
return format_date($timestamp, 'custom', 'Y', 'UTC');
}
}
/**
* Returns a formatted date based on the passed ISO date string and gap.
*
* @param $date
* A string containing the date as an ISO date string.
* @param $gap
* A string containing the gap, see FACETAPI_DATE_* constants for valid
* values, defaults to YEAR.
* @param $callback
* The formatting callback, defaults to "facetapi_format_timestamp".
*
* @return
* A gap-appropriate display date used in the facet link.
*
* @see facetapi_format_timestamp()
*/
function facetapi_format_date($date, $gap = FACETAPI_DATE_YEAR, $callback = 'facetapi_format_timestamp') {
$timestamp = strtotime($date);
return $callback($timestamp, $gap);
}
/**
* Returns the next increment from the given ISO date and gap. This function is
* useful for getting the upper limit of a date range from the given start
* date.
*
* @param $date
* A string containing the date as an ISO date string.
* @param $gap
* A string containing the gap, see FACETAPI_DATE_* constants for valid
* values, defaults to YEAR.
*
* @return
* A string containing the date, FALSE if the passed date could not be parsed.
*/
function facetapi_get_next_date_increment($date, $gap) {
if (preg_match(FACETAPI_REGEX_DATE, $date, $match)) {
// Increments the timestamp.
switch ($gap) {
case FACETAPI_DATE_MONTH:
$match[2] += 1;
break;
case FACETAPI_DATE_DAY:
$match[3] += 1;
break;
case FACETAPI_DATE_HOUR:
$match[4] += 1;
break;
case FACETAPI_DATE_MINUTE:
$match[5] += 1;
break;
case FACETAPI_DATE_SECOND:
$match[6] += 1;
break;
default:
$match[1] += 1;
break;
}
// Gets the next increment.
return facetapi_isodate(
gmmktime($match[4], $match[5], $match[6], $match[2], $match[3], $match[1])
);
}
return FALSE;
}
/**
* Compares two timestamp gaps.
*
* @param string $gap1
* @param string $gap2
*
* @return int
* Returns -1 if gap1 is less than gap2, 1 if gap1 is greater than gap2, and 0
* if they are equal.
*/
function facetapi_gap_compare($gap1, $gap2) {
$gap_numbers = array(
FACETAPI_DATE_YEAR => 6,
FACETAPI_DATE_MONTH => 5,
FACETAPI_DATE_DAY => 4,
FACETAPI_DATE_HOUR => 3,
FACETAPI_DATE_MINUTE => 2,
FACETAPI_DATE_SECOND => 1,
);
$gap1_num = isset($gap_numbers[$gap1]) ? $gap_numbers[$gap1] : 6;
$gap2_num = isset($gap_numbers[$gap2]) ? $gap_numbers[$gap2] : 6;
if ($gap1_num == $gap2_num) {
return 0;
}
else {
return ($gap1_num < $gap2_num) ? -1 : 1;
}
}