Date::timeOffset()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 18
rs 9.6666
cc 4
nc 6
nop 1
1
<?php
2
/* @description     Transformation Style Sheets - Revolutionising PHP templating    *
3
 * @author          Tom Butler [email protected]                                             *
4
 * @copyright       2017 Tom Butler <[email protected]> | https://r.je/                      *
5
 * @license         http://www.opensource.org/licenses/bsd-license.php  BSD License *
6
 * @version         1.2                                                             */
7
namespace Transphporm\Formatter;
8
/** Date/time formatting for use in formmat: property*/
9
class Date {
10
	private $locale;
11
12
	public function __construct($locale) {
13
		$this->locale = $locale;
14
	}
15
16
	/** Converts $val into a \DateTime object if it's not already */
17
	private function getDate($val) {
18
		$tz = new \DateTimeZone($this->locale['timezone']);
19
		$date =  $val instanceof \DateTimeInterface ? $val : new \DateTime($val, $tz);
20
		$date->setTimeZone($tz);
21
		return $date;
22
	}
23
24
	/** Formats date based on supplied $format or default format from $locale */
25
	public function date($val, $format = null) {
26
		$format = $format ? $format : $this->locale['date_format'];
27
		return $this->getDate($val)->format($format);
28
	}
29
30
	/** Formats \DateTime as time based on supplied $format or default format from $locale */
31
	public function time($val, $format = null) {
32
		$format = $format ? $format : $this->locale['time_format'];
33
		return $this->getDate($val)->format($format);
34
	}
35
36
	/** Formats \DateTime as Date and Time using formats from $locale */
37
	public function dateTime($val) {
38
		return $this->date($val, $this->locale['date_format'] . ' ' . $this->locale['time_format']);
39
	}
40
41
	/** Generates relative time offsets based on system clock. e.g "10 minutes ago" or "In 6 months"
42
		using strings from $locale	*/
43
	public function relative($val) {
44
		$now = $this->getDate(null);
45
		$date = $this->getDate($val);
46
47
		$diff = $now->diff($date);
48
49
50
		$diffDays = $diff->invert === 1 ? $diff->days : 0- $diff->days;
51
52
		if ($diffDays !== 0) return $this->dayOffset($diffDays);
53
		else return $this->timeOffset($diff);
54
	}
55
56
	/** Calculates offset in hours/minutes/seconds */
57
	private function timeOffset($diff) {
58
		$strings = $this->locale['offset_strings'];
59
60
		$str = $diff->invert === 1 ? $strings['past'] : $strings['future'];
61
62
		$parts = ['h' => 'hours', 'i' => 'minutes', 's'  => 'seconds'];
63
64
		$result = '';
65
66
		foreach ($parts as $l => $time) {
67
			if ($diff->$l > 0) {
68
				$result = sprintf($str, $diff->$l, $this->getPlural($strings, $diff->$l, $time));
69
				break;
70
			}
71
		}
72
73
		return $result;
74
	}
75
76
	/** Gets date ranges to represent uses of weeks/months/days/etc */
77
	private function getRanges($strings) {
78
		$ranges =  [
79
			[1, 1, $strings['yesterday'], 1, ''],
80
			[1, 13, $strings['past'], 1, 'days'],
81
			[13, 28, $strings['past'], 7, 'weeks'],
82
			[28, 365, $strings['past'], 28, 'months'],
83
			[365, 99999999, $strings['past'], 365, 'years'],
84
			[-1, -1, $strings['tomorrow'], 1, ''],
85
			[-13, -1, $strings['future'], 1, 'days'],
86
			[-28, -13, $strings['future'], 7, 'weeks'],
87
			[-365, -28, $strings['future'], 28, 'months'],
88
			[-999999, -365, $strings['future'], 365, 'years'],
89
		];
90
		if (isset($strings['day_before_yesterday'])) $this->add2DayRanges($ranges, $strings['day_before_yesterday'], "before");
91
		if (isset($strings['day_after_tomorrow'])) $this->add2DayRanges($ranges, $strings['day_after_tomorrow'], "after");
92
		return $ranges;
93
	}
94
95
    private function add2DayRanges(&$ranges, $property, $when) {
96
        $rangeVal = $when === "before" ? 2 : -2;
97
        array_unshift($ranges, [$rangeVal, $rangeVal, $property, 1, '']);
98
    }
99
100
	/** Converts "week" to "weeks", "month" to "months" etc when plural is required using language from $locale */
101
	private function getPlural($strings, $num, $interval) {
102
		if ($interval !== '') return $num == 1 ? $strings[$interval . '_singular'] : $strings[$interval . '_plural'];
103
		else return '';
104
	}
105
106
	/** Calculates offset in days/weeks/month/years */
107
	private function dayOffset($diffDays) {
108
		$strings = $this->locale['offset_strings'];
109
110
		$result = '';
111
112
		foreach ($this->getRanges($strings) as list($lower, $upper, $str, $divisor, $plural)) {
113
			if ($diffDays >= $lower && $diffDays <= $upper) {
114
				$num = abs(round($diffDays / $divisor));
115
				$result = sprintf($str, $num, $this->getPlural($strings, $num, $plural));
116
				break;
117
			}
118
		}
119
120
		return $result;
121
	}
122
}
123