]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/include/TimeDateTest.php
Release 6.5.10
[Github/sugarcrm.git] / tests / include / TimeDateTest.php
1 <?php
2 /*********************************************************************************
3  * SugarCRM Community Edition is a customer relationship management program developed by
4  * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
5  * 
6  * This program is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License version 3 as published by the
8  * Free Software Foundation with the addition of the following permission added
9  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12  * 
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
16  * details.
17  * 
18  * You should have received a copy of the GNU Affero General Public License along with
19  * this program; if not, see http://www.gnu.org/licenses or write to the Free
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301 USA.
22  * 
23  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
25  * 
26  * The interactive user interfaces in modified source and object code versions
27  * of this program must display Appropriate Legal Notices, as required under
28  * Section 5 of the GNU Affero General Public License version 3.
29  * 
30  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31  * these Appropriate Legal Notices must retain the display of the "Powered by
32  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33  * technical reasons, the Appropriate Legal Notices must display the words
34  * "Powered by SugarCRM".
35  ********************************************************************************/
36
37
38 require_once 'include/TimeDate.php';
39
40 class TimeDateTest extends Sugar_PHPUnit_Framework_TestCase
41 {
42         /**
43          * @var TimeDate
44          */
45         protected $time_date;
46
47         const DEFAULT_TIME_FORMAT = 'H:i';
48
49         public static function setUpBeforeClass()
50         {
51             unset($GLOBALS['disable_date_format']);
52         $GLOBALS['current_user'] = SugarTestUserUtilities::createAnonymousUser();
53         }
54
55         public function setUp()
56         {
57                 $this->time_date = new TimeDate();
58                 unset($GLOBALS['disable_date_format']);
59                 $this->_noUserCache();
60         }
61
62         public function tearDown()
63         {
64             SugarDateTime::$use_php_parser = true;
65             SugarDateTime::$use_strptime = true;
66         }
67
68         public static function tearDownAfterClass()
69         {
70             SugarTestUserUtilities::removeAllCreatedAnonymousUsers();
71         unset($GLOBALS['current_user']);
72         }
73
74         public function dateTestSet()
75         {
76             return array(
77                 array("db" => '2005-10-25 07:00:00', "df" => 'd-m-Y', 'tf' => '',               'tz' => 'America/Los_Angeles',          "display" => '25-10-2005',                      "dbdate" => "2005-10-25 00:00:00"),
78                 // add times
79                 array("db" => '2005-10-26 06:42:00', "df" => 'd-m-Y', "tf" => 'h.iA',   'tz' => 'America/Los_Angeles',          "display" => '25-10-2005 11.42PM',      "dbdate" => "2005-10-25 23:42:00"),
80                 // GMT+0 timezone
81                 array("db" => '2005-11-25 00:00:00', "df" => 'd-m-Y', 'tf' => '',               'tz' => 'Europe/London',                        "display" => '25-11-2005',                      "dbdate" => "2005-11-25 00:00:00"),
82                 // GMT+1
83                 array("db" => '2005-11-24 23:00:00', "df" => 'd;m;Y', 'tf' => '',               'tz' => 'Europe/Oslo',                          "display" => '25;11;2005',                      "dbdate" => "2005-11-25 00:00:00"),
84                 // DST in effect
85                 array("db" => '2005-10-24 23:00:00', "df" => 'd-m-Y', 'tf' => '',               'tz' => 'Europe/London',                        "display" => '25-10-2005',                      "dbdate" => "2005-10-25 00:00:00"),
86                 // different format
87                 array("db" => '1997-10-25 07:00:00', "df" => 'Y-m-d', 'tf' => '',               'tz' => 'America/Los_Angeles',          "display" => '1997-10-25',                      "dbdate" => "1997-10-25 00:00:00"),
88                 array("db" => '1997-01-25 00:00:00', "df" => 'm-d-Y', 'tf' => '',               'tz' => 'Europe/London',                        "display" => '01-25-1997',                      "dbdate" => "1997-01-25 00:00:00"),
89                 // with times
90                 array("db" => '2005-10-25 10:42:24', "df" => 'd/m/Y', "tf" => "H:i:s",  'tz' => 'America/Los_Angeles',          "display" => '25/10/2005 03:42:24', "dbdate" => "2005-10-25 03:42:24"),
91                 array("db" => '2005-10-25 02:42:24', "df" => 'd/m/Y', "tf" => "H:i:s",  'tz' => 'Europe/London',                        "display" => '25/10/2005 03:42:24', "dbdate" => "2005-10-25 03:42:24"),
92                 array("db" => '2005-10-25 01:42:24', "df" => 'd/m/Y', "tf" => "H:i:s",  'tz' => 'Asia/Jerusalem',                       "display" => '25/10/2005 03:42:24', "dbdate" => "2005-10-25 03:42:24"),
93                 // FAIL! FIXME: same format leads to no TZ conversion
94                 array("db" => '2005-10-25 10:42:24', "df" => 'Y-m-d', "tf" => "H:i:s",  'tz' => 'America/Los_Angeles',          "display" => '2005-10-25 03:42:24', "dbdate" => "2005-10-25 03:42:24"),
95                 // short times
96                 array("db" => '2005-10-25 10:42:00', "df" => 'd/m/Y', "tf" => "H:i",    'tz' => 'America/Los_Angeles',          "display" => '25/10/2005 03:42',        "dbdate" => "2005-10-25 03:42:00"),
97                 array("db" => '2005-10-25 22:00:00', "df" => 'd/m/Y', "tf" => "ha",             'tz' => 'America/Los_Angeles',          "display" => '25/10/2005 03pm',         "dbdate" => "2005-10-25 15:00:00"),
98                 array("db" => '2005-10-25 10:00:00', "df" => 'd/m/Y', "tf" => "h",              'tz' => 'America/Los_Angeles',          "display" => '25/10/2005 03',           "dbdate" => "2005-10-25 03:00:00"),
99                 array("db" => '2005-10-25 20:00:00', "df" => 'd/m/Y', "tf" => "H",              'tz' => 'America/Los_Angeles',          "display" => '25/10/2005 13',           "dbdate" => "2005-10-25 13:00:00"),
100                 array("db" => '2005-10-25 07:00:00', "df" => 'd/m/Y', "tf" => "ha",             'tz' => 'America/Los_Angeles',          "display" => '25/10/2005 12am',         "dbdate" => "2005-10-25 00:00:00"),
101                 array("db" => '2005-10-25 19:00:00', "df" => 'd/m/Y', "tf" => "ha",             'tz' => 'America/Los_Angeles',          "display" => '25/10/2005 12pm',         "dbdate" => "2005-10-25 12:00:00"),
102                 );
103         }
104
105         public function timetestSet()
106         {
107             return array(
108                 // full time
109                 array("db" => "11:45:00", "tf" => '', "display" => "11:45"),
110                 array("db" => "05:17:28", "tf" => "H.i.s", "display" => "05.17.28"),
111                 // short ones
112                 array("db" => "17:34:00", "tf" => "H:i", "display" => "17:34"),
113                 array("db" => "11:42:00", "tf" => "h.iA", "display" => "11.42AM"),
114                 array("db" => "15:00:00", "tf" => "ha", "display" => "03pm"),
115                 array("db" => "15:00:00", "tf" => "H", "display" => "15"),
116                 // FIXME: is this a valid format? it doesn't allow roundtrip
117                 array("db" => "03:00:00", "tf" => "h", "display" => "03"),
118                 // weirdo
119                 array("db" => "16:42:34", "tf" => "s:i:H", "display" => "34:42:16"),
120                 );
121         }
122
123         protected function _noUserCache()
124         {
125                 $this->time_date->allow_cache = false;
126         sugar_cache_clear($this->time_date->get_date_time_format_cache_key(null));
127         }
128
129         protected function _setPrefs($datef, $timef, $tz)
130         {
131         $GLOBALS['current_user']->setPreference('datef', $datef);
132         $GLOBALS['current_user']->setPreference('timef', $timef);
133         $GLOBALS['current_user']->setPreference('timezone', $tz);
134         // new object to avoid TZ caching
135         $this->time_date = new TimeDate();
136         $this->_noUserCache();
137         }
138
139         protected function _dateOnly($datetime)
140         {
141                 // FIXME: assumes dates have no spaces
142                 $dt = explode(' ', $datetime);
143                 return $dt[0];
144         }
145
146         protected function _timeOnly($datetime)
147         {
148                 // FIXME: assumes dates have no spaces
149                 $dt = explode(' ', $datetime);
150                 if(count($dt) > 1) {
151                         return $dt[1];
152                 }
153                 return $datetime;
154         }
155
156         /**
157          * test conversion from local datetime to DB datetime
158          * @dataProvider dateTestSet
159          */
160         public function testToDbFormats($db, $df, $tf, $tz,  $display, $dbdate)
161         {
162                 $tf = empty($tf) ? self::DEFAULT_TIME_FORMAT : $tf;
163                 $this->_setPrefs($df, $tf, $tz);
164                 $this->assertEquals($db,
165         $this->time_date->to_db($display),
166                 "Broken conversion for '$df $tf' with date '$display' and TZ $tz");
167         }
168
169         /**
170          * test conversion from full local datetime to DB date
171          * @dataProvider dateTestSet
172          */
173         public function testToDbDateFormatsWithOffset($db, $df, $tf, $tz,  $display, $dbdate)
174         {
175                 $tf = empty($tf) ? self::DEFAULT_TIME_FORMAT : $tf;
176                 $this->_setPrefs($df, $tf, $tz);
177                 $this->assertEquals(
178                         $this->_dateOnly($db),
179                         $this->time_date->to_db_date($display, true),
180                         "Broken conversion for '{$df} $tf' with date '{$display}' and TZ {$tz}");
181         }
182
183         /**
184          * test conversion from local date to DB date, no TZ handling
185          * @dataProvider dateTestSet
186          */
187         public function testToDbDateFormatsNoOffset($db, $df, $tf, $tz,  $display, $dbdate)
188         {
189                 $tf = empty($tf) ? self::DEFAULT_TIME_FORMAT : $tf;
190             $this->_setPrefs($df, $tf, $tz);
191                 $this->assertEquals(
192                         $this->_dateOnly($dbdate),
193                         $this->time_date->to_db_date($this->_dateOnly($display), false),
194                         "Broken conversion for '{$df} $tf' with date '{$display}' and TZ {$tz}");
195         }
196
197         /**
198          * test conversion from full local datetime to DB time
199          * @dataProvider dateTestSet
200          */
201         public function testToDbTimeFormatsWithTz($db, $df, $tf, $tz,  $display, $dbdate)
202         {
203                 $tf = empty($tf) ? self::DEFAULT_TIME_FORMAT : $tf;
204                 $this->_setPrefs($df, $tf, $tz);
205                 if(strpos($display, ' ') === false) {
206                     $display = $this->time_date->expandDate($display, "$df $tf");
207                 }
208                 $this->assertEquals(
209                         $this->_timeOnly($db),
210                         $this->time_date->to_db_time($display, true),
211                         "Broken conversion for '{$df} $tf' with date '{$display}' and TZ {$tz}");
212         }
213
214         /**
215          * test conversion from local time to DB time, no TZ handling
216          * @dataProvider timeTestSet
217          */
218         public function testToDbTimeFormatsNoTz($db, $tf, $display)
219         {
220                 $tf = empty($tf) ? self::DEFAULT_TIME_FORMAT : $tf;
221                 $this->_setPrefs('Y-m-d', $tf, '');
222                 $this->assertEquals(
223                         $db,
224                         $this->time_date->to_db_time($display, false),
225                         "Broken conversion for '$tf' with date '{$display}'");
226         }
227
228         /**
229          * test conversion from local date+time to DB date+time, no TZ handling
230          * @dataProvider dateTestSet
231          */
232         public function testToDbDateTimeFormats($db, $df, $tf, $tz,  $display, $dbdate)
233         {
234                 $tf = empty($tf) ? self::DEFAULT_TIME_FORMAT : $tf;
235                 $this->_setPrefs($df, $tf, $tz);
236                 $dt = explode(' ', $display);
237                 if(count($dt) > 1) {
238                         list($date, $time) = $dt;
239                 } else {
240                         $date = $dt[0];
241                         $z = new DateTime("@0", new DateTimeZone("GMT"));
242                         $time = $z->format($tf);
243                 }
244                 $this->assertEquals(
245                         explode(' ',$dbdate),
246                         $this->time_date->to_db_date_time($date, $time),
247                         "Broken conversion for '{$df} $tf' with date '{$display}' and TZ {$tz}");
248         }
249
250
251         /**
252          * test conversion from DB date+time to local date+time with TZ handling
253          * @dataProvider dateTestSet
254          */
255         public function testToDisplayDateTimeFormats($db, $df, $tf, $tz,  $display, $dbdate)
256         {
257                 $this->_setPrefs($df, $tf, $tz);
258                 $result = $this->time_date->to_display_date_time($db, true, true, $GLOBALS['current_user']);
259                 if(empty($tf)) {
260                         $result = $this->_dateOnly($result);
261                 }
262                 $this->assertEquals(
263                         $display,
264                         $result,
265                         "Broken conversion for '$df' with date '{$db}' and TZ {$tz}");
266         }
267
268         /**
269          * test conversion from DB date+time to local date+time without TZ handling
270          * @dataProvider dateTestSet
271          */
272         public function testToDisplayFormatsNoTz($db, $df, $tf, $tz,  $display, $dbdate)
273         {
274             $this->_setPrefs($df, $tf, $tz);
275             if(!empty($tf)) {
276                 $df .= " $tf";
277             }
278                 $result = $this->time_date->to_display($dbdate, $this->time_date->get_db_date_time_format(), $df);
279                 if(empty($tf)) {
280                         $result = $this->_dateOnly($result);
281                 }
282                 $this->assertEquals(
283                         $display,
284                         $result,
285                         "Broken conversion for '$df' with date '{$db}' and TZ {$tz}");
286         }
287
288         /**
289          * test conversion from DB time to local time without TZ conversion
290          * @dataProvider timeTestSet
291          */
292         public function testToDisplayTimeFormatsNoTZ($db, $tf, $display)
293         {
294                 if(empty($tf)) return;
295                 $this->_setPrefs('Y-m-d', $tf, '');
296                 $this->assertEquals(
297                         $this->_timeOnly($display),
298                         $this->time_date->to_display_time($db, true, false),
299                         "Broken conversion for '$tf' with date '{$db}'");
300         }
301
302         /**
303          * test conversion from DB time to local time with TZ conversion
304          * @dataProvider dateTestSet
305          */
306         public function testToDisplayTimeFormatsWithTZ($db, $df, $tf, $tz,  $display, $dbdate)
307         {
308                 if(empty($tf)) return;
309                 $this->_setPrefs($df, $tf, $tz);
310                 $result = $this->time_date->to_display_time($db, true, true);
311                 $result = $this->_timeOnly($result);
312                 $this->assertEquals(
313                         $this->_timeOnly($display),
314                         $result,
315                         "Broken conversion for '{$tf}' with date '{$db}' and TZ {$tz}");
316         }
317
318
319         /**
320          * test conversion from DB date to local date without TZ handling
321          * @dataProvider dateTestSet
322          */
323         public function testToDisplayDateFormatsNoTz($db, $df, $tf, $tz,  $display, $dbdate)
324         {
325                 $this->_setPrefs($df, $tf, $tz);
326                 $result = $this->time_date->to_display_date($this->_dateOnly($dbdate), false);
327                 $this->assertEquals(
328                         $this->_dateOnly($display),
329                         $this->_dateOnly($result),
330                         "Broken conversion for '{$df}' with date '{$dbdate}' and TZ {$tz}");
331         }
332
333         /**
334          * test conversion from DB date to local date with TZ handling
335          * @dataProvider dateTestSet
336          */
337         public function testToDisplayDateFormatsWithTz($db, $df, $tf, $tz,  $display, $dbdate)
338         {
339                 $this->_setPrefs($df, $tf, $tz);
340                 $result = $this->time_date->to_display_date($db, true);
341                 $this->assertEquals(
342                         $this->_dateOnly($display),
343                         $this->_dateOnly($result),
344                         "Broken conversion for '{$df}' with date '{$dbdate}' and TZ {$tz}");
345         }
346
347         public function midnightDataSet()
348         {
349             return array(
350                         array("tf" => "H:i", "time" => "00:00"),
351                         array("tf" => "H:i:s", "time" => "00:00:00"),
352                         array("tf" => "h:i", "time" => "12:00"),
353                         array("tf" => "h:i:s", "time" => "12:00:00"),
354                         array("tf" => "h`iA", "time" => "12`00AM"),
355                         array("tf" => "h`i`sa", "time" => "12`00`00am"),
356                 );
357         }
358
359         /**
360          * test midnight formatting
361          * @dataProvider midnightDataSet
362          */
363         public function testGetMidnight($tf, $time)
364         {
365                 if(!is_callable(array($this->time_date, "get_default_midnight"))) {
366                         $this->markTestSkipped("Method is no longer public");
367                 }
368                 $this->_setPrefs('', $tf, "America/Los_Angeles");
369                 $this->assertEquals($time,  $this->time_date->get_default_midnight(true),
370                         "Bad midnight value for $time format $tf");
371         }
372
373         public function testSwapFormatsWithTheSameDateFormat()
374         {
375                 $original_date = '2005-12-25';
376                 $original_format = 'Y-m-d';
377                 $new_format = $original_format;
378                 $expected_new_date = $original_date;
379
380                 $new_date = $this->time_date->swap_formats($original_date,
381                         $original_format, $new_format);
382
383                 $this->assertEquals($expected_new_date, $new_date);
384         }
385
386         public function testSwapFormatsFromMdyFormatToDmyFormat()
387         {
388                 $original_date = '12-25-2005';
389                 $original_format = 'm-d-Y';
390                 $new_format = 'd-m-Y';
391                 $expected_new_date = '25-12-2005';
392
393                 $new_date = $this->time_date->swap_formats($original_date,
394                         $original_format, $new_format);
395
396                 $this->assertEquals($expected_new_date, $new_date,
397                         "Convert from $original_format to $new_format failed.");
398         }
399
400         public function testSwapFormatsWithTheSameDatetimeFormat()
401         {
402                 $original_date = '2005-12-25 12:55:35';
403                 $original_format = 'Y-m-d H:i:s';
404                 $new_format = $original_format;
405                 $expected_new_date = $original_date;
406
407                 $new_date = $this->time_date->swap_formats($original_date,
408                         $original_format, $new_format);
409
410                 $this->assertEquals($expected_new_date, $new_date,
411                         'Same datetime format not returned.');
412         }
413
414         public function testSwapFormatsFromYmdhiFormatToYmdhisFormat()
415         {
416                 $original_date = '2005-12-25 12:55';
417                 $original_format = 'Y-m-d H:i';
418                 $new_format = 'Y-m-d H:i:s';
419                 $expected_new_date = '2005-12-25 12:55:00';
420
421                 $new_date = $this->time_date->swap_formats($original_date,
422                         $original_format, $new_format);
423
424                 $this->assertEquals($expected_new_date, $new_date);
425         }
426
427         public function testSwapFormatsFromYmdhiFormatToYmdhiaFormat()
428         {
429                 $original = '2005-12-25 13:55';
430                 $original_format = 'Y-m-d H:i';
431                 $new_format = 'Y-m-d h:ia';
432                 $expected = '2005-12-25 01:55pm';
433
434                 $new = $this->time_date->swap_formats($original,
435                         $original_format, $new_format);
436
437                 $this->assertEquals($expected, $new);
438         }
439
440         public function testAllDateFormatSwappingCombinations()
441         {
442                 $orig_formats_and_dates = array(
443                         'Y-m-d' => '2006-12-23',
444                         'm-d-Y' => '12-23-2006',
445                         'd-m-Y' => '23-12-2006',
446                         'Y/m/d' => '2006/12/23',
447                         'm/d/Y' => '12/23/2006',
448                         'd/m/Y' => '23/12/2006');
449
450                 $new_formats_and_dates = $orig_formats_and_dates;
451
452                 foreach($orig_formats_and_dates as $orig_format => $orig_date)
453                 {
454                         foreach($new_formats_and_dates as $new_format => $expected_date)
455                         {
456                                 $new_date = $this->time_date->swap_formats($orig_date,
457                                         $orig_format, $new_format);
458
459                                 $this->assertEquals($expected_date, $new_date,
460                                         "Convert from $orig_format to $new_format failed.");
461
462                                 if($expected_date != $new_date)
463                                 {
464                                         return;
465                                 }
466                         }
467                 }
468         }
469
470     /**
471      * @ticket 17528
472      */
473         public function testSwapDatetimeFormatToDbFormat()
474         {
475                 $date = '10-25-2007 12:00am';
476                 $format = $this->time_date->get_date_time_format();
477                 $db_format = $this->time_date->get_db_date_time_format();
478
479                 $this->assertEquals(
480                         $this->time_date->swap_formats(
481                                 $date,
482                                 'm-d-Y h:ia',
483                                 $this->time_date->get_db_date_time_format()
484                         ),
485                         '2007-10-25 00:00:00'
486                 );
487         }
488
489         /**
490      * @ticket 17528
491      */
492         public function testTodbCanHandleDdmmyyyyFormats()
493         {
494                 $old_pattern = $GLOBALS['current_user']->getPreference('datef');
495                 $GLOBALS['current_user']->setPreference('datef','d-m-Y');
496                 $db_date_pattern = '/2007-10-25 [0-9]{2}:[0-9]{2}:[0-9]{2}/';
497                 $this->assertRegExp(
498                         $db_date_pattern,
499                         $this->time_date->to_db('25-10-2007')
500                 );
501
502                 $this->_noUserCache();
503                 $GLOBALS['current_user']->setPreference('datef','m-d-Y');
504                 $this->assertRegExp(
505                         $db_date_pattern,
506                         $this->time_date->to_db('10-25-2007')
507                 );
508                 $GLOBALS['current_user']->setPreference('datef',$old_pattern);
509         }
510
511         /**
512      * @ticket 17528
513      */
514         public function testTodbCanHandleMmddyyyyFormats()
515         {
516                 $old_date = $GLOBALS['current_user']->getPreference('datef');
517
518                 $GLOBALS['current_user']->setPreference('datef','m-d-Y');
519                 $db_date_pattern = '/2007-10-25 [0-9]{2}:[0-9]{2}:[0-9]{2}/';
520                 $this->assertRegExp(
521                         $db_date_pattern,
522                         $this->time_date->to_db('10-25-2007')
523                 );
524
525                 $GLOBALS['current_user']->setPreference('datef',$old_date);
526         }
527
528         /**
529      * @ticket 17528
530      */
531         public function testTodbdateCanHandleDdmmyyyyFormats()
532         {
533                 $old_date = $GLOBALS['current_user']->getPreference('datef');
534
535                 $GLOBALS['current_user']->setPreference('datef','d-m-Y');
536                 $this->assertEquals(
537                         $this->time_date->to_db_date('25-10-2007'),
538                         '2007-10-25'
539                 );
540
541                 $GLOBALS['current_user']->setPreference('datef',$old_date);
542         }
543
544         /**
545      * @ticket 17528
546      */
547         public function testTodbdateCanHandleMmddyyyyFormats()
548         {
549                 $old_date = $GLOBALS['current_user']->getPreference('datef');
550                 $GLOBALS['current_user']->setPreference('datef','m-d-Y');
551                 $this->assertEquals(
552                         '2007-10-25',
553                         $this->time_date->to_db_date('10-25-2007')
554                 );
555
556                 $GLOBALS['current_user']->setPreference('datef',$old_date);
557         }
558
559         public function testConvertMmddyyyyFormatToYyyymmdd()
560         {
561                 $this->assertEquals(
562                         '2007-11-02',
563                         $this->time_date->swap_formats(
564                                 '11-02-2007',
565                                 'm-d-Y',
566                                 'Y-m-d'
567                         )
568                 );
569         }
570
571         public function testGeneratingDefaultMidnight()
572         {
573                 if(!is_callable(array($this->time_date, "get_default_midnight"))) {
574                         $this->markTestSkipped("Method is no longer public");
575                 }
576                 $old_time = $GLOBALS['current_user']->getPreference('timef');
577
578                 $GLOBALS['current_user']->setPreference('timef','H:i:s');
579                 $this->assertEquals(
580                         '00:00:00',
581                         $this->time_date->get_default_midnight(true)
582                 );
583
584                 $GLOBALS['current_user']->setPreference('timef','h:ia');
585                 $this->assertEquals(
586                         '12:00am',
587                         $this->time_date->get_default_midnight(true)
588                 );
589
590                 $GLOBALS['current_user']->setPreference('timef',$old_time);
591         }
592
593         /**
594          * tests for check_matching_format
595          * @dataProvider dateTestSet
596          */
597         public function testCheckMatchingFormats($db, $df, $tf, $tz,  $display, $dbdate)
598         {
599         if(!empty($tf)) {
600             $df = $this->time_date->merge_date_time($df, $tf);
601         }
602                 $this->assertTrue($this->time_date->check_matching_format($display, $df),
603                                 "Broken match for '$df' with date '{$display}'");
604         }
605
606         public function badMatchTestSet()
607         {
608             return  array(
609                         array("format" => "Y-m-d", "date" => ""),
610                         array("format" => "Y-m-d", "date" => "blah-blah-blah"),
611                         array("format" => "Y-m-d", "date" => "1-2"),
612                         array("format" => "Y-m-d", "date" => "2007-10"),
613                         //FIXME: array("format" => "Y-m-d", "date" => "200-10-25"),
614                         array("format" => "Y-m-d", "date" => "2007-101-25"),
615                         array("format" => "Y-m-d", "date" => "2007-Oct-25"),
616                         //FIXME: array("format" => "Y-m-d", "date" => "2007-10-250"),
617                         array("format" => "d-m-Y", "date" => "2007-10-25"),
618                         array("format" => "d-m-Y", "date" => "10/25/2007"),
619                         //FIXME: array("format" => "Y-m-d", "date" => "here: 2007-20-25"),
620                         //FIXME: array("format" => "Y-m-d", "date" => "2007-20-25 here"),
621                 );
622         }
623
624         /**
625          * tests for check_matching_format
626          * @dataProvider badMatchTestSet
627          */
628         public function testCheckbadMatchingFormats($format, $date)
629         {
630                 // Some bad dates not detected by current code, it's too lenient
631                 $this->assertFalse($this->time_date->check_matching_format($date, $format),
632                         "Broken match for '$format' with date '$date'");
633         }
634
635         /**
636          * test fetching user settings
637          */
638         public function testGetUserSettings()
639         {
640                 $this->_setPrefs('d/m/Y', 'h:i:sA', "America/Lima");
641                 $this->assertEquals('dd/mm/yyyy', $this->time_date->get_user_date_format());
642                 //FIXME: $this->assertEquals('11:00:00PM', $this->time_date->get_user_time_format());
643                 $tz = $this->time_date->getUserTimeZone();
644                 $this->assertEquals(-300, $tz["gmtOffset"]);
645 //              $this->assertEquals(60, $tz["dstOffset"]);
646         }
647
648         /**
649          * test getting GMT dates
650          */
651         public function testGetGMT()
652         {
653                 if (is_windows() || !function_exists("strptime")) {
654             $this->markTestSkipped('Skipping on Windows, no strptime');
655         }
656         $gmt = $this->time_date->nowDb();
657                 $dt = strptime($gmt, "%Y-%m-%d %H:%M:%S");
658                 $this->assertEquals($dt['tm_year']+1900, gmdate("Y"));
659                 $this->assertEquals($dt['tm_mon']+1, gmdate("m"));
660                 $this->assertEquals($dt['tm_mday'], gmdate("d"));
661
662                 $gmt = $this->time_date->nowDb();
663                 $dt = strptime($gmt, "%Y-%m-%d");
664                 $this->assertEquals($dt['tm_year']+1900, gmdate("Y"));
665                 $this->assertEquals($dt['tm_mon']+1, gmdate("m"));
666                 $this->assertEquals($dt['tm_mday'], gmdate("d"));
667         }
668
669         /**
670          * test getting DB date formats indifferent ways
671          */
672         public function testGetDB()
673         {
674                 $this->assertEquals(gmdate($this->time_date->merge_date_time($this->time_date->get_db_date_format(),
675                                                                                                                                                 $this->time_date->get_db_time_format())),
676                          $this->time_date->nowDb());
677         }
678
679         public function testGetCalFormats()
680         {
681                 $cal_tests = array(
682                         array("df" => "Y-m-d", "caldf" => "%Y-%m-%d", "tf" => "H:i:s", "caltf" => "%H:%M:%S"),
683                         array("df" => "d/m/Y", "caldf" => "%d/%m/%Y", "tf" => "h:i:sa", "caltf" => "%I:%M:%S%P"),
684                         array("df" => "m/d/Y", "caldf" => "%m/%d/%Y", "tf" => "H:i", "caltf" => "%H:%M"),
685                         array("df" => "Y-m-d", "caldf" => "%Y-%m-%d", "tf" => "h:iA", "caltf" => "%I:%M%p"),
686                 );
687                 foreach($cal_tests as $datetest) {
688                         $this->_setPrefs($datetest["df"], $datetest["tf"], "America/Los_Angeles");
689                         $this->assertEquals(
690                                 $datetest["caldf"],
691                                 $this->time_date->get_cal_date_format(),
692                                 "Bad cal date format for '{$datetest["df"]}'");
693                         $this->assertEquals(
694                                 $datetest["caltf"],
695                                 $this->time_date->get_cal_time_format(),
696                                 "Bad cal time format for '{$datetest["tf"]}'");
697                         $this->assertEquals(
698                                 $this->time_date->merge_date_time($datetest["caldf"], $datetest["caltf"]),
699                                 $this->time_date->get_cal_date_time_format(),
700                                 "Bad cal datetime format for '{$datetest["df"]} {$datetest["tf"]}'");
701                 }
702         }
703
704         public function dayDataSet()
705         {
706             return array(
707                         array("date" => "2010-05-19", "start" => "2010-05-19 07:00:00", "end" => "2010-05-20 06:59:59", 'tz' => 'America/Los_Angeles'),
708                         array("date" => "2010-01-19", "start" => "2010-01-19 08:00:00", "end" => "2010-01-20 07:59:59", 'tz' => 'America/Los_Angeles'),
709                         array("date" => "2010-05-19", "start" => "2010-05-18 23:00:00", "end" => "2010-05-19 22:59:59", 'tz' => 'Europe/London'),
710                         array("date" => "2010-01-19", "start" => "2010-01-19 00:00:00", "end" => "2010-01-19 23:59:59", 'tz' => 'Europe/London'),
711                         array("date" => "2010-05-19", "start" => "2010-05-18 22:00:00", "end" => "2010-05-19 21:59:59", 'tz' => 'Europe/Oslo'),
712                 );
713         }
714
715         /**
716          * test for handleOffsetMax
717          * @dataProvider dayDataSet
718          */
719         public function testDayMinMax($date, $start, $end, $tz)
720         {
721                 $this->_setPrefs('', '', $tz);
722                 $dates = $this->time_date->handleOffsetMax($date, '');
723                 $this->assertEquals($start, $dates["min"],
724                                 "Bad min result for {$date} tz {$tz}");
725                 $this->assertEquals($end, $dates["max"],
726                                 "Bad max result for {$date} tz {$tz}");
727         }
728
729         /**
730          * test for getDayStartEndGMT
731          * @dataProvider dayDataSet
732          */
733         public function testGetDayStartEnd($date, $start, $end, $tz)
734         {
735                 $this->_setPrefs('m/d/Y', '', $tz);
736         $date_arr = explode("-", $date);
737         $date = $date_arr[1].'/'.$date_arr[2].'/'.$date_arr[0];
738         $dates = $this->time_date->getDayStartEndGMT($date);
739                 $this->assertEquals($start, $dates["start"],
740                                 "Bad min result for {$date} tz {$tz}");
741                 $this->assertEquals($end, $dates["end"],
742                                 "Bad max result for {$date} tz {$tz}");
743         }
744
745         public function ampmDataSet()
746         {
747             return array(
748                         array("date" => "05:17:28", "mer" => "am", "tf" => "H:i:s", "display" => "05:17:28"),
749                         array("date" => "05:17:28", "mer" => "am", "tf" => "h:i:sa", "display" => "05:17:28am"),
750                         // short ones
751                         array("date" => "17:34", "mer" => "pm", "tf" => "H:i", "display" => "17:34"),
752                         array("date" => "11:42", "mer" => "PM", "tf" => "h:iA", "display" => "11:42PM"),
753                         array("date" => "11:42", "mer" => "pm", "tf" => "h:iA", "display" => "11:42pm"),
754                         array("date" => "03", "mer" => "AM", "tf" => "ha", "display" => "03AM"),
755                         array("date" => "15", "mer" => "AM", "tf" => "H", "display" => "15"),
756             // bug 58924 - what if we have spaces in our time format?
757             array("date" => "11.13", "mer" => "AM", "tf" => "h.i A", "display" => "11.13 AM"),
758             array("date" => "11.14", "mer" => "PM", "tf" => "h.i A", "display" => "11.14 PM"),
759             array("date" => "10.15", "mer" => "am", "tf" => "h.i a", "display" => "10.15 am"),
760                 );
761         }
762
763         /**
764          * test for merge_time_meridiem
765          * @dataProvider ampmDataSet
766          */
767         public function testMergeAmPm($date, $mer, $tf, $display)
768         {
769                 $amdate = $this->time_date->merge_time_meridiem($date, $tf, $mer);
770                 $this->assertEquals($display, $amdate,
771                                 "Bad min result for {$date} format {$tf}");
772         }
773
774         public function providerSplitDateTime()
775         {
776             return array(
777                 array("2009-10-04 02:00:00","2009-10-04","02:00:00"),
778                 array("10/04/2010 2:00pm","10/04/2010","2:00pm"),
779                 array("10-04-2010 2:00","10-04-2010","2:00"),
780                 );
781         }
782
783         /**
784          * @dataProvider providerSplitDateTime
785          */
786         public function testSplitDateTime(
787             $datetime,
788             $date,
789             $time
790             )
791         {
792             $this->assertEquals($date,$this->time_date->getDatePart($datetime));
793             $this->assertEquals($time,$this->time_date->getTimePart($datetime));
794         }
795
796         public function testNoCache()
797         {
798         $this->_setPrefs("Y-m-d", "H:i:s", "GMT");
799             $now1 = $this->time_date->now();
800             sleep(2);
801             $now2 = $this->time_date->now();
802             $this->assertNotEquals($now1, $now2, "now() should produce different result when not cached");
803         }
804
805         public function testCache()
806         {
807         $this->_setPrefs("Y-m-d", "H:i:s", "GMT");
808             $this->time_date->allow_cache = true;
809             $now1 = $this->time_date->now();
810             sleep(2);
811             $now2 = $this->time_date->now();
812             $this->assertEquals($now1, $now2, "now() should produce same result when cached");
813         }
814
815         public function stringFormats()
816         {
817             return array(
818                 array("H:i", "15:38", "15:38:00"),
819                 array("h:ia", "03:38pm", "15:38:00"),
820                 array("h:iA", "03:38PM", "15:38:00"),
821                 array("h:ia", "03:38am", "03:38:00"),
822                 array("h:iA", "03:38AM", "03:38:00"),
823                 array("H.i", "15.38", "15:38:00"),
824                 array("h.ia", "03.38pm", "15:38:00"),
825                 array("h.iA", "03.38PM", "15:38:00"),
826                 array("h:ia", "03:38 pm", "15:38:00"),
827                 array("h:iA", "03:38 PM", "15:38:00"),
828                 array("h.ia", "03.38am", "03:38:00"),
829                 array("h.iA", "03.38AM", "03:38:00"),
830                 array("h:ia", "03:38 am", "03:38:00"),
831                 array("h:iA", "03:38 AM", "03:38:00"),
832                 );
833         }
834
835         /**
836          * @dataProvider stringFormats
837          * @param string $format
838          * @param string $string
839          * @param string $result
840          */
841         public function testCreateFromString($format, $string, $result)
842         {
843         $this->_setPrefs("Y-m-d", $format, "GMT");
844         $tz = new DateTimeZone("GMT");
845         SugarDateTime::$use_php_parser = true;
846             $date = SugarDateTime::createFromFormat($format, $string, $tz);
847             $this->assertInstanceOf("SugarDateTime", $date, "Parsing $string failed with PHP parser");
848             $this->assertEquals($result, $this->time_date->getTimePart($date->asDb()));
849
850             SugarDateTime::$use_php_parser = false;
851             $date = SugarDateTime::createFromFormat($format, $string, $tz);
852             $this->assertInstanceOf("SugarDateTime", $date, "Parsing $string failed with strptime");
853             $this->assertEquals($result, $this->time_date->getTimePart($date->asDb()));
854
855             SugarDateTime::$use_strptime = false;
856             $date = SugarDateTime::createFromFormat($format, $string, $tz);
857             $this->assertInstanceOf("SugarDateTime", $date, "Parsing $string failed with manual parser");
858             $this->assertEquals($result, $this->time_date->getTimePart($date->asDb()));
859
860             SugarDateTime::$use_php_parser = true;
861             SugarDateTime::$use_strptime = true;
862         }
863
864         public function testGetTimeDate()
865         {
866             global $current_user;
867             $this->_setPrefs("Y-m-d", "H:i", "GMT");
868
869             $f = $this->time_date->get_date_time_format();
870             $this->assertEquals("Y-m-d H:i", $f);
871
872             $f = $this->time_date->get_date_time_format(true);
873             $this->assertEquals("Y-m-d H:i", $f);
874
875             $f = $this->time_date->get_date_time_format(false);
876             $this->assertEquals("Y-m-d H:i", $f);
877
878             $f = $this->time_date->get_date_time_format(null);
879             $this->assertEquals("Y-m-d H:i", $f);
880
881             $f = $this->time_date->get_date_time_format(true, null);
882             $this->assertEquals("Y-m-d H:i", $f);
883
884             $f = $this->time_date->get_date_time_format(false, null);
885             $this->assertEquals("Y-m-d H:i", $f);
886
887             $f = $this->time_date->get_date_time_format(null, null);
888             $this->assertEquals("Y-m-d H:i", $f);
889
890             $f = $this->time_date->get_date_time_format(true, $current_user);
891             $this->assertEquals("Y-m-d H:i", $f);
892
893             $f = $this->time_date->get_date_time_format(false, $current_user);
894             $this->assertEquals("Y-m-d H:i", $f);
895
896             $f = $this->time_date->get_date_time_format(null, $current_user);
897             $this->assertEquals("Y-m-d H:i", $f);
898
899             $f = $this->time_date->get_date_time_format($current_user);
900             $this->assertEquals("Y-m-d H:i", $f);
901
902             $f = $this->time_date->get_date_time_format($current_user);
903             $this->assertEquals("Y-m-d H:i", $f);
904
905             $f = $this->time_date->get_date_time_format($current_user);
906             $this->assertEquals("Y-m-d H:i", $f);
907         }
908
909         public function dateRanges()
910         {
911             return array(
912                 array("yesterday", "2011-08-29 00:00:00", "2011-08-29 23:59:59"),
913                 array("today", "2011-08-30 00:00:00", "2011-08-30 23:59:59"),
914                 array("tomorrow", "2011-08-31 00:00:00", "2011-08-31 23:59:59"),
915                 array("last_7_days", "2011-08-24 00:00:00", "2011-08-30 23:59:59"),
916                 array("next_7_days", "2011-08-30 00:00:00", "2011-09-05 23:59:59"),
917                 array("last_30_days", "2011-08-01 00:00:00", "2011-08-30 23:59:59"),
918                 array("next_30_days", "2011-08-30 00:00:00", "2011-09-28 23:59:59"),
919                 array("next_month", "2011-09-01 00:00:00", "2011-09-30 23:59:59"),
920                 array("last_month", "2011-07-01 00:00:00", "2011-07-31 23:59:59"),
921                 array("this_month", "2011-08-01 00:00:00", "2011-08-31 23:59:59"),
922                 array("next_year", "2012-01-01 00:00:00", "2012-12-31 23:59:59"),
923                 array("last_year", "2010-01-01 00:00:00", "2010-12-31 23:59:59"),
924                 array("this_year", "2011-01-01 00:00:00", "2011-12-31 23:59:59"),
925                 );
926         }
927
928         /**
929          * @dataProvider dateRanges
930          */
931         public function testparseDateRange($range, $start, $end)
932         {
933         $this->time_date->setNow(SugarDateTime::createFromFormat(TimeDate::DB_DATETIME_FORMAT, "2011-08-30 12:01:02", new DateTimeZone($this->time_date->userTimezone())));
934         $this->time_date->allow_cache = true;
935             $daterage = $this->time_date->parseDateRange($range);
936         $this->assertEquals($start, $daterage[0]->format(TimeDate::DB_DATETIME_FORMAT), 'Start date is wrong');
937         $this->assertEquals($end, $daterage[1]->format(TimeDate::DB_DATETIME_FORMAT), 'End date is wrong');
938         }
939 }