HuasoFoundries /
jpgraph
| 1 | <?php |
||||
| 2 | |||||
| 3 | /** |
||||
| 4 | * JPGraph v4.0.3 |
||||
| 5 | */ |
||||
| 6 | |||||
| 7 | namespace Amenadiel\JpGraph\Util; |
||||
| 8 | |||||
| 9 | /* |
||||
| 10 | * @class DateScaleUtils |
||||
| 11 | * // Description: Help to create a manual date scale |
||||
| 12 | */ |
||||
| 13 | 1 | define('DSUTILS_MONTH', 1); // Major and minor ticks on a monthly basis |
|||
| 14 | 1 | define('DSUTILS_MONTH1', 1); // Major and minor ticks on a monthly basis |
|||
| 15 | 1 | define('DSUTILS_MONTH2', 2); // Major ticks on a bi-monthly basis |
|||
| 16 | 1 | define('DSUTILS_MONTH3', 3); // Major icks on a tri-monthly basis |
|||
| 17 | 1 | define('DSUTILS_MONTH6', 4); // Major on a six-monthly basis |
|||
| 18 | 1 | define('DSUTILS_WEEK1', 5); // Major ticks on a weekly basis |
|||
| 19 | 1 | define('DSUTILS_WEEK2', 6); // Major ticks on a bi-weekly basis |
|||
| 20 | 1 | define('DSUTILS_WEEK4', 7); // Major ticks on a quod-weekly basis |
|||
| 21 | 1 | define('DSUTILS_DAY1', 8); // Major ticks on a daily basis |
|||
| 22 | 1 | define('DSUTILS_DAY2', 9); // Major ticks on a bi-daily basis |
|||
| 23 | 1 | define('DSUTILS_DAY4', 10); // Major ticks on a qoud-daily basis |
|||
| 24 | 1 | define('DSUTILS_YEAR1', 11); // Major ticks on a yearly basis |
|||
| 25 | 1 | define('DSUTILS_YEAR2', 12); // Major ticks on a bi-yearly basis |
|||
| 26 | 1 | define('DSUTILS_YEAR5', 13); // Major ticks on a five-yearly basis |
|||
| 27 | |||||
| 28 | class DateScaleUtils |
||||
| 29 | { |
||||
| 30 | public static $iMin = 0; |
||||
| 31 | public static $iMax = 0; |
||||
| 32 | |||||
| 33 | private static $starthour; |
||||
| 34 | private static $startmonth; |
||||
| 35 | private static $startday; |
||||
| 36 | private static $startyear; |
||||
| 37 | private static $endmonth; |
||||
| 38 | private static $endyear; |
||||
| 39 | private static $endday; |
||||
| 40 | private static $tickPositions = []; |
||||
| 41 | private static $minTickPositions = []; |
||||
| 42 | private static $iUseWeeks = true; |
||||
| 43 | |||||
| 44 | public static function UseWeekFormat($aFlg) |
||||
| 45 | { |
||||
| 46 | self::$iUseWeeks = $aFlg; |
||||
| 47 | } |
||||
| 48 | |||||
| 49 | 1 | public static function doYearly($aType, $aMinor = false) |
|||
| 50 | { |
||||
| 51 | 1 | $i = 0; |
|||
| 52 | 1 | $j = 0; |
|||
| 53 | 1 | $m = self::$startmonth; |
|||
| 54 | 1 | $y = self::$startyear; |
|||
| 55 | |||||
| 56 | 1 | if (self::$startday == 1) { |
|||
| 57 | self::$tickPositions[$i++] = mktime(0, 0, 0, $m, 1, $y); |
||||
| 58 | } |
||||
| 59 | 1 | ++$m; |
|||
| 60 | |||||
| 61 | switch ($aType) { |
||||
| 62 | 1 | case DSUTILS_YEAR1: |
|||
| 63 | for ($y = self::$startyear; $y <= self::$endyear; ++$y) { |
||||
| 64 | if ($aMinor) { |
||||
| 65 | while ($m <= 12) { |
||||
| 66 | if (!($y == self::$endyear && $m > self::$endmonth)) { |
||||
| 67 | self::$minTickPositions[$j++] = mktime(0, 0, 0, $m, 1, $y); |
||||
| 68 | } |
||||
| 69 | ++$m; |
||||
| 70 | } |
||||
| 71 | $m = 1; |
||||
| 72 | } |
||||
| 73 | self::$tickPositions[$i++] = mktime(0, 0, 0, 1, 1, $y); |
||||
| 74 | } |
||||
| 75 | |||||
| 76 | break; |
||||
| 77 | 1 | case DSUTILS_YEAR2: |
|||
| 78 | 1 | $y = self::$startyear; |
|||
| 79 | 1 | while ($y <= self::$endyear) { |
|||
| 80 | 1 | self::$tickPositions[$i++] = mktime(0, 0, 0, 1, 1, $y); |
|||
| 81 | 1 | for ($k = 0; $k < 1; ++$k) { |
|||
| 82 | 1 | ++$y; |
|||
| 83 | 1 | if ($aMinor) { |
|||
| 84 | self::$minTickPositions[$j++] = mktime(0, 0, 0, 1, 1, $y); |
||||
| 85 | } |
||||
| 86 | } |
||||
| 87 | 1 | ++$y; |
|||
| 88 | } |
||||
| 89 | |||||
| 90 | 1 | break; |
|||
| 91 | case DSUTILS_YEAR5: |
||||
| 92 | $y = self::$startyear; |
||||
| 93 | while ($y <= self::$endyear) { |
||||
| 94 | self::$tickPositions[$i++] = mktime(0, 0, 0, 1, 1, $y); |
||||
| 95 | for ($k = 0; $k < 4; ++$k) { |
||||
| 96 | ++$y; |
||||
| 97 | if ($aMinor) { |
||||
| 98 | self::$minTickPositions[$j++] = mktime(0, 0, 0, 1, 1, $y); |
||||
| 99 | } |
||||
| 100 | } |
||||
| 101 | ++$y; |
||||
| 102 | } |
||||
| 103 | |||||
| 104 | break; |
||||
| 105 | } |
||||
| 106 | 1 | } |
|||
| 107 | |||||
| 108 | public static function doDaily($aType, $aMinor = false) |
||||
| 109 | { |
||||
| 110 | $m = self::$startmonth; |
||||
| 111 | $y = self::$startyear; |
||||
| 112 | $d = self::$startday; |
||||
| 113 | $h = self::$starthour; |
||||
| 114 | $i = 0; |
||||
| 115 | $j = 0; |
||||
| 116 | |||||
| 117 | if ($h == 0) { |
||||
| 118 | self::$tickPositions[$i++] = mktime(0, 0, 0, $m, $d, $y); |
||||
| 119 | } |
||||
| 120 | $t = mktime(0, 0, 0, $m, $d, $y); |
||||
| 121 | |||||
| 122 | switch ($aType) { |
||||
| 123 | case DSUTILS_DAY1: |
||||
| 124 | while ($t <= self::$iMax) { |
||||
| 125 | $t = strtotime('+1 day', $t); |
||||
| 126 | self::$tickPositions[$i++] = $t; |
||||
| 127 | if ($aMinor) { |
||||
| 128 | self::$minTickPositions[$j++] = strtotime('+12 hours', $t); |
||||
| 129 | } |
||||
| 130 | } |
||||
| 131 | |||||
| 132 | break; |
||||
| 133 | case DSUTILS_DAY2: |
||||
| 134 | while ($t <= self::$iMax) { |
||||
| 135 | $t = strtotime('+1 day', $t); |
||||
| 136 | if ($aMinor) { |
||||
| 137 | self::$minTickPositions[$j++] = $t; |
||||
| 138 | } |
||||
| 139 | $t = strtotime('+1 day', $t); |
||||
| 140 | self::$tickPositions[$i++] = $t; |
||||
| 141 | } |
||||
| 142 | |||||
| 143 | break; |
||||
| 144 | case DSUTILS_DAY4: |
||||
| 145 | while ($t <= self::$iMax) { |
||||
| 146 | for ($k = 0; $k < 3; ++$k) { |
||||
| 147 | $t = strtotime('+1 day', $t); |
||||
| 148 | if ($aMinor) { |
||||
| 149 | self::$minTickPositions[$j++] = $t; |
||||
| 150 | } |
||||
| 151 | } |
||||
| 152 | $t = strtotime('+1 day', $t); |
||||
| 153 | self::$tickPositions[$i++] = $t; |
||||
| 154 | } |
||||
| 155 | |||||
| 156 | break; |
||||
| 157 | } |
||||
| 158 | } |
||||
| 159 | |||||
| 160 | public static function doWeekly($aType, $aMinor = false) |
||||
| 161 | { |
||||
| 162 | $hpd = 3600 * 24; |
||||
| 163 | $hpw = 3600 * 24 * 7; |
||||
| 164 | // Find out week number of min date |
||||
| 165 | $thursday = self::$iMin + $hpd * (3 - (date('w', self::$iMin) + 6) % 7); |
||||
| 166 | $week = 1 + (date('z', $thursday) - (11 - date('w', mktime(0, 0, 0, 1, 1, date('Y', $thursday)))) % 7) / 7; |
||||
|
0 ignored issues
–
show
Unused Code
introduced
by
Loading history...
date('Y', $thursday) of type string is incompatible with the type integer expected by parameter $year of mktime().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 167 | $daynumber = date('w', self::$iMin); |
||||
| 168 | if ($daynumber == 0) { |
||||
| 169 | $daynumber = 7; |
||||
| 170 | } |
||||
| 171 | |||||
| 172 | $m = self::$startmonth; |
||||
| 173 | $y = self::$startyear; |
||||
| 174 | $d = self::$startday; |
||||
| 175 | $i = 0; |
||||
| 176 | $j = 0; |
||||
| 177 | // The assumption is that the weeks start on Monday. If the first day |
||||
| 178 | // is later in the week then the first week tick has to be on the following |
||||
| 179 | // week. |
||||
| 180 | if ($daynumber == 1) { |
||||
| 181 | self::$tickPositions[$i++] = mktime(0, 0, 0, $m, $d, $y); |
||||
| 182 | $t = mktime(0, 0, 0, $m, $d, $y) + $hpw; |
||||
| 183 | } else { |
||||
| 184 | $t = mktime(0, 0, 0, $m, $d, $y) + $hpd * (8 - $daynumber); |
||||
| 185 | } |
||||
| 186 | |||||
| 187 | switch ($aType) { |
||||
| 188 | case DSUTILS_WEEK1: |
||||
| 189 | $cnt = 0; |
||||
| 190 | |||||
| 191 | break; |
||||
| 192 | case DSUTILS_WEEK2: |
||||
| 193 | $cnt = 1; |
||||
| 194 | |||||
| 195 | break; |
||||
| 196 | case DSUTILS_WEEK4: |
||||
| 197 | $cnt = 3; |
||||
| 198 | |||||
| 199 | break; |
||||
| 200 | } |
||||
| 201 | while ($t <= self::$iMax) { |
||||
| 202 | self::$tickPositions[$i++] = $t; |
||||
| 203 | for ($k = 0; $k < $cnt; ++$k) { |
||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
| 204 | $t += $hpw; |
||||
| 205 | if ($aMinor) { |
||||
| 206 | self::$minTickPositions[$j++] = $t; |
||||
| 207 | } |
||||
| 208 | } |
||||
| 209 | $t += $hpw; |
||||
| 210 | } |
||||
| 211 | } |
||||
| 212 | |||||
| 213 | public static function doMonthly($aType, $aMinor = false) |
||||
| 214 | { |
||||
| 215 | $monthcount = 0; |
||||
| 216 | $m = self::$startmonth; |
||||
| 217 | $y = self::$startyear; |
||||
| 218 | $i = 0; |
||||
| 219 | $j = 0; |
||||
| 220 | |||||
| 221 | // Skip the first month label if it is before the startdate |
||||
| 222 | if (self::$startday == 1) { |
||||
| 223 | self::$tickPositions[$i++] = mktime(0, 0, 0, $m, 1, $y); |
||||
| 224 | $monthcount = 1; |
||||
| 225 | } |
||||
| 226 | if ($aType == 1) { |
||||
| 227 | if (self::$startday < 15) { |
||||
| 228 | self::$minTickPositions[$j++] = mktime(0, 0, 0, $m, 15, $y); |
||||
| 229 | } |
||||
| 230 | } |
||||
| 231 | ++$m; |
||||
| 232 | |||||
| 233 | // Loop through all the years included in the scale |
||||
| 234 | for ($y = self::$startyear; $y <= self::$endyear; ++$y) { |
||||
| 235 | // Loop through all the months. There are three cases to consider: |
||||
| 236 | // 1. We are in the first year and must start with the startmonth |
||||
| 237 | // 2. We are in the end year and we must stop at last month of the scale |
||||
| 238 | // 3. A year in between where we run through all the 12 months |
||||
| 239 | $stopmonth = $y == self::$endyear ? self::$endmonth : 12; |
||||
| 240 | while ($m <= $stopmonth) { |
||||
| 241 | switch ($aType) { |
||||
| 242 | case DSUTILS_MONTH1: |
||||
| 243 | // Set minor tick at the middle of the month |
||||
| 244 | if ($aMinor) { |
||||
| 245 | if ($m <= $stopmonth) { |
||||
| 246 | if (!($y == self::$endyear && $m == $stopmonth && self::$endday < 15)) { |
||||
| 247 | self::$minTickPositions[$j++] = mktime(0, 0, 0, $m, 15, $y); |
||||
| 248 | } |
||||
| 249 | } |
||||
| 250 | } |
||||
| 251 | // Major at month |
||||
| 252 | // Get timestamp of first hour of first day in each month |
||||
| 253 | self::$tickPositions[$i++] = mktime(0, 0, 0, $m, 1, $y); |
||||
| 254 | |||||
| 255 | break; |
||||
| 256 | case DSUTILS_MONTH2: |
||||
| 257 | if ($aMinor) { |
||||
| 258 | // Set minor tick at start of each month |
||||
| 259 | self::$minTickPositions[$j++] = mktime(0, 0, 0, $m, 1, $y); |
||||
| 260 | } |
||||
| 261 | |||||
| 262 | // Major at every second month |
||||
| 263 | // Get timestamp of first hour of first day in each month |
||||
| 264 | if ($monthcount % 2 == 0) { |
||||
| 265 | self::$tickPositions[$i++] = mktime(0, 0, 0, $m, 1, $y); |
||||
| 266 | } |
||||
| 267 | |||||
| 268 | break; |
||||
| 269 | case DSUTILS_MONTH3: |
||||
| 270 | if ($aMinor) { |
||||
| 271 | // Set minor tick at start of each month |
||||
| 272 | self::$minTickPositions[$j++] = mktime(0, 0, 0, $m, 1, $y); |
||||
| 273 | } |
||||
| 274 | // Major at every third month |
||||
| 275 | // Get timestamp of first hour of first day in each month |
||||
| 276 | if ($monthcount % 3 == 0) { |
||||
| 277 | self::$tickPositions[$i++] = mktime(0, 0, 0, $m, 1, $y); |
||||
| 278 | } |
||||
| 279 | |||||
| 280 | break; |
||||
| 281 | case DSUTILS_MONTH6: |
||||
| 282 | if ($aMinor) { |
||||
| 283 | // Set minor tick at start of each month |
||||
| 284 | self::$minTickPositions[$j++] = mktime(0, 0, 0, $m, 1, $y); |
||||
| 285 | } |
||||
| 286 | // Major at every third month |
||||
| 287 | // Get timestamp of first hour of first day in each month |
||||
| 288 | if ($monthcount % 6 == 0) { |
||||
| 289 | self::$tickPositions[$i++] = mktime(0, 0, 0, $m, 1, $y); |
||||
| 290 | } |
||||
| 291 | |||||
| 292 | break; |
||||
| 293 | } |
||||
| 294 | ++$m; |
||||
| 295 | ++$monthcount; |
||||
| 296 | } |
||||
| 297 | $m = 1; |
||||
| 298 | } |
||||
| 299 | |||||
| 300 | // For the case where all dates are within the same month |
||||
| 301 | // we want to make sure we have at least two ticks on the scale |
||||
| 302 | // since the scale want work properly otherwise |
||||
| 303 | if (self::$startmonth == self::$endmonth && self::$startyear == self::$endyear && $aType == 1) { |
||||
| 304 | self::$tickPositions[$i++] = mktime(0, 0, 0, self::$startmonth + 1, 1, self::$startyear); |
||||
| 305 | } |
||||
| 306 | |||||
| 307 | return [self::$tickPositions, self::$minTickPositions]; |
||||
| 308 | } |
||||
| 309 | |||||
| 310 | 1 | public static function GetTicks($aData, $aType = 1, $aMinor = false, $aEndPoints = false) |
|||
| 311 | { |
||||
| 312 | 1 | $n = safe_count($aData); |
|||
| 313 | |||||
| 314 | 1 | return self::GetTicksFromMinMax($aData[0], $aData[$n - 1], $aType, $aMinor, $aEndPoints); |
|||
| 315 | } |
||||
| 316 | |||||
| 317 | public static function GetAutoTicks($aMin, $aMax, $aMaxTicks = 10, $aMinor = false) |
||||
| 318 | { |
||||
| 319 | $diff = $aMax - $aMin; |
||||
| 320 | $spd = 3600 * 24; |
||||
| 321 | $spw = $spd * 7; |
||||
| 322 | $spm = $spd * 30; |
||||
| 323 | $spy = $spd * 352; |
||||
| 324 | |||||
| 325 | if (self::$iUseWeeks) { |
||||
| 326 | $w = 'W'; |
||||
| 327 | } else { |
||||
| 328 | $w = 'd M'; |
||||
| 329 | } |
||||
| 330 | |||||
| 331 | // Decision table for suitable scales |
||||
| 332 | // First value: Main decision point |
||||
| 333 | // Second value: Array of formatting depending on divisor for wanted max number of ticks. <divisor><formatting><format-string>,.. |
||||
| 334 | $tt = [ |
||||
| 335 | [$spw, [1, DSUTILS_DAY1, 'd M', 2, DSUTILS_DAY2, 'd M', -1, DSUTILS_DAY4, 'd M']], |
||||
| 336 | [$spm, [1, DSUTILS_DAY1, 'd M', 2, DSUTILS_DAY2, 'd M', 4, DSUTILS_DAY4, 'd M', 7, DSUTILS_WEEK1, $w, -1, DSUTILS_WEEK2, $w]], |
||||
| 337 | [$spy, [1, DSUTILS_DAY1, 'd M', 2, DSUTILS_DAY2, 'd M', 4, DSUTILS_DAY4, 'd M', 7, DSUTILS_WEEK1, $w, 14, DSUTILS_WEEK2, $w, 30, DSUTILS_MONTH1, 'M', 60, DSUTILS_MONTH2, 'M', -1, DSUTILS_MONTH3, 'M']], |
||||
| 338 | [-1, [30, DSUTILS_MONTH1, 'M-Y', 60, DSUTILS_MONTH2, 'M-Y', 90, DSUTILS_MONTH3, 'M-Y', 180, DSUTILS_MONTH6, 'M-Y', 352, DSUTILS_YEAR1, 'Y', 704, DSUTILS_YEAR2, 'Y', -1, DSUTILS_YEAR5, 'Y']], ]; |
||||
| 339 | |||||
| 340 | $ntt = safe_count($tt); |
||||
| 341 | $nd = floor($diff / $spd); |
||||
| 342 | for ($i = 0; $i < $ntt; ++$i) { |
||||
| 343 | if ($diff <= $tt[$i][0] || $i == $ntt - 1) { |
||||
| 344 | $t = $tt[$i][1]; |
||||
| 345 | $n = safe_count($t) / 3; |
||||
| 346 | for ($j = 0; $j < $n; ++$j) { |
||||
| 347 | if ($nd / $t[3 * $j] <= $aMaxTicks || $j == $n - 1) { |
||||
| 348 | $type = $t[3 * $j + 1]; |
||||
| 349 | $fs = $t[3 * $j + 2]; |
||||
| 350 | list($tickPositions, $minTickPositions) = self::GetTicksFromMinMax($aMin, $aMax, $type, $aMinor); |
||||
| 351 | |||||
| 352 | return [$fs, $tickPositions, $minTickPositions, $type]; |
||||
| 353 | } |
||||
| 354 | } |
||||
| 355 | } |
||||
| 356 | } |
||||
| 357 | } |
||||
| 358 | |||||
| 359 | 1 | public static function GetTicksFromMinMax($aMin, $aMax, $aType, $aMinor = false, $aEndPoints = false) |
|||
| 360 | { |
||||
| 361 | 1 | self::$starthour = date('G', $aMin); |
|||
| 362 | 1 | self::$startmonth = date('n', $aMin); |
|||
| 363 | 1 | self::$startday = date('j', $aMin); |
|||
| 364 | 1 | self::$startyear = date('Y', $aMin); |
|||
| 365 | 1 | self::$endmonth = date('n', $aMax); |
|||
| 366 | 1 | self::$endyear = date('Y', $aMax); |
|||
| 367 | 1 | self::$endday = date('j', $aMax); |
|||
| 368 | 1 | self::$iMin = $aMin; |
|||
| 369 | 1 | self::$iMax = $aMax; |
|||
| 370 | |||||
| 371 | 1 | if ($aType <= DSUTILS_MONTH6) { |
|||
| 372 | self::doMonthly($aType, $aMinor); |
||||
| 373 | 1 | } elseif ($aType <= DSUTILS_WEEK4) { |
|||
| 374 | self::doWeekly($aType, $aMinor); |
||||
| 375 | 1 | } elseif ($aType <= DSUTILS_DAY4) { |
|||
| 376 | self::doDaily($aType, $aMinor); |
||||
| 377 | 1 | } elseif ($aType <= DSUTILS_YEAR5) { |
|||
| 378 | 1 | self::doYearly($aType, $aMinor); |
|||
| 379 | } else { |
||||
| 380 | JpGraphError::RaiseL(24003); |
||||
| 381 | } |
||||
| 382 | // put a label at the very left data pos |
||||
| 383 | 1 | if ($aEndPoints) { |
|||
| 384 | $tickPositions[$i++] = $aData[0]; |
||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
Comprehensibility
Best Practice
introduced
by
|
|||||
| 385 | } |
||||
| 386 | |||||
| 387 | // put a label at the very right data pos |
||||
| 388 | 1 | if ($aEndPoints) { |
|||
| 389 | $tickPositions[$i] = $aData[$n - 1]; |
||||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
| 390 | } |
||||
| 391 | |||||
| 392 | 1 | return [self::$tickPositions, self::$minTickPositions]; |
|||
| 393 | } |
||||
| 394 | } |
||||
| 395 |