This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); |
||
3 | /********************************************************************************* |
||
4 | * SugarCRM Community Edition is a customer relationship management program developed by |
||
5 | * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. |
||
6 | |||
7 | * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd. |
||
8 | * Copyright (C) 2011 - 2014 Salesagility Ltd. |
||
9 | * |
||
10 | * This program is free software; you can redistribute it and/or modify it under |
||
11 | * the terms of the GNU Affero General Public License version 3 as published by the |
||
12 | * Free Software Foundation with the addition of the following permission added |
||
13 | * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK |
||
14 | * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY |
||
15 | * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. |
||
16 | * |
||
17 | * This program is distributed in the hope that it will be useful, but WITHOUT |
||
18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
||
19 | * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
||
20 | * details. |
||
21 | * |
||
22 | * You should have received a copy of the GNU Affero General Public License along with |
||
23 | * this program; if not, see http://www.gnu.org/licenses or write to the Free |
||
24 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
||
25 | * 02110-1301 USA. |
||
26 | * |
||
27 | * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, |
||
28 | * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected]. |
||
29 | * |
||
30 | * The interactive user interfaces in modified source and object code versions |
||
31 | * of this program must display Appropriate Legal Notices, as required under |
||
32 | * Section 5 of the GNU Affero General Public License version 3. |
||
33 | * |
||
34 | * In accordance with Section 7(b) of the GNU Affero General Public License version 3, |
||
35 | * these Appropriate Legal Notices must retain the display of the "Powered by |
||
36 | * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not |
||
37 | * reasonably feasible for technical reasons, the Appropriate Legal Notices must |
||
38 | * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". |
||
39 | ********************************************************************************/ |
||
40 | |||
41 | require_once 'include/SugarDateTime.php'; |
||
42 | |||
43 | /** |
||
44 | * New Time & Date handling class |
||
45 | * @api |
||
46 | * Migration notes: |
||
47 | * - to_db_time() requires either full datetime or time, won't work with just date |
||
48 | * The reason is that it's not possible to know if short string has only date or only time, |
||
49 | * and it makes more sense to assume time for the time conversion function. |
||
50 | */ |
||
51 | class TimeDate |
||
52 | { |
||
53 | const DB_DATE_FORMAT = 'Y-m-d'; |
||
54 | const DB_TIME_FORMAT = 'H:i:s'; |
||
55 | // little optimization |
||
56 | const DB_DATETIME_FORMAT = 'Y-m-d H:i:s'; |
||
57 | const RFC2616_FORMAT = 'D, d M Y H:i:s \G\M\T'; |
||
58 | |||
59 | const SECONDS_IN_A_DAY = 86400; |
||
60 | |||
61 | // Standard DB date/time formats |
||
62 | // they are constant, vars are for compatibility |
||
63 | public $dbDayFormat = self::DB_DATE_FORMAT; |
||
64 | public $dbTimeFormat = self::DB_TIME_FORMAT; |
||
65 | |||
66 | /** |
||
67 | * Regexp for matching format elements |
||
68 | * @var array |
||
69 | */ |
||
70 | protected static $format_to_regexp = array( |
||
71 | 'a' => '[ ]*[ap]m', |
||
72 | 'A' => '[ ]*[AP]M', |
||
73 | 'd' => '[0-9]{1,2}', |
||
74 | 'j' => '[0-9]{1,2}', |
||
75 | 'h' => '[0-9]{1,2}', |
||
76 | 'H' => '[0-9]{1,2}', |
||
77 | 'g' => '[0-9]{1,2}', |
||
78 | 'G' => '[0-9]{1,2}', |
||
79 | 'i' => '[0-9]{1,2}', |
||
80 | 'm' => '[0-9]{1,2}', |
||
81 | 'n' => '[0-9]{1,2}', |
||
82 | 'Y' => '[0-9]{4}', |
||
83 | 's' => '[0-9]{1,2}', |
||
84 | 'F' => '\w+', |
||
85 | "M" => '[\w]{1,3}', |
||
86 | ); |
||
87 | |||
88 | /** |
||
89 | * Relation between date() and strftime() formats |
||
90 | * @var array |
||
91 | */ |
||
92 | public static $format_to_str = array( |
||
93 | // date |
||
94 | 'Y' => '%Y', |
||
95 | |||
96 | 'm' => '%m', |
||
97 | 'M' => '%b', |
||
98 | 'F' => '%B', |
||
99 | 'n' => '%m', |
||
100 | |||
101 | 'd' => '%d', |
||
102 | //'j' => '%e', |
||
103 | // time |
||
104 | 'a' => '%P', |
||
105 | 'A' => '%p', |
||
106 | |||
107 | 'h' => '%I', |
||
108 | 'H' => '%H', |
||
109 | //'g' => '%l', |
||
110 | //'G' => '%H', |
||
111 | |||
112 | 'i' => '%M', |
||
113 | 's' => '%S', |
||
114 | ); |
||
115 | |||
116 | /** |
||
117 | * GMT timezone object |
||
118 | * |
||
119 | * @var DateTimeZone |
||
120 | */ |
||
121 | protected static $gmtTimezone; |
||
122 | |||
123 | /** |
||
124 | * Current time |
||
125 | * @var SugarDateTime |
||
126 | */ |
||
127 | protected $now; |
||
128 | |||
129 | /** |
||
130 | * The current user |
||
131 | * |
||
132 | * @var User |
||
133 | */ |
||
134 | protected $user; |
||
135 | |||
136 | /** |
||
137 | * Current user's ID |
||
138 | * |
||
139 | * @var string |
||
140 | */ |
||
141 | protected $current_user_id; |
||
142 | /** |
||
143 | * Current user's TZ |
||
144 | * @var DateTimeZone |
||
145 | */ |
||
146 | protected $current_user_tz; |
||
147 | |||
148 | /** |
||
149 | * Separator for current user time format |
||
150 | * |
||
151 | * @var string |
||
152 | */ |
||
153 | protected $time_separator; |
||
154 | |||
155 | /** |
||
156 | * Always consider user TZ to be GMT and date format DB format - for SOAP etc. |
||
157 | * |
||
158 | * @var bool |
||
159 | */ |
||
160 | protected $always_db = false; |
||
161 | |||
162 | /** |
||
163 | * Global instance of TimeDate |
||
164 | * @var TimeDate |
||
165 | */ |
||
166 | protected static $timedate; |
||
167 | |||
168 | /** |
||
169 | * Allow returning cached now() value |
||
170 | * If false, new system time is checked each time now() is required |
||
171 | * If true, same value is returned for whole request. |
||
172 | * Also, current user's timezone is cached. |
||
173 | * @var bool |
||
174 | */ |
||
175 | public $allow_cache = true; |
||
176 | |||
177 | /** |
||
178 | * Create TimeDate handler |
||
179 | * @param User $user User to work with, default if current user |
||
180 | */ |
||
181 | 2 | public function __construct(User $user = null) |
|
182 | { |
||
183 | 2 | if (self::$gmtTimezone == null) { |
|
184 | self::$gmtTimezone = new DateTimeZone("UTC"); |
||
185 | } |
||
186 | 2 | $this->now = new SugarDateTime(); |
|
187 | 2 | $this->tzGMT($this->now); |
|
188 | 2 | $this->user = $user; |
|
189 | 2 | } |
|
190 | |||
191 | /** |
||
192 | * Set flag specifying we should always use DB format |
||
193 | * @param bool $flag |
||
194 | * @return TimeDate |
||
195 | */ |
||
196 | public function setAlwaysDb($flag = true) |
||
197 | { |
||
198 | $this->always_db = $flag; |
||
199 | $this->clearCache(); |
||
200 | return $this; |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * Get "always use DB format" flag |
||
205 | * @return bool |
||
206 | */ |
||
207 | 167 | public function isAlwaysDb() |
|
208 | { |
||
209 | 167 | return !empty($GLOBALS['disable_date_format']) || $this->always_db; |
|
210 | } |
||
211 | |||
212 | /** |
||
213 | * Get TimeDate instance |
||
214 | * @return TimeDate |
||
215 | */ |
||
216 | 30 | public static function getInstance() |
|
217 | { |
||
218 | 30 | if(empty(self::$timedate)) { |
|
219 | if(ini_get('date.timezone') == '') { |
||
220 | // Remove warning about default timezone |
||
221 | date_default_timezone_set(@date('e')); |
||
222 | try { |
||
223 | $tz = self::guessTimezone(); |
||
224 | } catch(Exception $e) { |
||
225 | $tz = "UTC"; // guess failed, switch to UTC |
||
226 | } |
||
227 | if(isset($GLOBALS['log'])) { |
||
228 | $GLOBALS['log']->fatal("Configuration variable date.timezone is not set, guessed timezone $tz. Please set date.timezone=\"$tz\" in php.ini!"); |
||
229 | } |
||
230 | date_default_timezone_set($tz); |
||
231 | } |
||
232 | self::$timedate = new self; |
||
233 | } |
||
234 | 30 | return self::$timedate; |
|
235 | } |
||
236 | |||
237 | /** |
||
238 | * Set current user for this object |
||
239 | * |
||
240 | * @param User $user User object, default is current user |
||
241 | * @return TimeDate |
||
242 | */ |
||
243 | public function setUser(User $user = null) |
||
244 | { |
||
245 | $this->user = $user; |
||
246 | $this->clearCache(); |
||
247 | return $this; |
||
248 | } |
||
249 | |||
250 | /** |
||
251 | * Figure out what the required user is |
||
252 | * |
||
253 | * The order is: supplied parameter, TimeDate's user, global current user |
||
254 | * |
||
255 | * @param User $user User object, default is current user |
||
256 | * @internal |
||
257 | * @return User |
||
258 | */ |
||
259 | 167 | protected function _getUser(User $user = null) |
|
260 | { |
||
261 | 167 | if (empty($user)) { |
|
262 | 163 | $user = $this->user; |
|
263 | } |
||
264 | 167 | if (empty($user)) { |
|
265 | 163 | $user = $GLOBALS['current_user']; |
|
266 | } |
||
267 | 167 | return $user; |
|
268 | } |
||
269 | |||
270 | /** |
||
271 | * Get timezone for the specified user |
||
272 | * |
||
273 | * @param User $user User object, default is current user |
||
274 | * @return DateTimeZone |
||
275 | */ |
||
276 | 159 | protected function _getUserTZ(User $user = null) |
|
277 | { |
||
278 | 159 | $user = $this->_getUser($user); |
|
279 | 159 | if (empty($user) || $this->isAlwaysDb()) { |
|
280 | return self::$gmtTimezone; |
||
281 | } |
||
282 | |||
283 | 159 | if ($this->allow_cache && $user->id == $this->current_user_id && ! empty($this->current_user_tz)) { |
|
284 | // current user is cached |
||
285 | return $this->current_user_tz; |
||
286 | } |
||
287 | |||
288 | 159 | $usertimezone = $user->getPreference('timezone'); |
|
289 | 159 | if(empty($usertimezone)) { |
|
290 | 159 | return self::$gmtTimezone; |
|
291 | } |
||
292 | try { |
||
293 | $tz = new DateTimeZone($usertimezone); |
||
294 | } catch (Exception $e) { |
||
295 | $GLOBALS['log']->fatal('Unknown timezone: ' . $usertimezone); |
||
296 | return self::$gmtTimezone; |
||
297 | } |
||
298 | |||
299 | if (empty($this->current_user_id)) { |
||
300 | $this->current_user_id = $user->id; |
||
301 | $this->current_user_tz = $tz; |
||
302 | } |
||
303 | |||
304 | return $tz; |
||
305 | } |
||
306 | |||
307 | /** |
||
308 | * Clears all cached data regarding current user |
||
309 | */ |
||
310 | public function clearCache() |
||
311 | { |
||
312 | $this->current_user_id = null; |
||
313 | $this->current_user_tz = null; |
||
314 | $this->time_separator = null; |
||
315 | $this->now = new SugarDateTime(); |
||
316 | } |
||
317 | |||
318 | /** |
||
319 | * Get user date format. |
||
320 | * @todo add caching |
||
321 | * |
||
322 | * @param User $user user object, current user if not specified |
||
323 | * @return string |
||
324 | */ |
||
325 | 57 | public function get_date_format(User $user = null) |
|
326 | { |
||
327 | 57 | $user = $this->_getUser($user); |
|
328 | |||
329 | 57 | if (empty($user) || $this->isAlwaysDb()) { |
|
330 | return self::DB_DATE_FORMAT; |
||
331 | } |
||
332 | |||
333 | 57 | $datef = $user->getPreference('datef'); |
|
334 | 57 | if(empty($datef) && isset($GLOBALS['current_user']) && $GLOBALS['current_user'] !== $user) { |
|
335 | // if we got another user and it has no date format, try current user |
||
336 | $datef = $GLOBALS['current_user']->getPreference('datef'); |
||
337 | } |
||
338 | 57 | if (empty($datef)) { |
|
339 | $datef = $GLOBALS['sugar_config']['default_date_format']; |
||
340 | } |
||
341 | 57 | if (empty($datef)) { |
|
342 | $datef = ''; |
||
343 | } |
||
344 | |||
345 | 57 | return $datef; |
|
346 | } |
||
347 | |||
348 | /** |
||
349 | * Get user time format. |
||
350 | * @todo add caching |
||
351 | * |
||
352 | * @param User $user user object, current user if not specified |
||
353 | * @return string |
||
354 | */ |
||
355 | 25 | public function get_time_format(/*User*/ $user = null) |
|
356 | { |
||
357 | 25 | if(is_bool($user) || func_num_args() > 1) { |
|
358 | // BC dance - old signature was boolean, User |
||
359 | $GLOBALS['log']->fatal('TimeDate::get_time_format(): Deprecated API used, please update you code - get_time_format() now has one argument of type User'); |
||
360 | if(func_num_args() > 1) { |
||
361 | $user = func_get_arg(1); |
||
362 | } else { |
||
363 | $user = null; |
||
364 | } |
||
365 | } |
||
366 | 25 | $user = $this->_getUser($user); |
|
367 | |||
368 | 25 | if (empty($user) || $this->isAlwaysDb()) { |
|
369 | return self::DB_TIME_FORMAT; |
||
370 | } |
||
371 | |||
372 | 25 | $timef = $user->getPreference('timef'); |
|
373 | 25 | if(empty($timef) && isset($GLOBALS['current_user']) && $GLOBALS['current_user'] !== $user) { |
|
374 | // if we got another user and it has no time format, try current user |
||
375 | $timef = $GLOBALS['current_user']->getPreference('$timef'); |
||
376 | } |
||
377 | 25 | if (empty($timef)) { |
|
378 | $timef = $GLOBALS['sugar_config']['default_time_format']; |
||
379 | } |
||
380 | 25 | if (empty($timef)) { |
|
381 | $timef = ''; |
||
382 | } |
||
383 | 25 | return $timef; |
|
384 | } |
||
385 | |||
386 | /** |
||
387 | * Get user datetime format. |
||
388 | * |
||
389 | * @param User $user user object, current user if not specified |
||
390 | * @return string |
||
391 | */ |
||
392 | 129 | public function get_date_time_format($user = null) |
|
393 | { |
||
394 | // BC fix - had (bool, user) signature before |
||
395 | 129 | if(!($user instanceof User)) { |
|
396 | 124 | if(func_num_args() > 1) { |
|
397 | $user = func_get_arg(1); |
||
398 | if(!($user instanceof User)) { |
||
399 | $user = null; |
||
400 | } |
||
401 | } else { |
||
402 | 124 | $user = null; |
|
403 | } |
||
404 | } |
||
405 | |||
406 | 129 | $cacheKey= $this->get_date_time_format_cache_key($user); |
|
407 | 129 | $cachedValue = sugar_cache_retrieve($cacheKey); |
|
408 | |||
409 | 129 | if(!empty($cachedValue) ) |
|
410 | { |
||
411 | 129 | return $cachedValue; |
|
412 | } |
||
413 | else |
||
414 | { |
||
415 | 2 | $value = $this->merge_date_time($this->get_date_format($user), $this->get_time_format($user)); |
|
416 | 2 | sugar_cache_put($cacheKey,$value,0); |
|
417 | 2 | return $value; |
|
418 | } |
||
419 | } |
||
420 | |||
421 | /** |
||
422 | * Retrieve the cache key used for user date/time formats |
||
423 | * |
||
424 | * @param $user |
||
425 | * @return string |
||
426 | */ |
||
427 | 129 | public function get_date_time_format_cache_key($user) |
|
428 | { |
||
429 | 129 | $cacheKey = get_class($this) ."dateTimeFormat"; |
|
430 | 129 | $user = $this->_getUser($user); |
|
431 | |||
432 | 129 | if($user instanceof User) |
|
433 | { |
||
434 | 129 | $cacheKey .= "_{$user->id}"; |
|
435 | } |
||
436 | |||
437 | 129 | if( $this->isAlwaysDb() ) |
|
438 | $cacheKey .= '_asdb'; |
||
439 | |||
440 | 129 | return $cacheKey; |
|
441 | } |
||
442 | |||
443 | /** |
||
444 | * Get user's first day of week setting. |
||
445 | * |
||
446 | * @param User $user user object, current user if not specified |
||
447 | * @return int Day, 0 = Sunday, 1 = Monday, etc... |
||
448 | */ |
||
449 | public function get_first_day_of_week(User $user = null) |
||
450 | { |
||
451 | $user = $this->_getUser($user); |
||
452 | $fdow = 0; |
||
453 | |||
454 | if (!empty($user)) |
||
455 | { |
||
456 | $fdow = $user->getPreference('fdow'); |
||
457 | if (empty($fdow)) |
||
458 | $fdow = 0; |
||
459 | } |
||
460 | |||
461 | return $fdow; |
||
462 | } |
||
463 | |||
464 | |||
465 | /** |
||
466 | * Make one datetime string from date string and time string |
||
467 | * |
||
468 | * @param string $date |
||
469 | * @param string $time |
||
470 | * @return string New datetime string |
||
471 | */ |
||
472 | 9 | function merge_date_time($date, $time) |
|
473 | { |
||
474 | 9 | return $date . ' ' . $time; |
|
475 | } |
||
476 | |||
477 | /** |
||
478 | * Split datetime string into date & time |
||
479 | * |
||
480 | * @param string $datetime |
||
481 | * @return array |
||
482 | */ |
||
483 | 4 | function split_date_time($datetime) |
|
484 | { |
||
485 | 4 | return explode(' ', $datetime, 2); |
|
486 | } |
||
487 | |||
488 | |||
489 | /** |
||
490 | * Get user date format in Javascript form |
||
491 | * @return string |
||
492 | */ |
||
493 | 13 | function get_cal_date_format() |
|
494 | { |
||
495 | 13 | return str_replace(array_keys(self::$format_to_str), array_values(self::$format_to_str), $this->get_date_format()); |
|
496 | } |
||
497 | |||
498 | /** |
||
499 | * Get user time format in Javascript form |
||
500 | * @return string |
||
501 | */ |
||
502 | function get_cal_time_format() |
||
503 | { |
||
504 | return str_replace(array_keys(self::$format_to_str), array_values(self::$format_to_str), $this->get_time_format()); |
||
505 | } |
||
506 | |||
507 | /** |
||
508 | * Get user date&time format in Javascript form |
||
509 | * @return string |
||
510 | */ |
||
511 | function get_cal_date_time_format() |
||
512 | { |
||
513 | return str_replace(array_keys(self::$format_to_str), array_values(self::$format_to_str), $this->get_date_time_format()); |
||
514 | } |
||
515 | |||
516 | /** |
||
517 | * Verify if the date string conforms to a format |
||
518 | * |
||
519 | * @param string $date |
||
520 | * @param string $format Format to check |
||
521 | * |
||
522 | * @internal |
||
523 | * @return bool Is the date ok? |
||
524 | */ |
||
525 | public function check_matching_format($date, $format) |
||
526 | { |
||
527 | try { |
||
528 | $dt = SugarDateTime::createFromFormat($format, $date); |
||
529 | if (!is_object($dt)) { |
||
530 | return false; |
||
531 | } |
||
532 | } catch (Exception $e) { |
||
533 | return false; |
||
534 | } |
||
535 | return true; |
||
536 | } |
||
537 | |||
538 | /** |
||
539 | * Format DateTime object as DB datetime |
||
540 | * |
||
541 | * @param DateTime $date |
||
542 | * @return string |
||
543 | */ |
||
544 | 86 | public function asDb(DateTime $date) |
|
545 | { |
||
546 | 86 | $date->setTimezone(self::$gmtTimezone); |
|
547 | 86 | return $date->format($this->get_db_date_time_format()); |
|
548 | } |
||
549 | |||
550 | /** |
||
551 | * Format date as DB-formatted field type |
||
552 | * @param DateTime $date |
||
553 | * @param string $type Field type - date, time, datetime[combo] |
||
554 | * @return string Formatted date |
||
555 | */ |
||
556 | public function asDbType(DateTime $date, $type) |
||
557 | { |
||
558 | switch($type) { |
||
559 | case "date": |
||
560 | return $this->asDbDate($date); |
||
561 | break; |
||
562 | case 'time': |
||
563 | return $this->asDbtime($date); |
||
564 | break; |
||
565 | case 'datetime': |
||
566 | case 'datetimecombo': |
||
567 | default: |
||
568 | return $this->asDb($date); |
||
569 | } |
||
570 | } |
||
571 | |||
572 | /** |
||
573 | * Format DateTime object as user datetime |
||
574 | * |
||
575 | * @param DateTime $date |
||
576 | * @param User $user |
||
577 | * @return string |
||
578 | */ |
||
579 | 38 | public function asUser(DateTime $date, User $user = null) |
|
580 | { |
||
581 | 38 | $this->tzUser($date, $user); |
|
582 | 38 | return $date->format($this->get_date_time_format($user)); |
|
583 | } |
||
584 | |||
585 | /** |
||
586 | * Format date as user-formatted field type |
||
587 | * @param DateTime $date |
||
588 | * @param string $type Field type - date, time, datetime[combo] |
||
589 | * @param User $user |
||
590 | * @return string |
||
591 | */ |
||
592 | public function asUserType(DateTime $date, $type, User $user = null) |
||
593 | { |
||
594 | switch($type) { |
||
595 | case "date": |
||
596 | return $this->asUserDate($date, true, $user); |
||
597 | break; |
||
598 | case 'time': |
||
599 | return $this->asUserTime($date, true, $user); |
||
600 | break; |
||
601 | case 'datetime': |
||
602 | case 'datetimecombo': |
||
603 | default: |
||
604 | return $this->asUser($date, $user); |
||
605 | } |
||
606 | } |
||
607 | |||
608 | /** |
||
609 | * Produce timestamp offset by user's timezone |
||
610 | * |
||
611 | * So if somebody converts it to format assuming GMT, it would actually display user's time. |
||
612 | * This is used by Javascript. |
||
613 | * |
||
614 | * @param DateTime $date |
||
615 | * @param User $user |
||
616 | * @return int |
||
617 | */ |
||
618 | 3 | public function asUserTs(DateTime $date, User $user = null) |
|
619 | { |
||
620 | 3 | return $date->format('U')+$this->_getUserTZ($user)->getOffset($date); |
|
621 | } |
||
622 | |||
623 | /** |
||
624 | * Format DateTime object as DB date |
||
625 | * Note: by default does not convert TZ! |
||
626 | * @param DateTime $date |
||
627 | * @param boolean $tz Perform TZ conversion? |
||
628 | * @return string |
||
629 | */ |
||
630 | 4 | public function asDbDate(DateTime $date, $tz = false) |
|
631 | { |
||
632 | 4 | if($tz) $date->setTimezone(self::$gmtTimezone); |
|
633 | 4 | return $date->format($this->get_db_date_format()); |
|
634 | } |
||
635 | |||
636 | /** |
||
637 | * Format DateTime object as user date |
||
638 | * Note: by default does not convert TZ! |
||
639 | * @param DateTime $date |
||
640 | * @param boolean $tz Perform TZ conversion? |
||
641 | * @param User $user |
||
642 | * @return string |
||
643 | */ |
||
644 | 37 | public function asUserDate(DateTime $date, $tz = false, User $user = null) |
|
645 | { |
||
646 | 37 | if($tz) $this->tzUser($date, $user); |
|
647 | 37 | return $date->format($this->get_date_format($user)); |
|
648 | } |
||
649 | |||
650 | /** |
||
651 | * Format DateTime object as DB time |
||
652 | * |
||
653 | * @param DateTime $date |
||
654 | * @return string |
||
655 | */ |
||
656 | 2 | public function asDbTime(DateTime $date) |
|
657 | { |
||
658 | 2 | $date->setTimezone(self::$gmtTimezone); |
|
659 | 2 | return $date->format($this->get_db_time_format()); |
|
660 | } |
||
661 | |||
662 | /** |
||
663 | * Format DateTime object as user time |
||
664 | * |
||
665 | * @param DateTime $date |
||
666 | * @param User $user |
||
667 | * @return string |
||
668 | */ |
||
669 | 1 | public function asUserTime(DateTime $date, User $user = null) |
|
670 | { |
||
671 | 1 | $this->tzUser($date, $user); |
|
672 | 1 | return $date->format($this->get_time_format($user)); |
|
673 | } |
||
674 | |||
675 | /** |
||
676 | * Get DateTime from DB datetime string |
||
677 | * |
||
678 | * @param string $date |
||
679 | * @return SugarDateTime |
||
680 | */ |
||
681 | 12 | public function fromDb($date) |
|
682 | { |
||
683 | try { |
||
684 | 12 | return SugarDateTime::createFromFormat(self::DB_DATETIME_FORMAT, $date, self::$gmtTimezone); |
|
685 | } catch (Exception $e) { |
||
686 | $GLOBALS['log']->error("fromDb: Conversion of $date from DB format failed: {$e->getMessage()}"); |
||
687 | return null; |
||
688 | } |
||
689 | } |
||
690 | |||
691 | /** |
||
692 | * Create a date from a certain type of field in DB format |
||
693 | * The types are: date, time, datatime[combo] |
||
694 | * @param string $date the datetime string |
||
695 | * @param string $type string type |
||
696 | * @return SugarDateTime |
||
697 | */ |
||
698 | public function fromDbType($date, $type) |
||
699 | { |
||
700 | switch($type) { |
||
701 | case "date": |
||
702 | return $this->fromDbDate($date); |
||
703 | break; |
||
704 | case 'time': |
||
705 | return $this->fromDbFormat($date, self::DB_TIME_FORMAT); |
||
706 | break; |
||
707 | case 'datetime': |
||
708 | case 'datetimecombo': |
||
709 | default: |
||
710 | return $this->fromDb($date); |
||
711 | } |
||
712 | } |
||
713 | |||
714 | /** |
||
715 | * Get DateTime from DB date string |
||
716 | * |
||
717 | * @param string $date |
||
718 | * @return SugarDateTime |
||
719 | */ |
||
720 | public function fromDbDate($date) |
||
721 | { |
||
722 | try { |
||
723 | return SugarDateTime::createFromFormat(self::DB_DATE_FORMAT, $date, self::$gmtTimezone); |
||
724 | } catch (Exception $e) { |
||
725 | $GLOBALS['log']->error("fromDbDate: Conversion of $date from DB format failed: {$e->getMessage()}"); |
||
726 | return null; |
||
727 | } |
||
728 | } |
||
729 | |||
730 | /** |
||
731 | * Get DateTime from DB datetime string using non-standard format |
||
732 | * |
||
733 | * Non-standard format usually would be only date, only time, etc. |
||
734 | * |
||
735 | * @param string $date |
||
736 | * @param string $format format to accept |
||
737 | * @return SugarDateTime |
||
738 | */ |
||
739 | public function fromDbFormat($date, $format) |
||
740 | { |
||
741 | try { |
||
742 | return SugarDateTime::createFromFormat($format, $date, self::$gmtTimezone); |
||
743 | } catch (Exception $e) { |
||
744 | $GLOBALS['log']->error("fromDbFormat: Conversion of $date from DB format $format failed: {$e->getMessage()}"); |
||
745 | return null; |
||
746 | } |
||
747 | } |
||
748 | |||
749 | /** |
||
750 | * Get DateTime from user datetime string |
||
751 | * |
||
752 | * @param string $date |
||
753 | * @param User $user |
||
754 | * @return SugarDateTime |
||
755 | */ |
||
756 | 7 | public function fromUser($date, User $user = null) |
|
757 | { |
||
758 | 7 | $res = null; |
|
759 | try { |
||
760 | 7 | $res = SugarDateTime::createFromFormat($this->get_date_time_format($user), $date, $this->_getUserTZ($user)); |
|
761 | } catch (Exception $e) { |
||
762 | $GLOBALS['log']->error("fromUser: Conversion of $date exception: {$e->getMessage()}"); |
||
763 | } |
||
764 | 7 | if(!($res instanceof DateTime)) { |
|
765 | 4 | $uf = $this->get_date_time_format($user); |
|
766 | 4 | $GLOBALS['log']->error("fromUser: Conversion of $date from user format $uf failed"); |
|
767 | 4 | return null; |
|
768 | } |
||
769 | 3 | return $res; |
|
770 | } |
||
771 | |||
772 | /** |
||
773 | * Create a date from a certain type of field in user format |
||
774 | * The types are: date, time, datatime[combo] |
||
775 | * @param string $date the datetime string |
||
776 | * @param string $type string type |
||
777 | * @param User $user |
||
778 | * @return SugarDateTime |
||
779 | */ |
||
780 | public function fromUserType($date, $type, $user = null) |
||
781 | { |
||
782 | switch($type) { |
||
783 | case "date": |
||
784 | return $this->fromUserDate($date, $user); |
||
785 | break; |
||
786 | case 'time': |
||
787 | return $this->fromUserTime($date, $user); |
||
788 | break; |
||
789 | case 'datetime': |
||
790 | case 'datetimecombo': |
||
791 | default: |
||
792 | return $this->fromUser($date, $user); |
||
793 | } |
||
794 | } |
||
795 | |||
796 | /** |
||
797 | * Get DateTime from user time string |
||
798 | * |
||
799 | * @param string $date |
||
800 | * @param User $user |
||
801 | * @return SugarDateTime |
||
802 | */ |
||
803 | public function fromUserTime($date, User $user = null) |
||
804 | { |
||
805 | try { |
||
806 | return SugarDateTime::createFromFormat($this->get_time_format($user), $date, $this->_getUserTZ($user)); |
||
807 | } catch (Exception $e) { |
||
808 | $uf = $this->get_time_format($user); |
||
809 | $GLOBALS['log']->error("fromUserTime: Conversion of $date from user format $uf failed: {$e->getMessage()}"); |
||
810 | return null; |
||
811 | } |
||
812 | } |
||
813 | |||
814 | /** |
||
815 | * Get DateTime from user date string |
||
816 | * Usually for calendar-related functions like holidays |
||
817 | * Note: by default does not convert tz! |
||
818 | * @param string $date |
||
819 | * @param bool $convert_tz perform TZ converson? |
||
820 | * @param User $user |
||
821 | * @return SugarDateTime |
||
822 | */ |
||
823 | 13 | public function fromUserDate($date, $convert_tz = false, User $user = null) |
|
824 | { |
||
825 | try { |
||
826 | 13 | return SugarDateTime::createFromFormat($this->get_date_format($user), $date, $convert_tz?$this->_getUserTZ($user):self::$gmtTimezone); |
|
827 | } catch (Exception $e) { |
||
828 | $uf = $this->get_date_format($user); |
||
829 | $GLOBALS['log']->error("fromUserDate: Conversion of $date from user format $uf failed: {$e->getMessage()}"); |
||
830 | return null; |
||
831 | } |
||
832 | } |
||
833 | |||
834 | /** |
||
835 | * Create a date object from any string |
||
836 | * |
||
837 | * Same formats accepted as for DateTime ctor |
||
838 | * |
||
839 | * @param string $date |
||
840 | * @param User $user |
||
841 | * @return SugarDateTime |
||
842 | */ |
||
843 | 18 | public function fromString($date, User $user = null) |
|
844 | { |
||
845 | try { |
||
846 | 18 | return new SugarDateTime($date, $this->_getUserTZ($user)); |
|
847 | } catch (Exception $e) { |
||
848 | $GLOBALS['log']->error("fromString: Conversion of $date from string failed: {$e->getMessage()}"); |
||
849 | return null; |
||
850 | } |
||
851 | } |
||
852 | |||
853 | /** |
||
854 | * Create DateTime from timestamp |
||
855 | * |
||
856 | * @param interger|string $ts |
||
857 | * @return SugarDateTime |
||
858 | */ |
||
859 | 2 | public function fromTimestamp($ts) |
|
860 | { |
||
861 | 2 | return new SugarDateTime("@$ts"); |
|
862 | } |
||
863 | |||
864 | /** |
||
865 | * Convert DateTime to GMT timezone |
||
866 | * @param DateTime $date |
||
867 | * @return DateTime |
||
868 | */ |
||
869 | 2 | public function tzGMT(DateTime $date) |
|
870 | { |
||
871 | 2 | return $date->setTimezone(self::$gmtTimezone); |
|
872 | } |
||
873 | |||
874 | /** |
||
875 | * Convert DateTime to user timezone |
||
876 | * @param DateTime $date |
||
877 | * @param User $user |
||
878 | * @return DateTime |
||
879 | */ |
||
880 | 76 | public function tzUser(DateTime $date, User $user = null) |
|
881 | { |
||
882 | 76 | return $date->setTimezone($this->_getUserTZ($user)); |
|
883 | } |
||
884 | |||
885 | /** |
||
886 | * Get string defining midnight in current user's format |
||
887 | * @param string $format Time format to use |
||
888 | * @return string |
||
889 | */ |
||
890 | 4 | protected function _get_midnight($format = null) |
|
891 | { |
||
892 | 4 | $zero = new DateTime("@0", self::$gmtTimezone); |
|
893 | 4 | return $zero->format($format?$format:$this->get_time_format()); |
|
894 | } |
||
895 | |||
896 | /** |
||
897 | * |
||
898 | * Basic conversion function |
||
899 | * |
||
900 | * Converts between two string dates in different formats and timezones |
||
901 | * |
||
902 | * @param string $date |
||
903 | * @param string $fromFormat |
||
904 | * @param DateTimeZone $fromTZ |
||
905 | * @param string $toFormat |
||
906 | * @param DateTimeZone|null $toTZ |
||
907 | * @param bool $expand If string lacks time, expand it to include time |
||
908 | * @return string |
||
909 | */ |
||
910 | 100 | protected function _convert($date, $fromFormat, $fromTZ, $toFormat, $toTZ, $expand = false) |
|
911 | { |
||
912 | 100 | $date = trim($date); |
|
913 | 100 | if (empty($date)) { |
|
914 | 3 | return $date; |
|
915 | } |
||
916 | try { |
||
917 | 98 | if ($expand && strlen($date) <= 10) { |
|
918 | 4 | $date = $this->expandDate($date, $fromFormat); |
|
919 | } |
||
920 | 98 | $phpdate = SugarDateTime::createFromFormat($fromFormat, $date, $fromTZ); |
|
921 | 98 | if ($phpdate == false) { |
|
922 | 1 | $GLOBALS['log']->error("convert: Conversion of $date from $fromFormat to $toFormat failed"); |
|
923 | 1 | return ''; |
|
924 | } |
||
925 | 97 | if ($fromTZ !== $toTZ && $toTZ != null) { |
|
926 | $phpdate->setTimeZone($toTZ); |
||
927 | } |
||
928 | 97 | return $phpdate->format($toFormat); |
|
929 | } catch (Exception $e) { |
||
930 | $GLOBALS['log']->error("Conversion of $date from $fromFormat to $toFormat failed: {$e->getMessage()}"); |
||
931 | return ''; |
||
932 | } |
||
933 | } |
||
934 | |||
935 | /** |
||
936 | * Convert DB datetime to local datetime |
||
937 | * |
||
938 | * TZ conversion is controlled by parameter |
||
939 | * |
||
940 | * @param string $date Original date in DB format |
||
941 | * @param bool $meridiem Ignored for BC |
||
942 | * @param bool $convert_tz Perform TZ conversion? |
||
943 | * @param User $user User owning the conversion formats |
||
944 | * @return string Date in display format |
||
945 | */ |
||
946 | 85 | function to_display_date_time($date, $meridiem = true, $convert_tz = true, $user = null) |
|
947 | { |
||
948 | 85 | return $this->_convert($date, self::DB_DATETIME_FORMAT, self::$gmtTimezone, $this->get_date_time_format($user), |
|
949 | 85 | $convert_tz ? $this->_getUserTZ($user) : self::$gmtTimezone, true); |
|
950 | } |
||
951 | |||
952 | /** |
||
953 | * Converts DB time string to local time string |
||
954 | * |
||
955 | * TZ conversion depends on parameter |
||
956 | * |
||
957 | * @param string $date Time in DB format |
||
958 | * @param bool $meridiem |
||
959 | * @param bool $convert_tz Perform TZ conversion? |
||
960 | * @return string Time in user-defined format |
||
961 | */ |
||
962 | 4 | public function to_display_time($date, $meridiem = true, $convert_tz = true) |
|
963 | { |
||
964 | 4 | if($convert_tz && strpos($date, ' ') === false) { |
|
965 | // we need TZ adjustment but have no date, assume today |
||
966 | $date = $this->expandTime($date, self::DB_DATETIME_FORMAT, self::$gmtTimezone); |
||
967 | } |
||
968 | 4 | return $this->_convert($date, |
|
969 | 4 | $convert_tz ? self::DB_DATETIME_FORMAT : self::DB_TIME_FORMAT, self::$gmtTimezone, |
|
970 | 4 | $this->get_time_format(), $convert_tz ? $this->_getUserTZ() : self::$gmtTimezone); |
|
971 | } |
||
972 | |||
973 | /** |
||
974 | * Splits time in given format into components |
||
975 | * |
||
976 | * Components: h, m, s, a (am/pm) if format requires it |
||
977 | * If format has am/pm, hour is 12-based, otherwise 24-based |
||
978 | * |
||
979 | * @param string $date |
||
980 | * @param string $format |
||
981 | * @return array |
||
982 | */ |
||
983 | public function splitTime($date, $format) |
||
984 | { |
||
985 | if (! ($date instanceof DateTime)) { |
||
986 | $date = SugarDateTime::createFromFormat($format, $date); |
||
987 | } |
||
988 | $ampm = strpbrk($format, 'aA'); |
||
989 | $datearr = array( |
||
990 | "h" => ($ampm == false) ? $date->format("H") : $date->format("h"), |
||
991 | 'm' => $date->format("i"), |
||
992 | 's' => $date->format("s") |
||
993 | ); |
||
994 | if ($ampm) { |
||
995 | $datearr['a'] = ($ampm{0} == 'a') ? $date->format("a") : $date->format("A"); |
||
996 | } |
||
997 | return $datearr; |
||
998 | } |
||
999 | |||
1000 | /** |
||
1001 | * Converts DB date string to local date string |
||
1002 | * |
||
1003 | * TZ conversion depens on parameter |
||
1004 | * |
||
1005 | * @param string $date Date in DB format |
||
1006 | * @param bool $convert_tz Perform TZ conversion? |
||
1007 | * @return string Date in user-defined format |
||
1008 | */ |
||
1009 | 2 | public function to_display_date($date, $convert_tz = true) |
|
1010 | { |
||
1011 | 2 | return $this->_convert($date, |
|
1012 | 2 | self::DB_DATETIME_FORMAT, self::$gmtTimezone, |
|
1013 | 2 | $this->get_date_format(), $convert_tz ? $this->_getUserTZ() : self::$gmtTimezone, true); |
|
1014 | } |
||
1015 | |||
1016 | /** |
||
1017 | * Convert date from format to format |
||
1018 | * |
||
1019 | * No TZ conversion is performed! |
||
1020 | * |
||
1021 | * @param string $date |
||
1022 | * @param string $from Source format |
||
1023 | * @param string $to Destination format |
||
1024 | * @return string Converted date |
||
1025 | */ |
||
1026 | function to_display($date, $from, $to) |
||
1027 | { |
||
1028 | return $this->_convert($date, $from, self::$gmtTimezone, $to, self::$gmtTimezone); |
||
1029 | } |
||
1030 | |||
1031 | /** |
||
1032 | * Get DB datetime format |
||
1033 | * @return string |
||
1034 | */ |
||
1035 | 87 | public function get_db_date_time_format() |
|
1036 | { |
||
1037 | 87 | return self::DB_DATETIME_FORMAT; |
|
1038 | } |
||
1039 | |||
1040 | /** |
||
1041 | * Get DB date format |
||
1042 | * @return string |
||
1043 | */ |
||
1044 | 4 | public function get_db_date_format() |
|
1045 | { |
||
1046 | 4 | return self::DB_DATE_FORMAT; |
|
1047 | } |
||
1048 | |||
1049 | /** |
||
1050 | * Get DB time format |
||
1051 | * @return string |
||
1052 | */ |
||
1053 | 2 | public function get_db_time_format() |
|
1054 | { |
||
1055 | 2 | return self::DB_TIME_FORMAT; |
|
1056 | } |
||
1057 | |||
1058 | /** |
||
1059 | * Convert date from local datetime to GMT-based DB datetime |
||
1060 | * |
||
1061 | * Includes TZ conversion. |
||
1062 | * |
||
1063 | * @param string $date |
||
1064 | * @return string Datetime in DB format |
||
1065 | */ |
||
1066 | 11 | public function to_db($date) |
|
1067 | { |
||
1068 | 11 | return $this->_convert($date, |
|
1069 | 11 | $this->get_date_time_format(), $this->_getUserTZ(), |
|
1070 | 11 | $this->get_db_date_time_format(), self::$gmtTimezone, |
|
1071 | 11 | true); |
|
1072 | } |
||
1073 | |||
1074 | /** |
||
1075 | * Convert local datetime to DB date |
||
1076 | * |
||
1077 | * TZ conversion depends on parameter. If false, only format conversion is performed. |
||
1078 | * |
||
1079 | * @param string $date Local date |
||
1080 | * @param bool $convert_tz Should time and TZ be taken into account? |
||
1081 | * @return string Date in DB format |
||
1082 | */ |
||
1083 | 5 | public function to_db_date($date, $convert_tz = true) |
|
1084 | { |
||
1085 | 5 | return $this->_convert($date, |
|
1086 | 5 | $this->get_date_time_format(), $convert_tz ? $this->_getUserTZ() : self::$gmtTimezone, |
|
1087 | 5 | self::DB_DATE_FORMAT, self::$gmtTimezone, true); |
|
1088 | } |
||
1089 | |||
1090 | /** |
||
1091 | * Convert local datetime to DB time |
||
1092 | * |
||
1093 | * TZ conversion depends on parameter. If false, only format conversion is performed. |
||
1094 | * |
||
1095 | * @param string $date Local date |
||
1096 | * @param bool $convert_tz Should time and TZ be taken into account? |
||
1097 | * @return string Time in DB format |
||
1098 | */ |
||
1099 | public function to_db_time($date, $convert_tz = true) |
||
1100 | { |
||
1101 | $format = $this->get_date_time_format(); |
||
1102 | $tz = $convert_tz ? $this->_getUserTZ() : self::$gmtTimezone; |
||
1103 | if($convert_tz && strpos($date, ' ') === false) { |
||
1104 | // we need TZ adjustment but have short string, expand it to full one |
||
1105 | // FIXME: if the string is short, should we assume date or time? |
||
1106 | $date = $this->expandTime($date, $format, $tz); |
||
1107 | } |
||
1108 | return $this->_convert($date, |
||
1109 | $convert_tz ? $format : $this->get_time_format(), |
||
1110 | $tz, |
||
1111 | self::DB_TIME_FORMAT, self::$gmtTimezone); |
||
1112 | } |
||
1113 | |||
1114 | /** |
||
1115 | * Takes a Date & Time value in local format and converts them to DB format |
||
1116 | * No TZ conversion! |
||
1117 | * |
||
1118 | * @param string $date |
||
1119 | * @param string $time |
||
1120 | * @return array Date & time in DB format |
||
1121 | **/ |
||
1122 | public function to_db_date_time($date, $time) |
||
1123 | { |
||
1124 | try { |
||
1125 | $phpdate = SugarDateTime::createFromFormat($this->get_date_time_format(), |
||
1126 | $this->merge_date_time($date, $time), self::$gmtTimezone); |
||
1127 | if ($phpdate == false) { |
||
1128 | return array('', ''); |
||
1129 | } |
||
1130 | return array($this->asDbDate($phpdate), $this->asDbTime($phpdate)); |
||
1131 | } catch (Exception $e) { |
||
1132 | $GLOBALS['log']->error("Conversion of $date,$time failed"); |
||
1133 | return array('', ''); |
||
1134 | } |
||
1135 | } |
||
1136 | |||
1137 | /** |
||
1138 | * Return current time in DB format |
||
1139 | * @return string |
||
1140 | */ |
||
1141 | 86 | public function nowDb() |
|
1142 | { |
||
1143 | 86 | if(!$this->allow_cache) { |
|
1144 | $nowGMT = $this->getNow(); |
||
1145 | } else { |
||
1146 | 86 | $nowGMT = $this->now; |
|
1147 | } |
||
1148 | 86 | return $this->asDb($nowGMT); |
|
1149 | } |
||
1150 | |||
1151 | /** |
||
1152 | * Return current date in DB format |
||
1153 | * @return string |
||
1154 | */ |
||
1155 | 1 | public function nowDbDate() |
|
1156 | { |
||
1157 | 1 | if(!$this->allow_cache) { |
|
1158 | $nowGMT = $this->getNow(); |
||
1159 | } else { |
||
1160 | 1 | $nowGMT = $this->now; |
|
1161 | } |
||
1162 | 1 | return $this->asDbDate($nowGMT, true); |
|
1163 | } |
||
1164 | |||
1165 | /** |
||
1166 | * Get 'now' DateTime object |
||
1167 | * @param bool $userTz return in user timezone? |
||
1168 | * @return SugarDateTime |
||
1169 | */ |
||
1170 | 84 | public function getNow($userTz = false) |
|
1171 | { |
||
1172 | 84 | if(!$this->allow_cache) { |
|
1173 | return new SugarDateTime("now", $userTz?$this->_getUserTz():self::$gmtTimezone); |
||
1174 | } |
||
1175 | // TODO: should we return clone? |
||
1176 | 84 | $now = clone $this->now; |
|
1177 | 84 | if($userTz) { |
|
1178 | 62 | return $this->tzUser($now); |
|
1179 | } |
||
1180 | 29 | return $now; |
|
1181 | } |
||
1182 | |||
1183 | /** |
||
1184 | * Set 'now' time |
||
1185 | * For testability - predictable time value |
||
1186 | * @param DateTime $now |
||
1187 | * @return TimeDate $this |
||
1188 | */ |
||
1189 | public function setNow($now) |
||
1190 | { |
||
1191 | $this->now = $now; |
||
0 ignored issues
–
show
|
|||
1192 | return $this; |
||
1193 | } |
||
1194 | |||
1195 | /** |
||
1196 | * Return current datetime in local format |
||
1197 | * @return string |
||
1198 | */ |
||
1199 | 7 | public function now() |
|
1200 | { |
||
1201 | 7 | return $this->asUser($this->getNow()); |
|
1202 | } |
||
1203 | |||
1204 | /** |
||
1205 | * Return current date in User format |
||
1206 | * @return string |
||
1207 | */ |
||
1208 | 1 | public function nowDate() |
|
1209 | { |
||
1210 | 1 | return $this->asUserDate($this->getNow()); |
|
1211 | } |
||
1212 | |||
1213 | /** |
||
1214 | * Get user format's time separator |
||
1215 | * @return string |
||
1216 | */ |
||
1217 | 4 | public function timeSeparator() |
|
1218 | { |
||
1219 | 4 | if (empty($this->time_separator)) { |
|
1220 | 4 | $this->time_separator = $this->timeSeparatorFormat($this->get_time_format()); |
|
1221 | } |
||
1222 | 4 | return $this->time_separator; |
|
1223 | } |
||
1224 | |||
1225 | /** |
||
1226 | * Find out format's time separator |
||
1227 | * @param string $timeformat Time format |
||
1228 | * @return stringS |
||
1229 | */ |
||
1230 | 4 | public function timeSeparatorFormat($timeformat) |
|
1231 | { |
||
1232 | 4 | $date = $this->_convert("00:11:22", self::DB_TIME_FORMAT, null, $timeformat, null); |
|
1233 | 4 | if (preg_match('/\d+(.+?)11/', $date, $matches)) { |
|
1234 | 4 | $sep = $matches[1]; |
|
1235 | } else { |
||
1236 | $sep = ':'; |
||
1237 | } |
||
1238 | 4 | return $sep; |
|
1239 | } |
||
1240 | |||
1241 | /** |
||
1242 | * Returns start and end of a certain local date in GMT |
||
1243 | * Example: for May 19 in PDT start would be 2010-05-19 07:00:00, end would be 2010-05-20 06:59:59 |
||
1244 | * @param string|DateTime $date Date in any suitable format |
||
1245 | * @param User $user |
||
1246 | * @return array Start & end date in start, startdate, starttime, end, enddate, endtime |
||
1247 | */ |
||
1248 | public function getDayStartEndGMT($date, User $user = null) |
||
1249 | { |
||
1250 | if ($date instanceof DateTime) { |
||
1251 | $min = clone $date; |
||
1252 | $min->setTimezone($this->_getUserTZ($user)); |
||
1253 | $max = clone $date; |
||
1254 | $max->setTimezone($this->_getUserTZ($user)); |
||
1255 | } else { |
||
1256 | $min = new DateTime($date, $this->_getUserTZ($user)); |
||
1257 | $max = new DateTime($date, $this->_getUserTZ($user)); |
||
1258 | } |
||
1259 | $min->setTime(0, 0); |
||
1260 | $max->setTime(23, 59, 59); |
||
1261 | |||
1262 | $min->setTimezone(self::$gmtTimezone); |
||
1263 | $max->setTimezone(self::$gmtTimezone); |
||
1264 | |||
1265 | $result['start'] = $this->asDb($min); |
||
1266 | $result['startdate'] = $this->asDbDate($min); |
||
1267 | $result['starttime'] = $this->asDbTime($min); |
||
1268 | $result['end'] = $this->asDb($max); |
||
1269 | $result['enddate'] = $this->asDbDate($max); |
||
1270 | $result['endtime'] = $this->asDbtime($max); |
||
1271 | |||
1272 | return $result; |
||
1273 | } |
||
1274 | |||
1275 | /** |
||
1276 | * Expand date format by adding midnight to it |
||
1277 | * Note: date is assumed to be in target format already |
||
1278 | * @param string $date |
||
1279 | * @param string $format Target format |
||
1280 | * @return string |
||
1281 | */ |
||
1282 | 4 | public function expandDate($date, $format) |
|
1283 | { |
||
1284 | 4 | $formats = $this->split_date_time($format); |
|
1285 | 4 | if(isset($formats[1])) { |
|
1286 | 4 | return $this->merge_date_time($date, $this->_get_midnight($formats[1])); |
|
1287 | } |
||
1288 | return $date; |
||
1289 | } |
||
1290 | |||
1291 | /** |
||
1292 | * Expand time format by adding today to it |
||
1293 | * Note: time is assumed to be in target format already |
||
1294 | * @param string $date |
||
1295 | * @param string $format Target format |
||
1296 | * @param DateTimeZone $tz |
||
1297 | * @return string |
||
1298 | */ |
||
1299 | public function expandTime($date, $format, $tz) |
||
1300 | { |
||
1301 | $formats = $this->split_date_time($format); |
||
1302 | if(isset($formats[1])) { |
||
1303 | $now = clone $this->getNow(); |
||
1304 | $now->setTimezone($tz); |
||
1305 | return $this->merge_date_time($now->format($formats[0]), $date); |
||
1306 | } |
||
1307 | return $date; |
||
1308 | } |
||
1309 | |||
1310 | /** |
||
1311 | * Get midnight (start of the day) in local time format |
||
1312 | * |
||
1313 | * @return Time string |
||
1314 | */ |
||
1315 | function get_default_midnight() |
||
1316 | { |
||
1317 | return $this->_get_midnight($this->get_time_format()); |
||
1318 | } |
||
1319 | |||
1320 | /** |
||
1321 | * Get the name of the timezone for the user |
||
1322 | * @param User $user User, default - current user |
||
1323 | * @return string |
||
1324 | */ |
||
1325 | 8 | public static function userTimezone(User $user = null) |
|
1326 | { |
||
1327 | 8 | $user = self::getInstance()->_getUser($user); |
|
1328 | 8 | if(empty($user)) { |
|
1329 | return ''; |
||
1330 | } |
||
1331 | 8 | $tz = self::getInstance()->_getUserTZ($user); |
|
1332 | 8 | if($tz) { |
|
1333 | 8 | return $tz->getName(); |
|
1334 | } |
||
1335 | return ''; |
||
1336 | } |
||
1337 | |||
1338 | /** |
||
1339 | * Guess the timezone for the current user |
||
1340 | * @param int $userOffset Offset from GMT in minutes |
||
1341 | * @return string |
||
1342 | */ |
||
1343 | public static function guessTimezone($userOffset = 0) |
||
1344 | { |
||
1345 | if(!is_numeric($userOffset)) { |
||
1346 | return ''; |
||
1347 | } |
||
1348 | $defaultZones= array( |
||
1349 | 'America/Anchorage', 'America/Los_Angeles', 'America/Phoenix', 'America/Chicago', |
||
1350 | 'America/New_York', 'America/Argentina/Buenos_Aires', 'America/Montevideo', |
||
1351 | 'Europe/London', 'Europe/Amsterdam', 'Europe/Athens', 'Europe/Moscow', |
||
1352 | 'Asia/Tbilisi', 'Asia/Omsk', 'Asia/Jakarta', 'Asia/Hong_Kong', |
||
1353 | 'Asia/Tokyo', 'Pacific/Guam', 'Australia/Sydney', 'Australia/Perth', |
||
1354 | ); |
||
1355 | |||
1356 | $now = new DateTime(); |
||
1357 | $tzlist = timezone_identifiers_list(); |
||
1358 | if($userOffset == 0) { |
||
1359 | $gmtOffset = date('Z'); |
||
1360 | $nowtz = date('e'); |
||
1361 | if(in_array($nowtz, $tzlist)) { |
||
1362 | array_unshift($defaultZones, $nowtz); |
||
1363 | } else { |
||
1364 | $nowtz = timezone_name_from_abbr(date('T'), $gmtOffset, date('I')); |
||
1365 | if(in_array($nowtz, $tzlist)) { |
||
1366 | array_unshift($defaultZones, $nowtz); |
||
1367 | } |
||
1368 | } |
||
1369 | } else { |
||
1370 | $gmtOffset = $userOffset * 60; |
||
1371 | } |
||
1372 | foreach($defaultZones as $zoneName) { |
||
1373 | $tz = new DateTimeZone($zoneName); |
||
1374 | if($tz->getOffset($now) == $gmtOffset) { |
||
1375 | return $tz->getName(); |
||
1376 | } |
||
1377 | } |
||
1378 | // try all zones |
||
1379 | foreach($tzlist as $zoneName) { |
||
1380 | $tz = new DateTimeZone($zoneName); |
||
1381 | if($tz->getOffset($now) == $gmtOffset) { |
||
1382 | return $tz->getName(); |
||
1383 | } |
||
1384 | } |
||
1385 | return null; |
||
1386 | } |
||
1387 | |||
1388 | /** |
||
1389 | * Get the description of the user timezone for specific date |
||
1390 | * Like: PST(+08:00) |
||
1391 | * We need the date because it can be DST or non-DST |
||
1392 | * Note it's different from TZ name in tzName() that relates to current date |
||
1393 | * @param DateTime $date Current date |
||
1394 | * @param User $user User, default - current user |
||
1395 | * @return string |
||
1396 | */ |
||
1397 | 5 | public static function userTimezoneSuffix(DateTime $date, User $user = null) |
|
1398 | { |
||
1399 | 5 | $user = self::getInstance()->_getUser($user); |
|
1400 | 5 | if(empty($user)) { |
|
1401 | return ''; |
||
1402 | } |
||
1403 | 5 | self::getInstance()->tzUser($date, $user); |
|
1404 | 5 | return $date->format('T(P)'); |
|
1405 | } |
||
1406 | |||
1407 | /** |
||
1408 | * Get display name for a certain timezone |
||
1409 | * Note: it uses current date for GMT offset, so it may be not suitable for displaying generic dates |
||
1410 | * @param string|DateTimeZone $name TZ name |
||
1411 | * @return string |
||
1412 | */ |
||
1413 | 7 | public static function tzName($name) |
|
1414 | { |
||
1415 | 7 | if(empty($name)) { |
|
1416 | return ''; |
||
1417 | } |
||
1418 | 7 | if($name instanceof DateTimeZone) { |
|
1419 | $tz = $name; |
||
1420 | } else { |
||
1421 | 7 | $tz = timezone_open($name); |
|
1422 | } |
||
1423 | 7 | if(!$tz) { |
|
1424 | return "???"; |
||
1425 | } |
||
1426 | 7 | $now = new DateTime("now", $tz); |
|
1427 | 7 | $off = $now->getOffset(); |
|
1428 | 7 | $translated = translate('timezone_dom','',$name); |
|
1429 | 7 | if(is_string($translated) && !empty($translated)) { |
|
1430 | $name = $translated; |
||
1431 | } |
||
1432 | 7 | return sprintf("%s (GMT%+2d:%02d)%s", str_replace('_',' ', $name), $off/3600, (abs($off)/60)%60, "");//$now->format('I')==1?"(+DST)":""); |
|
1433 | } |
||
1434 | |||
1435 | |||
1436 | /** |
||
1437 | * Timezone sorting helper |
||
1438 | * Sorts by name |
||
1439 | * @param array $a |
||
1440 | * @param array $b |
||
1441 | * @internal |
||
1442 | * @return int |
||
1443 | */ |
||
1444 | public static function _sortTz($a, $b) |
||
1445 | { |
||
1446 | if($a[0] == $b[0]) { |
||
1447 | return strcmp($a[1], $b[1]); |
||
1448 | } else { |
||
1449 | return $a[0]<$b[0]?-1:1; |
||
1450 | } |
||
1451 | } |
||
1452 | |||
1453 | /** |
||
1454 | * Get list of all timezones in the system |
||
1455 | * @return array |
||
1456 | */ |
||
1457 | public static function getTimezoneList() |
||
1458 | { |
||
1459 | $now = new DateTime(); |
||
1460 | $res_zones = $zones = array(); |
||
1461 | foreach(timezone_identifiers_list() as $zoneName) { |
||
1462 | $tz = new DateTimeZone($zoneName); |
||
1463 | $zones[$zoneName] = array($tz->getOffset($now), self::tzName($zoneName)); |
||
1464 | } |
||
1465 | uasort($zones, array('TimeDate', '_sortTz')); |
||
1466 | foreach($zones as $name => $zonedef) { |
||
1467 | $res_zones[$name] = $zonedef[1]; |
||
1468 | } |
||
1469 | return $res_zones; |
||
1470 | } |
||
1471 | |||
1472 | /** |
||
1473 | * Print timestamp in RFC2616 format: |
||
1474 | * @param int|null $ts Null means current ts |
||
1475 | * @return string |
||
1476 | */ |
||
1477 | public static function httpTime($ts = null) |
||
1478 | { |
||
1479 | if($ts === null) { |
||
1480 | $ts = time(); |
||
1481 | } |
||
1482 | return gmdate(self::RFC2616_FORMAT, $ts); |
||
1483 | } |
||
1484 | |||
1485 | /** |
||
1486 | * Create datetime object from calendar array |
||
1487 | * @param array $time |
||
1488 | * @return SugarDateTime |
||
1489 | */ |
||
1490 | public function fromTimeArray($time) |
||
1491 | { |
||
1492 | if (! isset( $time) || count($time) == 0 ) |
||
1493 | { |
||
1494 | return $this->nowDb(); |
||
1495 | } |
||
1496 | elseif ( isset( $time['ts'])) |
||
1497 | { |
||
1498 | return $this->fromTimestamp($time['ts']); |
||
1499 | } |
||
1500 | elseif ( isset( $time['date_str'])) |
||
1501 | { |
||
1502 | return $this->fromDb($time['date_str']); |
||
1503 | } |
||
1504 | else |
||
1505 | { |
||
1506 | $hour = 0; |
||
1507 | $min = 0; |
||
1508 | $sec = 0; |
||
1509 | $now = $this->getNow(true); |
||
1510 | $day = $now->day; |
||
1511 | $month = $now->month; |
||
1512 | $year = $now->year; |
||
1513 | if (isset($time['sec'])) |
||
1514 | { |
||
1515 | $sec = $time['sec']; |
||
1516 | } |
||
1517 | if (isset($time['min'])) |
||
1518 | { |
||
1519 | $min = $time['min']; |
||
1520 | } |
||
1521 | if (isset($time['hour'])) |
||
1522 | { |
||
1523 | $hour = $time['hour']; |
||
1524 | } |
||
1525 | if (isset($time['day'])) |
||
1526 | { |
||
1527 | $day = $time['day']; |
||
1528 | } |
||
1529 | if (isset($time['month'])) |
||
1530 | { |
||
1531 | $month = $time['month']; |
||
1532 | } |
||
1533 | if (isset($time['year']) && $time['year'] >= 1970) |
||
1534 | { |
||
1535 | $year = $time['year']; |
||
1536 | } |
||
1537 | return $now->setDate($year, $month, $day)->setTime($hour, $min, $sec)->setTimeZone(self::$gmtTimezone); |
||
1538 | } |
||
1539 | return null; |
||
1540 | } |
||
1541 | |||
1542 | /** |
||
1543 | * Returns the date portion of a datetime string |
||
1544 | * |
||
1545 | * @param string $datetime |
||
1546 | * @return string |
||
1547 | */ |
||
1548 | public function getDatePart($datetime) |
||
1549 | { |
||
1550 | list($date, $time) = $this->split_date_time($datetime); |
||
1551 | return $date; |
||
1552 | } |
||
1553 | |||
1554 | /** |
||
1555 | * Returns the time portion of a datetime string |
||
1556 | * |
||
1557 | * @param string $datetime |
||
1558 | * @return string |
||
1559 | */ |
||
1560 | public function getTimePart($datetime) |
||
1561 | { |
||
1562 | list($date, $time) = $this->split_date_time($datetime); |
||
1563 | return $time; |
||
1564 | } |
||
1565 | |||
1566 | /** |
||
1567 | * Returns the offset from user's timezone to GMT |
||
1568 | * @param User $user |
||
1569 | * @param DateTime $time When the offset is taken, default is now |
||
1570 | * @return int Offset in minutes |
||
1571 | */ |
||
1572 | 12 | public function getUserUTCOffset(User $user = null, DateTime $time = null) |
|
1573 | { |
||
1574 | 12 | if(empty($time)) { |
|
1575 | 12 | $time = $this->now; |
|
1576 | } |
||
1577 | 12 | return $this->_getUserTZ($user)->getOffset($time) / 60; |
|
1578 | } |
||
1579 | |||
1580 | /** |
||
1581 | * Create regexp from datetime format |
||
1582 | * @param string $format |
||
1583 | * @return string Regular expression string |
||
1584 | */ |
||
1585 | 4 | public static function get_regular_expression($format) |
|
1586 | { |
||
1587 | 4 | $newFormat = ''; |
|
1588 | 4 | $regPositions = array(); |
|
1589 | 4 | $ignoreNextChar = false; |
|
1590 | 4 | $count = 1; |
|
1591 | 4 | foreach (str_split($format) as $char) { |
|
1592 | 4 | if (! $ignoreNextChar && isset(self::$format_to_regexp[$char])) { |
|
1593 | 4 | $newFormat .= '(' . self::$format_to_regexp[$char] . ')'; |
|
1594 | 4 | $regPositions[$char] = $count; |
|
1595 | 4 | $count ++; |
|
1596 | } else { |
||
1597 | 4 | $ignoreNextChar = false; |
|
1598 | 4 | $newFormat .= $char; |
|
1599 | |||
1600 | } |
||
1601 | 4 | if ($char == "\\") { |
|
1602 | 4 | $ignoreNextChar = true; |
|
1603 | } |
||
1604 | } |
||
1605 | |||
1606 | 4 | return array('format' => $newFormat, 'positions' => $regPositions); |
|
1607 | } |
||
1608 | |||
1609 | // format - date expression ('' means now) for start and end of the range |
||
1610 | protected $date_expressions = array( |
||
1611 | 'yesterday' => array("-1 day", "-1 day"), |
||
1612 | 'today' => array("", ""), |
||
1613 | 'tomorrow' => array("+1 day", "+1 day"), |
||
1614 | 'last_7_days' => array("-6 days", ""), |
||
1615 | 'next_7_days' => array("", "+6 days"), |
||
1616 | 'last_30_days' => array("-29 days", ""), |
||
1617 | 'next_30_days' => array("", "+29 days"), |
||
1618 | ); |
||
1619 | |||
1620 | /** |
||
1621 | * Parse date template |
||
1622 | * @internal |
||
1623 | * @param string $template Date expression |
||
1624 | * @param bool $daystart Do we want start or end of the day? |
||
1625 | * @param User $user |
||
1626 | * @param bool $adjustForTimezone |
||
1627 | * @return SugarDateTime |
||
1628 | */ |
||
1629 | protected function parseFromTemplate($template, $daystart, User $user = null, $adjustForTimezone = true) |
||
1630 | { |
||
1631 | $rawTime = $this->getNow(); |
||
1632 | $now = $adjustForTimezone?$this->tzUser($rawTime, $user):$rawTime; |
||
1633 | if(!empty($template)) { |
||
1634 | $now->modify($template); |
||
1635 | } |
||
1636 | if($daystart) { |
||
1637 | return $now->get_day_begin(); |
||
1638 | } else { |
||
1639 | return $now->get_day_end(); |
||
1640 | } |
||
1641 | } |
||
1642 | |||
1643 | /** |
||
1644 | * Get month-long range mdiff months from now |
||
1645 | * @internal |
||
1646 | * @param int $mdiff |
||
1647 | * @param User $user |
||
1648 | * @param bool $adjustForTimezone |
||
1649 | * @return array |
||
1650 | */ |
||
1651 | protected function diffMon($mdiff, User $user = null, $adjustForTimezone = true) |
||
1652 | { |
||
1653 | $rawTime = $this->getNow(); |
||
1654 | $now = $adjustForTimezone?$this->tzUser($rawTime, $user):$rawTime; |
||
1655 | $now->setDate($now->year, $now->month+$mdiff, 1); |
||
1656 | $start = $now->get_day_begin(); |
||
1657 | $end = $now->setDate($now->year, $now->month, $now->days_in_month)->setTime(23, 59, 59); |
||
1658 | return array($start, $end); |
||
1659 | } |
||
1660 | |||
1661 | /** |
||
1662 | * Get year-long range ydiff years from now |
||
1663 | * @internal |
||
1664 | * @param int $ydiff |
||
1665 | * @param User $user |
||
1666 | * @param bool $adjustForTimezone |
||
1667 | * @return array |
||
1668 | */ |
||
1669 | protected function diffYear($ydiff, User $user = null, $adjustForTimezone = true) |
||
1670 | { |
||
1671 | $rawTime = $this->getNow(); |
||
1672 | $now = $adjustForTimezone?$this->tzUser($rawTime, $user):$rawTime; |
||
1673 | $now->setDate($now->year+$ydiff, 1, 1); |
||
1674 | $start = $now->get_day_begin(); |
||
1675 | $end = $now->setDate($now->year, 12, 31)->setTime(23, 59, 59); |
||
1676 | return array($start, $end); |
||
1677 | } |
||
1678 | |||
1679 | /** |
||
1680 | * Parse date range expression |
||
1681 | * Returns beginning and end of the range as a date |
||
1682 | * @param string $range |
||
1683 | * @param User $user |
||
1684 | * @param bool $adjustForTimezone Do we need to adjust for timezone? |
||
1685 | * @return array of two Date objects, start & end |
||
1686 | */ |
||
1687 | public function parseDateRange($range, User $user = null, $adjustForTimezone = true) |
||
1688 | { |
||
1689 | if(isset($this->date_expressions[$range])) { |
||
1690 | return array($this->parseFromTemplate($this->date_expressions[$range][0], true, $user, $adjustForTimezone), |
||
1691 | $this->parseFromTemplate($this->date_expressions[$range][1], false, $user, $adjustForTimezone) |
||
1692 | ); |
||
1693 | } |
||
1694 | switch($range) { |
||
1695 | case 'next_month': |
||
1696 | return $this->diffMon(1, $user, $adjustForTimezone); |
||
1697 | case 'last_month': |
||
1698 | return $this->diffMon(-1, $user, $adjustForTimezone); |
||
1699 | case 'this_month': |
||
1700 | return $this->diffMon(0, $user, $adjustForTimezone); |
||
1701 | case 'last_year': |
||
1702 | return $this->diffYear(-1, $user, $adjustForTimezone); |
||
1703 | case 'this_year': |
||
1704 | return $this->diffYear(0, $user, $adjustForTimezone); |
||
1705 | case 'next_year': |
||
1706 | return $this->diffYear(1, $user, $adjustForTimezone); |
||
1707 | default: |
||
1708 | return null; |
||
1709 | } |
||
1710 | } |
||
1711 | |||
1712 | /********************* OLD functions, should not be used publicly anymore ****************/ |
||
1713 | /** |
||
1714 | * Merge time without am/pm with am/pm string |
||
1715 | * @TODO find better way to do this! |
||
1716 | * @deprecated for public use |
||
1717 | * @param string $date |
||
1718 | * @param string $format User time format |
||
1719 | * @param string $mer |
||
1720 | * @return string |
||
1721 | */ |
||
1722 | function merge_time_meridiem($date, $format, $mer) |
||
1723 | { |
||
1724 | $date = trim($date); |
||
1725 | if (empty($date)) { |
||
1726 | return $date; |
||
1727 | } |
||
1728 | $fakeMerFormat = str_replace(array('a', 'A'), array('@~@', '@~@'), $format); |
||
1729 | $noMerFormat = trim(str_replace(array('a', 'A'), array('', ''), $format)); |
||
1730 | $newDate = $this->swap_formats($date, $noMerFormat, $fakeMerFormat); |
||
1731 | return str_replace('@~@', $mer, $newDate); |
||
1732 | } |
||
1733 | |||
1734 | /** |
||
1735 | * @deprecated for public use |
||
1736 | * Convert date from one format to another |
||
1737 | * |
||
1738 | * @param string $date |
||
1739 | * @param string $from |
||
1740 | * @param string $to |
||
1741 | * @return string |
||
1742 | */ |
||
1743 | public function swap_formats($date, $from, $to) |
||
1744 | { |
||
1745 | return $this->_convert($date, $from, self::$gmtTimezone, $to, self::$gmtTimezone); |
||
1746 | } |
||
1747 | |||
1748 | /** |
||
1749 | * @deprecated for public use |
||
1750 | * handles offset values for Timezones and DST |
||
1751 | * @param $date string date/time formatted in user's selected format |
||
1752 | * @param $format string destination format value as passed to PHP's date() funtion |
||
1753 | * @param $to boolean |
||
1754 | * @param $user object user object from which Timezone and DST |
||
1755 | * @param $usetimezone string timezone name |
||
1756 | * values will be derived |
||
1757 | * @return string date formatted and adjusted for TZ and DST |
||
1758 | */ |
||
1759 | 2 | function handle_offset($date, $format, $to = true, $user = null, $usetimezone = null) |
|
1760 | { |
||
1761 | 2 | $tz = empty($usetimezone)?$this->_getUserTZ($user):new DateTimeZone($usetimezone); |
|
1762 | 2 | $dateobj = new SugarDateTime($date, $to? self::$gmtTimezone : $tz); |
|
1763 | 2 | $dateobj->setTimezone($to ? $tz: self::$gmtTimezone); |
|
1764 | 2 | return $dateobj->format($format); |
|
1765 | // return $this->_convert($date, $format, $to ? self::$gmtTimezone : $tz, $format, $to ? $tz : self::$gmtTimezone); |
||
1766 | } |
||
1767 | |||
1768 | /** |
||
1769 | * @deprecated for public use |
||
1770 | * Get current GMT datetime in DB format |
||
1771 | * @return string |
||
1772 | */ |
||
1773 | function get_gmt_db_datetime() |
||
1774 | { |
||
1775 | return $this->nowDb(); |
||
1776 | } |
||
1777 | |||
1778 | /** |
||
1779 | * @deprecated for public use |
||
1780 | * Get current GMT date in DB format |
||
1781 | * @return string |
||
1782 | */ |
||
1783 | function get_gmt_db_date() |
||
1784 | { |
||
1785 | return $this->nowDbDate(); |
||
1786 | } |
||
1787 | |||
1788 | /** |
||
1789 | * @deprecated for public use |
||
1790 | * this method will take an input $date variable (expecting Y-m-d format) |
||
1791 | * and get the GMT equivalent - with an hour-level granularity : |
||
1792 | * return the max value of a given locale's |
||
1793 | * date+time in GMT metrics (i.e., if in PDT, "2005-01-01 23:59:59" would be |
||
1794 | * "2005-01-02 06:59:59" in GMT metrics) |
||
1795 | * @param $date |
||
1796 | * @return array |
||
1797 | */ |
||
1798 | function handleOffsetMax($date) |
||
1799 | { |
||
1800 | $min = new DateTime($date, $this->_getUserTZ()); |
||
1801 | $min->setTime(0, 0); |
||
1802 | $max = new DateTime($date, $this->_getUserTZ()); |
||
1803 | $max->setTime(23, 59, 59); |
||
1804 | |||
1805 | $min->setTimezone(self::$gmtTimezone); |
||
1806 | $max->setTimezone(self::$gmtTimezone); |
||
1807 | |||
1808 | $gmtDateTime['date'] = $this->asDbDate($max, false); |
||
1809 | $gmtDateTime['time'] = $this->asDbDate($max, false); |
||
1810 | $gmtDateTime['min'] = $this->asDb($min); |
||
1811 | $gmtDateTime['max'] = $this->asDb($max); |
||
1812 | |||
1813 | return $gmtDateTime; |
||
1814 | } |
||
1815 | |||
1816 | /** |
||
1817 | * @deprecated for public use |
||
1818 | * this returns the adjustment for a user against the server time |
||
1819 | * |
||
1820 | * @return integer number of minutes to adjust a time by to get the appropriate time for the user |
||
1821 | */ |
||
1822 | public function adjustmentForUserTimeZone() |
||
1823 | { |
||
1824 | $tz = $this->_getUserTZ(); |
||
1825 | $server_tz = new DateTimeZone(date_default_timezone_get()); |
||
1826 | if ($tz && $server_tz) { |
||
1827 | return ($server_tz->getOffset($this->now) - $tz->getOffset($this->now)) / 60; |
||
1828 | } |
||
1829 | return 0; |
||
1830 | } |
||
1831 | |||
1832 | /** |
||
1833 | * @deprecated for public use |
||
1834 | * assumes that olddatetime is in Y-m-d H:i:s format |
||
1835 | * @param $olddatetime |
||
1836 | * @return string |
||
1837 | */ |
||
1838 | function convert_to_gmt_datetime($olddatetime) |
||
1839 | { |
||
1840 | if (! empty($olddatetime)) { |
||
1841 | return date('Y-m-d H:i:s', strtotime($olddatetime) - date('Z')); |
||
1842 | } |
||
1843 | return ''; |
||
1844 | } |
||
1845 | |||
1846 | /** |
||
1847 | * @deprecated for public use |
||
1848 | * get user timezone info |
||
1849 | * @param User $user |
||
1850 | * @return array |
||
1851 | */ |
||
1852 | public function getUserTimeZone(User $user = null) |
||
1853 | { |
||
1854 | $tz = $this->_getUserTZ($user); |
||
1855 | return array("gmtOffset" => $tz->getOffset($this->now) / 60); |
||
1856 | } |
||
1857 | |||
1858 | /** |
||
1859 | * @deprecated for public use |
||
1860 | * get timezone start & end |
||
1861 | * @param $year |
||
1862 | * @param string $zone |
||
1863 | * @return array |
||
1864 | */ |
||
1865 | public function getDSTRange($year, $zone = null) |
||
1866 | { |
||
1867 | if(!empty($zone)) { |
||
1868 | $tz = timezone_open($zone); |
||
1869 | } |
||
1870 | if(empty($tz)) { |
||
1871 | $tz = $this->_getUserTZ(); |
||
1872 | } |
||
1873 | |||
1874 | $year_date = SugarDateTime::createFromFormat("Y", $year, self::$gmtTimezone); |
||
1875 | $year_end = clone $year_date; |
||
1876 | $year_end->setDate((int) $year, 12, 31); |
||
1877 | $year_end->setTime(23, 59, 59); |
||
1878 | $year_date->setDate((int) $year, 1, 1); |
||
1879 | $year_date->setTime(0, 0, 0); |
||
1880 | $result = array(); |
||
1881 | $transitions = $tz->getTransitions($year_date->ts, $year_end->ts); |
||
1882 | $idx = 0; |
||
1883 | if(version_compare(PHP_VERSION, '5.3.0', '<')) { |
||
1884 | // <5.3.0 ignores parameters, advance manually to current year |
||
1885 | $start_ts = $year_date->ts; |
||
1886 | while(isset($transitions[$idx]) && $transitions[$idx]["ts"] < $start_ts) $idx++; |
||
1887 | } |
||
1888 | // get DST start |
||
1889 | while (isset($transitions[$idx]) && !$transitions[$idx]["isdst"]) $idx++; |
||
1890 | if(isset($transitions[$idx])) { |
||
1891 | $result["start"] = $this->fromTimestamp($transitions[$idx]["ts"])->asDb(); |
||
1892 | } |
||
1893 | // get DST end |
||
1894 | while (isset($transitions[$idx]) && $transitions[$idx]["isdst"]) $idx++; |
||
1895 | if(isset($transitions[$idx])) { |
||
1896 | $result["end"] = $this->fromTimestamp($transitions[$idx]["ts"])->asDb(); |
||
1897 | } |
||
1898 | return $result; |
||
1899 | } |
||
1900 | |||
1901 | /****************** GUI stuff that really shouldn't be here, will be moved ************/ |
||
1902 | /** |
||
1903 | * Get Javascript variables setup for user date format validation |
||
1904 | * @deprecated moved to SugarView |
||
1905 | * @return string JS code |
||
1906 | */ |
||
1907 | function get_javascript_validation() |
||
1908 | { |
||
1909 | return SugarView::getJavascriptValidation(); |
||
1910 | } |
||
1911 | |||
1912 | /** |
||
1913 | * AMPMMenu |
||
1914 | * This method renders a SELECT HTML form element based on the |
||
1915 | * user's time format preferences, with give date's value highlighted. |
||
1916 | * |
||
1917 | * If user's prefs have no AM/PM string, returns empty string. |
||
1918 | * |
||
1919 | * @todo There is hardcoded HTML in here that does not allow for localization |
||
1920 | * of the AM/PM am/pm Strings in this drop down menu. Also, perhaps |
||
1921 | * change to the substr_count function calls to strpos |
||
1922 | * TODO: Remove after full switch to fields |
||
1923 | * @deprecated |
||
1924 | * @param string $prefix Prefix for SELECT |
||
1925 | * @param string $date Date in display format |
||
1926 | * @param string $attrs Additional attributes for SELECT |
||
1927 | * @return string SELECT HTML |
||
1928 | */ |
||
1929 | 4 | function AMPMMenu($prefix, $date, $attrs = '') |
|
1930 | { |
||
1931 | 4 | $tf = $this->get_time_format(); |
|
1932 | 4 | $am = strpbrk($tf, 'aA'); |
|
1933 | 4 | if ($am == false) { |
|
1934 | 4 | return ''; |
|
1935 | } |
||
1936 | $selected = array("am" => "", "pm" => "", "AM" => "", "PM" => ""); |
||
1937 | if (preg_match('/([ap]m)/i', $date, $match)) { |
||
1938 | $selected[$match[1]] = " selected"; |
||
1939 | } |
||
1940 | |||
1941 | $menu = "<select name='" . $prefix . "meridiem' " . $attrs . ">"; |
||
1942 | if ($am{0} == 'a') { |
||
1943 | $menu .= "<option value='am'{$selected["am"]}>am"; |
||
1944 | $menu .= "<option value='pm'{$selected["pm"]}>pm"; |
||
1945 | } else { |
||
1946 | $menu .= "<option value='AM'{$selected["AM"]}>AM"; |
||
1947 | $menu .= "<option value='PM'{$selected["PM"]}>PM"; |
||
1948 | } |
||
1949 | |||
1950 | return $menu . '</select>'; |
||
1951 | } |
||
1952 | |||
1953 | /** |
||
1954 | * Get user format in JS form |
||
1955 | * TODO: Remove after full switch to fields |
||
1956 | * @return string |
||
1957 | */ |
||
1958 | 9 | function get_user_date_format() |
|
1959 | { |
||
1960 | 9 | return str_replace(array('Y', 'm', 'd'), array('yyyy', 'mm', 'dd'), $this->get_date_format()); |
|
1961 | } |
||
1962 | |||
1963 | /** |
||
1964 | * Get user time format example |
||
1965 | * TODO: Remove after full switch to fields |
||
1966 | * @deprecated |
||
1967 | * @return string |
||
1968 | */ |
||
1969 | 9 | function get_user_time_format() |
|
1970 | { |
||
1971 | 9 | global $sugar_config; |
|
1972 | 9 | $time_pref = $this->get_time_format(); |
|
1973 | |||
1974 | 9 | if (! empty($time_pref) && ! empty($sugar_config['time_formats'][$time_pref])) { |
|
1975 | 9 | return $sugar_config['time_formats'][$time_pref]; |
|
1976 | } |
||
1977 | |||
1978 | return '23:00'; //default |
||
1979 | } |
||
1980 | |||
1981 | } |
||
1982 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.
Either this assignment is in error or an instanceof check should be added for that assignment.