Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
bc77d7c0 | 4 | | Copyright CiviCRM LLC. All rights reserved. | |
6a488035 | 5 | | | |
bc77d7c0 TO |
6 | | This work is published under the GNU AGPLv3 license with some | |
7 | | permitted exceptions and without any warranty. For full license | | |
8 | | and copyright information, see https://civicrm.org/licensing | | |
6a488035 | 9 | +--------------------------------------------------------------------+ |
d25dd0ee | 10 | */ |
6a488035 TO |
11 | |
12 | /** | |
13 | * | |
14 | * @package CRM | |
ca5cec67 | 15 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
6a488035 TO |
16 | */ |
17 | ||
18 | /** | |
19 | * Date time utilties | |
20 | */ | |
21 | class CRM_Utils_Time { | |
22 | ||
23 | /** | |
ea9371f9 TO |
24 | * A function which determines the current time. |
25 | * Only used during testing (with mocked time). | |
26 | * | |
27 | * The normal value, NULL, indicates the use of real time. | |
28 | * | |
29 | * @var callable|null | |
6a488035 | 30 | */ |
ea9371f9 | 31 | static private $callback = NULL; |
6a488035 TO |
32 | |
33 | /** | |
fe482240 | 34 | * Get the time. |
6a488035 | 35 | * |
77855840 TO |
36 | * @param string $returnFormat |
37 | * Format in which date is to be retrieved. | |
6a488035 | 38 | * |
2e9914a0 | 39 | * @return string |
6a488035 | 40 | */ |
00be9182 | 41 | public static function getTime($returnFormat = 'YmdHis') { |
6a488035 TO |
42 | return date($returnFormat, self::getTimeRaw()); |
43 | } | |
44 | ||
45 | /** | |
fe482240 | 46 | * Get the time. |
6a488035 | 47 | * |
50bfb460 SB |
48 | * @return int |
49 | * seconds since epoch | |
6a488035 | 50 | */ |
00be9182 | 51 | public static function getTimeRaw() { |
ea9371f9 | 52 | return self::$callback === NULL ? time() : call_user_func(self::$callback); |
6a488035 TO |
53 | } |
54 | ||
55 | /** | |
fe482240 | 56 | * Set the given time. |
6a488035 | 57 | * |
77855840 TO |
58 | * @param string $newDateTime |
59 | * A date formatted with strtotime. | |
60 | * @param string $returnFormat | |
61 | * Format in which date is to be retrieved. | |
6a488035 | 62 | * |
ea9371f9 TO |
63 | * Note: The progression of time will be influenced by TIME_FUNC, which may be: |
64 | * - 'frozen' (time does not move) | |
65 | * - 'natural' (time moves naturally) | |
66 | * - 'linear:XXX' (time moves in increments of XXX milliseconds - with every lookup) | |
67 | * - 'prng:XXX' (time moves by random increments, between 0 and XXX milliseconds) | |
2e9914a0 | 68 | * @return string |
6a488035 | 69 | */ |
00be9182 | 70 | public static function setTime($newDateTime, $returnFormat = 'YmdHis') { |
ea9371f9 TO |
71 | $mode = getenv('TIME_FUNC') ? getenv('TIME_FUNC') : 'natural'; |
72 | ||
73 | list ($modeName, $modeNum) = explode(":", "$mode:"); | |
74 | ||
75 | switch ($modeName) { | |
76 | case 'frozen': | |
77 | // Every getTime() will produce the same value (ie $newDateTime). | |
78 | $now = strtotime($newDateTime); | |
79 | self::$callback = function () use ($now) { | |
80 | return $now; | |
81 | }; | |
82 | break; | |
83 | ||
84 | case 'natural': | |
85 | // Time changes to $newDateTime and then proceeds naturally. | |
86 | $delta = strtotime($newDateTime) - time(); | |
87 | self::$callback = function () use ($delta) { | |
88 | return time() + $delta; | |
89 | }; | |
90 | break; | |
91 | ||
92 | case 'linear': | |
93 | // Time changes to $newDateTime and then proceeds in fixed increments ($modeNum milliseconds). | |
94 | $incr = ($modeNum / 1000.0); | |
95 | $now = (float) strtotime($newDateTime) - $incr; | |
96 | self::$callback = function () use (&$now, $incr) { | |
97 | $now += $incr; | |
98 | return floor($now); | |
99 | }; | |
100 | break; | |
101 | ||
102 | case 'prng': | |
103 | // Time changes to $newDateTime and then proceeds using deterministic pseudorandom increments (of up to $modeNum milliseconds). | |
104 | $seed = md5($newDateTime . chr(0) . $mode, TRUE); | |
105 | $now = (float) strtotime($newDateTime); | |
106 | self::$callback = function () use (&$seed, &$now, $modeNum) { | |
107 | $mod = gmp_strval(gmp_mod(gmp_import($seed), "$modeNum")); | |
108 | $seed = md5($seed . $now, TRUE); | |
109 | $now = $now + ($mod / 1000.0); | |
110 | return floor($now); | |
111 | }; | |
112 | break; | |
113 | ||
114 | default: | |
115 | throw new \RuntimeException("Unrecognized TIME_FUNC ($mode)"); | |
116 | } | |
117 | ||
6a488035 TO |
118 | return self::getTime($returnFormat); |
119 | } | |
120 | ||
121 | /** | |
fe482240 | 122 | * Remove any time overrides. |
6a488035 | 123 | */ |
00be9182 | 124 | public static function resetTime() { |
ea9371f9 | 125 | self::$callback = NULL; |
6a488035 | 126 | } |
8010540a TO |
127 | |
128 | /** | |
129 | * Approximate time-comparison. $a and $b are considered equal if they | |
130 | * are within $threshold seconds of each other. | |
131 | * | |
77855840 TO |
132 | * @param string $a |
133 | * Time which can be parsed by strtotime. | |
134 | * @param string $b | |
135 | * Time which can be parsed by strtotime. | |
136 | * @param int $threshold | |
137 | * Maximum allowed difference (in seconds). | |
8010540a TO |
138 | * @return bool |
139 | */ | |
00be9182 | 140 | public static function isEqual($a, $b, $threshold = 0) { |
8010540a TO |
141 | $diff = strtotime($b) - strtotime($a); |
142 | return (abs($diff) <= $threshold); | |
143 | } | |
96025800 | 144 | |
6a488035 | 145 | } |