1<?php
2/*
3 +-------------------------------------------------------------------------+
4 | Copyright (C) 2004-2021 The Cacti Group                                 |
5 |                                                                         |
6 | This program is free software; you can redistribute it and/or           |
7 | modify it under the terms of the GNU General Public License             |
8 | as published by the Free Software Foundation; either version 2          |
9 | of the License, or (at your option) any later version.                  |
10 |                                                                         |
11 | This program is distributed in the hope that it will be useful,         |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of          |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           |
14 | GNU General Public License for more details.                            |
15 +-------------------------------------------------------------------------+
16 | Cacti: The Complete RRDtool-based Graphing Solution                     |
17 +-------------------------------------------------------------------------+
18 | This code is designed, written, and maintained by the Cacti Group. See  |
19 | about.php and/or the AUTHORS file for specific developer information.   |
20 +-------------------------------------------------------------------------+
21 | http://www.cacti.net/                                                   |
22 +-------------------------------------------------------------------------+
23*/
24
25/* get_timespan		 		- returns start/end time for given date and timespan
26 * 							  do NOT use absolute numbers of seconds but let php
27 * 							  do all the time calculations to cover:
28 * 							  leap years, daylight savings and weekdays ...
29   @arg $span				- array &$timespan (begin_now, end_now)
30   @arg $curr_time	 		- base date (time since epoch)
31   @arg $timespan_given		- timespan as given by global_arrays.php($graph_timespans)
32   @arg $first_weekdayid	- first weekday (numeric representation) */
33function get_timespan(&$span, $curr_time, $timespan_given, $first_weekdayid) {
34	# unless changed later, $span['end_now'] is always $curr_time
35	$span['begin_now'] 	= $curr_time; # initialization only!
36	$span['end_now'] 	= $curr_time;
37
38	switch ($timespan_given)  {
39		case GT_LAST_HALF_HOUR:
40			$span['begin_now'] = strtotime('-30 minutes', $curr_time);
41			break;
42		case GT_LAST_HOUR:
43			$span['begin_now'] = strtotime('-1 hour', $curr_time);
44			break;
45		case GT_LAST_2_HOURS:
46			$span['begin_now'] = strtotime('-2 hours', $curr_time);
47			break;
48		case GT_LAST_4_HOURS:
49			$span['begin_now'] = strtotime('-4 hours', $curr_time);
50			break;
51		case GT_LAST_6_HOURS:
52			$span['begin_now'] = strtotime('-6 hours', $curr_time);
53			break;
54		case GT_LAST_12_HOURS:
55			$span['begin_now'] = strtotime('-12 hours', $curr_time);
56			break;
57		case GT_LAST_DAY:
58			$span['begin_now'] = strtotime('-1 day', $curr_time);
59			break;
60		case GT_LAST_2_DAYS:
61			$span['begin_now'] = strtotime('-2 days', $curr_time);
62			break;
63		case GT_LAST_3_DAYS:
64			$span['begin_now'] = strtotime('-3 days', $curr_time);
65			break;
66		case GT_LAST_4_DAYS:
67			$span['begin_now'] = strtotime('-4 days', $curr_time);
68			break;
69		case GT_LAST_WEEK:
70			$span['begin_now'] = strtotime('-1 week', $curr_time);
71			break;
72		case GT_LAST_2_WEEKS:
73			$span['begin_now'] = strtotime('-2 weeks', $curr_time);
74			break;
75		case GT_LAST_MONTH:
76			$span['begin_now'] = strtotime('-1 month', $curr_time);
77			break;
78		case GT_LAST_2_MONTHS:
79			$span['begin_now'] = strtotime('-2 months', $curr_time);
80			break;
81		case GT_LAST_3_MONTHS:
82			$span['begin_now'] = strtotime('-3 months', $curr_time);
83			break;
84		case GT_LAST_4_MONTHS:
85			$span['begin_now'] = strtotime('-4 months', $curr_time);
86			break;
87		case GT_LAST_6_MONTHS:
88			$span['begin_now'] = strtotime('-6 months', $curr_time);
89			break;
90		case GT_LAST_YEAR:
91			$span['begin_now'] = strtotime('-1 year', $curr_time);
92			break;
93		case GT_LAST_2_YEARS:
94			$span['begin_now'] = strtotime('-2 years', $curr_time);
95			break;
96		case GT_DAY_SHIFT:
97			# take this day, start and end time fetched from config_settings
98			$span['begin_now'] = strtotime(date('Y-m-d', $curr_time) . ' ' . read_user_setting('day_shift_start'));
99			$span['end_now']   = strtotime(date('Y-m-d', $curr_time) . ' ' . read_user_setting('day_shift_end'));
100			break;
101		case GT_THIS_DAY:
102			# return Year-Month-Day for given 'time since epoch'
103			# and convert this to 'time since epoch' (Hour:Minute:Second set to 00:00:00)
104			$span['begin_now'] = strtotime(date('Y-m-d', $curr_time));
105			$span['end_now']   = strtotime('+1 day', $span['begin_now']) - 1;
106			break;
107		case GT_THIS_WEEK:
108			# compute offset to start-of-week
109			# remember: start-of-week may be > current-weekday, so do modulo calc
110			$offset = (date('w',$curr_time) - $first_weekdayid + 7) % 7;
111			$span['begin_now'] = strtotime( '-' . $offset . ' days' . date('Y-m-d', $curr_time));
112			$span['end_now']   = strtotime('+1 week', $span['begin_now']) - 1;
113			break;
114		case GT_THIS_MONTH:
115			# this date format set day-of-month to 01
116			$span['begin_now'] = strtotime(date('Y-m-01', $curr_time));
117			$span['end_now']   = strtotime('+1 month', $span['begin_now']) - 1;
118			break;
119		case GT_THIS_YEAR:
120			# this date format set day-of-month to 01 and month-of-year to 01
121			$span['begin_now'] = strtotime(date('Y-01-01', $curr_time));
122			$span['end_now']   = strtotime('+1 year', $span['begin_now']) - 1;
123			break;
124		case GT_PREV_DAY:
125			$span['begin_now'] = strtotime('-1 day' . date('Y-m-d', $curr_time));
126			$span['end_now']   = strtotime('+1 day', $span['begin_now']) - 1;
127			break;
128		case GT_PREV_WEEK:
129			# compute offset to start-of-week
130			# remember: start-of-week may be > current-weekday, so do modulo calc
131			$offset = (date('w',$curr_time) - $first_weekdayid + 7) % 7;
132			$span['begin_now'] = strtotime( '-1 week -' . $offset . ' days' . date('Y-m-d', $curr_time));
133			$span['end_now']   = strtotime('+1 week', $span['begin_now']) - 1;
134			break;
135		case GT_PREV_MONTH:
136			$span['begin_now'] = strtotime('-1 month' . date('Y-m-01', $curr_time));
137			$span['end_now']   = strtotime('+1 month', $span['begin_now']) - 1;
138			break;
139		case GT_PREV_YEAR:
140			$span['begin_now'] = strtotime('-1 year' . date('Y-01-01', $curr_time));
141			$span['end_now']   = strtotime('+1 year', $span['begin_now']) - 1;
142			break;
143		default:
144			$span['begin_now'] = $curr_time - DEFAULT_TIMESPAN;
145			break;
146	}
147
148	# reformat time-since-epoch start/end times to human readable format
149	$span['current_value_date1'] = date('Y-m-d H:i',$span['begin_now']);
150	$span['current_value_date2'] = date('Y-m-d H:i',$span['end_now']);
151}
152
153/* month_shift		- check for shifting one or more months
154 * @arg $shift_size	- requested shift amount
155 * returns			- true, if month shifting required, else false
156 */
157function month_shift($shift_size) {
158	# is monthly shifting required?
159	return ( strpos(strtolower($shift_size), 'month') > 0);
160}
161
162/* check_month_boundaries 	- check given boundaries for begin/end of month matching
163 * @arg $span				- array $timespan with given boundaries
164 * returns					- true, if begin AND end match month begin/end boundaries
165 */
166function check_month_boundaries(&$span) {
167	# check left boundary -----------------------------------------------
168	$begin_of_month = strtotime(date('Y-m-01', $span['begin_now']));
169	$begin_match 	= ( $begin_of_month == $span['begin_now']);
170
171	# check right boundary ----------------------------------------------
172	# first, get a defined date of the month, $span['end_now'] belongs to
173	$begin_of_month = strtotime(date('Y-m-01', $span['end_now']));
174	# do "end of month" magic to get end_of_month for arbitrary months
175	$end_of_month = strtotime('+1 month', $begin_of_month) - 1;
176
177	# accept end of month if no seconds given (adjust for 59 missing seconds)
178	$end_match = ( (($end_of_month - 59) <= $span['end_now']) && ($span['end_now'] <= $end_of_month));
179
180	return ( $begin_match && $end_match );
181}
182
183/* shift_right_boundary	- shift right boundary with end-of-month adjustment
184 * @arg $span			- timespan array
185 * @arg $direction		- shift left/right (-/+)
186 * @arg $shift_size		- amount of shift
187 * returns				- time-since-epoch for shifted right boundary
188 */
189function shift_right_boundary(&$span, $direction, $shift_size) {
190	# first, get begin of the month, $span['end_now'] belongs to
191	$begin = date('Y-m-01', $span['end_now']);
192
193	# shift the begin date to correct month
194	$begin_of_shifted_month	= strtotime($direction . $shift_size . ' ' . $begin);
195
196	# do "end of month" magic
197	return strtotime('+1 month', $begin_of_shifted_month) - 1;
198}
199
200/* shift_time		- shift given timespan left/right
201 * @arg &$span		- given timespan (start/end time as time-since-epoch and human readable)
202 * @arg $direction	- "-" for shifting left, "+" for shifting right
203 * @arg $timeshift	- amount of shifting
204 */
205function shift_time(&$span, $direction, $shift_size) {
206	# move left/right according to $direction
207	# amount to be moved is derived from $shift_size
208	# base dates are taken from array $span
209
210	# is this a month shift AND current timespane is on month boundaries?
211	if ( month_shift($shift_size) && check_month_boundaries($span) ) {
212		# shift left boundary
213		$span['begin_now'] 	= strtotime($direction . $shift_size . ' ' . $span['current_value_date1']);
214		# shifting right boundary is somewhat complicated
215		$span['end_now'] 	= shift_right_boundary($span, $direction, $shift_size);
216	} else {
217		# 'normal' time shifting: use strtotime magic
218		$span['begin_now'] 	= strtotime($direction . $shift_size . ' ' . $span['current_value_date1']);
219		$span['end_now'] 	= strtotime($direction . $shift_size . ' ' . $span['current_value_date2']);
220	}
221
222	# convert to human readable format
223	$span['current_value_date1'] = date('Y-m-d H:i', $span['begin_now']);
224	$span['current_value_date2'] = date('Y-m-d H:i', $span['end_now']);
225
226	# now custom time settings in effect
227	$_SESSION['sess_current_timespan'] = GT_CUSTOM;
228	$_SESSION['custom'] = 1;
229	set_request_var('predefined_timespan', GT_CUSTOM);
230}
231
232