1<?php defined('SYSPATH') OR die('Kohana bootstrap needs to be included before tests run'); 2 3/** 4 * Tests Date class 5 * 6 * @group kohana 7 * @group kohana.core 8 * @group kohana.core.date 9 * 10 * @package Kohana 11 * @category Tests 12 * @author Kohana Team 13 * @author BRMatt <matthew@sigswitch.com> 14 * @copyright (c) 2008-2012 Kohana Team 15 * @license http://kohanaframework.org/license 16 */ 17class Kohana_DateTest extends Unittest_TestCase 18{ 19 protected $_original_timezone = NULL; 20 protected $default_locale; 21 22 /** 23 * Ensures we have a consistant timezone for testing. 24 */ 25 // @codingStandardsIgnoreStart 26 public function setUp() 27 // @codingStandardsIgnoreEnd 28 { 29 parent::setUp(); 30 31 $this->_original_timezone = date_default_timezone_get(); 32 $this->default_locale = setlocale(LC_ALL, 0); 33 34 date_default_timezone_set('America/Chicago'); 35 setlocale(LC_ALL, 'en_US.utf8'); 36 } 37 38 /** 39 * Restores original timezone after testing. 40 */ 41 // @codingStandardsIgnoreStart 42 public function tearDown() 43 // @codingStandardsIgnoreEnd 44 { 45 date_default_timezone_set($this->_original_timezone); 46 setlocale(LC_ALL, $this->default_locale); 47 48 parent::tearDown(); 49 } 50 51 /** 52 * Provides test data for test_offset() 53 * 54 * @return array 55 */ 56 public function provider_offset() 57 { 58 return array( 59 array(30600, 'Asia/Calcutta', 'America/Argentina/Buenos_Aires'), 60 ); 61 } 62 63 /** 64 * Tests Date::offset() 65 * 66 * @test 67 * @dataProvider provider_offset 68 * @covers Date::offset 69 * @param integer $expected Expected offset 70 * @param string $remote Remote TZ 71 * @param string $local Local TZ 72 * @param integer $now Current timestamp 73 */ 74 public function test_offset($expected, $remote, $local, $now = NULL) 75 { 76 $this->assertSame($expected, Date::offset($remote, $local, $now)); 77 } 78 79 /** 80 * Provides test data for test_date() 81 * 82 * @return array 83 */ 84 public function provider_am_pm() 85 { 86 return array( 87 // All possible values 88 array(0, 'AM'), 89 array(1, 'AM'), 90 array(2, 'AM'), 91 array(3, 'AM'), 92 array(4, 'AM'), 93 array(5, 'AM'), 94 array(6, 'AM'), 95 array(7, 'AM'), 96 array(8, 'AM'), 97 array(9, 'AM'), 98 array(10, 'AM'), 99 array(11, 'AM'), 100 array(12, 'PM'), 101 array(13, 'PM'), 102 array(14, 'PM'), 103 array(15, 'PM'), 104 array(16, 'PM'), 105 array(17, 'PM'), 106 array(18, 'PM'), 107 array(19, 'PM'), 108 array(20, 'PM'), 109 array(21, 'PM'), 110 array(22, 'PM'), 111 array(23, 'PM'), 112 array(24, 'PM'), 113 // ampm doesn't validate the hour, so I don't think we should test it.. 114 // test strings are converted 115 array('0', 'AM'), 116 array('12', 'PM'), 117 ); 118 } 119 120 /** 121 * Tests Date::ampm() 122 * 123 * @test 124 * @covers Date::ampm 125 * @dataProvider provider_am_pm 126 * @param <type> $hour 127 * @param <type> $expected 128 */ 129 public function test_am_pm($hour, $expected) 130 { 131 $this->assertSame( 132 $expected, 133 Date::ampm($hour) 134 ); 135 } 136 137 /** 138 * Provides test data for test_adjust() 139 * 140 * @return array 141 */ 142 public function provider_adjust() 143 { 144 return array( 145 // Might as well test all possibilities 146 array(1, 'am', '01'), 147 array(2, 'am', '02'), 148 array(3, 'am', '03'), 149 array(4, 'am', '04'), 150 array(5, 'am', '05'), 151 array(6, 'am', '06'), 152 array(7, 'am', '07'), 153 array(8, 'am', '08'), 154 array(9, 'am', '09'), 155 array(10, 'am', '10'), 156 array(11, 'am', '11'), 157 array(12, 'am', '00'), 158 array(1, 'pm', '13'), 159 array(2, 'pm', '14'), 160 array(3, 'pm', '15'), 161 array(4, 'pm', '16'), 162 array(5, 'pm', '17'), 163 array(6, 'pm', '18'), 164 array(7, 'pm', '19'), 165 array(8, 'pm', '20'), 166 array(9, 'pm', '21'), 167 array(10, 'pm', '22'), 168 array(11, 'pm', '23'), 169 array(12, 'pm', '12'), 170 // It should also work with strings instead of ints 171 array('10', 'pm', '22'), 172 array('10', 'am', '10'), 173 ); 174 } 175 176 /** 177 * Tests Date::ampm() 178 * 179 * @test 180 * @dataProvider provider_adjust 181 * @param integer $hour Hour in 12 hour format 182 * @param string $ampm Either am or pm 183 * @param string $expected Expected result 184 */ 185 public function test_adjust($hour, $ampm, $expected) 186 { 187 $this->assertSame( 188 $expected, 189 Date::adjust($hour, $ampm) 190 ); 191 } 192 193 /** 194 * Provides test data for test_days() 195 * 196 * @return array 197 */ 198 public function provider_days() 199 { 200 return array( 201 // According to "the rhyme" these should be the same every year 202 array(9, FALSE, 30), 203 array(4, FALSE, 30), 204 array(6, FALSE, 30), 205 array(11, FALSE, 30), 206 array(1, FALSE, 31), 207 array(3, FALSE, 31), 208 array(5, FALSE, 31), 209 array(7, FALSE, 31), 210 array(8, FALSE, 31), 211 array(10, FALSE, 31), 212 // February is such a pain 213 array(2, 2001, 28), 214 array(2, 2000, 29), 215 array(2, 2012, 29), 216 ); 217 } 218 219 /** 220 * Tests Date::days() 221 * 222 * @test 223 * @covers Date::days 224 * @dataProvider provider_days 225 * @param integer $month 226 * @param integer $year 227 * @param integer $expected 228 */ 229 public function test_days($month, $year, $expected) 230 { 231 $days = Date::days($month, $year); 232 233 $this->assertSame( 234 $expected, 235 count($days) 236 ); 237 238 // This should be a mirrored array, days => days 239 for ($i = 1; $i <= $expected; ++$i) 240 { 241 $this->assertArrayHasKey($i, $days); 242 // Combining the type check into this saves about 400-500 assertions! 243 $this->assertSame( (string) $i, $days[$i]); 244 } 245 } 246 247 /** 248 * Provides test data for test_formatted_time() 249 * 250 * @return array 251 */ 252 public function provider_formatted_time() 253 { 254 return array( 255 // Test the default format 256 array('2010-04-16 17:00:00', '5:00PM 16th April 2010'), 257 // Now we use our own format 258 // Binary date! 259 array('01/01/2010 01:00', '1AM 1st January 2010', 'd/m/Y H:i'), 260 // Timezones (see #3902) 261 array('2011-04-01 01:23:45 Antarctica/South_Pole', '2011-04-01 01:23:45', 'Y-m-d H:i:s e', 'Antarctica/South_Pole'), 262 array('2011-04-01 01:23:45 Antarctica/South_Pole', '2011-03-31 14:23:45 Europe/Paris', 'Y-m-d H:i:s e', 'Antarctica/South_Pole'), 263 array('2011-04-01 01:23:45 Antarctica/South_Pole', '@1301574225', 'Y-m-d H:i:s e', 'Antarctica/South_Pole'), 264 ); 265 } 266 267 /** 268 * Tests Date::formatted_time() 269 * 270 * @test 271 * @dataProvider provider_formatted_time 272 * @covers Date::formatted_time 273 * @ticket 3035 3902 274 * @param string $expected Expected output 275 * @param string|integer $datetime_str The datetime timestamp / string 276 * @param string|null $timestamp_format The output format 277 * @param string|null $timezone The timezone identifier 278 */ 279 public function test_formatted_time($expected, $datetime_str, $timestamp_format = NULL, $timezone = NULL) 280 { 281 $timestamp = Date::formatted_time($datetime_str, $timestamp_format, $timezone); 282 283 $this->assertSame($expected, $timestamp); 284 } 285 286 /** 287 * Provider for test_months() 288 * 289 * @return array Test data 290 */ 291 public function provider_months() 292 { 293 return array( 294 array( 295 array( 296 1 => "1", 297 2 => "2", 298 3 => "3", 299 4 => "4", 300 5 => "5", 301 6 => "6", 302 7 => "7", 303 8 => "8", 304 9 => "9", 305 10 => "10", 306 11 => "11", 307 12 => "12" 308 ), 309 NULL 310 ), 311 array( 312 array( 313 1 => "1", 314 2 => "2", 315 3 => "3", 316 4 => "4", 317 5 => "5", 318 6 => "6", 319 7 => "7", 320 8 => "8", 321 9 => "9", 322 10 => "10", 323 11 => "11", 324 12 => "12" 325 ), 326 'Guinness' 327 ), 328 array( 329 array( 330 1 => "January", 331 2 => "February", 332 3 => "March", 333 4 => "April", 334 5 => "May", 335 6 => "June", 336 7 => "July", 337 8 => "August", 338 9 => "September", 339 10 => "October", 340 11 => "November", 341 12 => "December" 342 ), 343 Date::MONTHS_LONG 344 ), 345 array( 346 array( 347 1 => "Jan", 348 2 => "Feb", 349 3 => "Mar", 350 4 => "Apr", 351 5 => "May", 352 6 => "Jun", 353 7 => "Jul", 354 8 => "Aug", 355 9 => "Sep", 356 10 => "Oct", 357 11 => "Nov", 358 12 => "Dec" 359 ), 360 Date::MONTHS_SHORT 361 ) 362 363 ); 364 } 365 366 /** 367 * Date::months() should allow the user to specify different format types, defaulting 368 * to a mirrored month number => month number array if format is NULL or unrecognised 369 * 370 * @test 371 * @dataProvider provider_months 372 * @covers Date::months 373 */ 374 public function test_months($expected, $format) 375 { 376 $months = Date::months($format); 377 378 $this->assertSame($expected, $months); 379 } 380 381 /** 382 * Provides test data for test_span() 383 * 384 * @return array 385 */ 386 public function provider_span() 387 { 388 $time = time(); 389 return array( 390 // Test that it must specify an output format 391 array( 392 $time, 393 $time, 394 '', 395 FALSE 396 ), 397 // Test that providing only one output just returns that output 398 array( 399 $time - 30, 400 $time, 401 'seconds', 402 30 403 ), 404 // Random tests 405 array( 406 $time - 30, 407 $time, 408 'years,months,weeks,days,hours,minutes,seconds', 409 array('years' => 0, 'months' => 0, 'weeks' => 0, 'days' => 0, 'hours' => 0, 'minutes' => 0, 'seconds' => 30), 410 ), 411 array( 412 $time - (60 * 60 * 24 * 782) + (60 * 25), 413 $time, 414 'years,months,weeks,days,hours,minutes,seconds', 415 array('years' => 2, 'months' => 1, 'weeks' => 3, 'days' => 0, 'hours' => 1, 'minutes' => 28, 'seconds' => 24), 416 ), 417 // Should be able to compare with the future & that it only uses formats specified 418 array( 419 $time + (60 * 60 * 24 * 15) + (60 * 5), 420 $time, 421 'weeks,days,hours,minutes,seconds', 422 array('weeks' => 2, 'days' => 1, 'hours' => 0, 'minutes' => 5, 'seconds' => 0), 423 ), 424 array( 425 // Add a bit of extra time to account for phpunit processing 426 $time + (14 * 31 * 24* 60 * 60) + (79 * 80), 427 NULL, 428 'months,years', 429 array('months' => 2, 'years' => 1), 430 ), 431 ); 432 } 433 434 /** 435 * Tests Date::span() 436 * 437 * @test 438 * @covers Date::span 439 * @dataProvider provider_span 440 * @param integer $time1 Time in the past 441 * @param integer $time2 Time to compare against 442 * @param string $output Units to output 443 * @param array $expected Array of $outputs => values 444 */ 445 public function test_span($time1, $time2, $output, $expected) 446 { 447 $this->assertSame( 448 $expected, 449 Date::span($time1, $time2, $output) 450 ); 451 } 452 453 /** 454 * Provides test data to test_fuzzy_span 455 * 456 * This test data is provided on the assumption that it 457 * won't take phpunit more than 30 seconds to get the 458 * data from this provider to the test... ;) 459 * 460 * @return array Test Data 461 */ 462 public function provider_fuzzy_span() 463 { 464 $now = time(); 465 466 return array( 467 array('moments ago', $now - 30, $now), 468 array('in moments', $now + 30, $now), 469 470 array('a few minutes ago', $now - 10*60, $now), 471 array('in a few minutes', $now + 10*60, $now), 472 473 array('less than an hour ago', $now - 45*60, $now), 474 array('in less than an hour', $now + 45*60, $now), 475 476 array('a couple of hours ago', $now - 2*60*60, $now), 477 array('in a couple of hours', $now + 2*60*60, $now), 478 479 array('less than a day ago', $now - 12*60*60, $now), 480 array('in less than a day', $now + 12*60*60, $now), 481 482 array('about a day ago', $now - 30*60*60, $now), 483 array('in about a day', $now + 30*60*60, $now), 484 485 array('a couple of days ago', $now - 3*24*60*60, $now), 486 array('in a couple of days', $now + 3*24*60*60, $now), 487 488 array('less than a week ago', $now - 5*24*60*60, $now), 489 array('in less than a week', $now + 5*24*60*60, $now), 490 491 array('about a week ago', $now - 9*24*60*60, $now), 492 array('in about a week', $now + 9*24*60*60, $now), 493 494 array('less than a month ago', $now - 20*24*60*60, $now), 495 array('in less than a month', $now + 20*24*60*60, $now), 496 497 array('about a month ago', $now - 40*24*60*60, $now), 498 array('in about a month', $now + 40*24*60*60, $now), 499 500 array('a couple of months ago', $now - 3*30*24*60*60, $now), 501 array('in a couple of months', $now + 3*30*24*60*60, $now), 502 503 array('less than a year ago', $now - 7*31*24*60*60, $now), 504 array('in less than a year', $now + 7*31*24*60*60, $now), 505 506 array('about a year ago', $now - 18*31*24*60*60, $now), 507 array('in about a year', $now + 18*31*24*60*60, $now), 508 509 array('a couple of years ago', $now - 3*12*31*24*60*60, $now), 510 array('in a couple of years', $now + 3*12*31*24*60*60, $now), 511 512 array('a few years ago', $now - 5*12*31*24*60*60, $now), 513 array('in a few years', $now + 5*12*31*24*60*60, $now), 514 515 array('about a decade ago', $now - 11*12*31*24*60*60, $now), 516 array('in about a decade', $now + 11*12*31*24*60*60, $now), 517 518 array('a couple of decades ago', $now - 20*12*31*24*60*60, $now), 519 array('in a couple of decades', $now + 20*12*31*24*60*60, $now), 520 521 array('several decades ago', $now - 50*12*31*24*60*60, $now), 522 array('in several decades', $now + 50*12*31*24*60*60, $now), 523 524 array('a long time ago', $now - pow(10,10), $now), 525 array('in a long time', $now + pow(10,10), $now), 526 ); 527 } 528 529 /** 530 * Test of Date::fuzy_span() 531 * 532 * @test 533 * @dataProvider provider_fuzzy_span 534 * @param string $expected Expected output 535 * @param integer $timestamp Timestamp to use 536 * @param integer $local_timestamp The local timestamp to use 537 */ 538 public function test_fuzzy_span($expected, $timestamp, $local_timestamp) 539 { 540 $this->assertSame( 541 $expected, 542 Date::fuzzy_span($timestamp, $local_timestamp) 543 ); 544 } 545 546 /** 547 * Provides test data for test_years() 548 * 549 * @return array Test Data 550 */ 551 public function provider_years() 552 { 553 return array( 554 array( 555 array ( 556 2005 => '2005', 557 2006 => '2006', 558 2007 => '2007', 559 2008 => '2008', 560 2009 => '2009', 561 2010 => '2010', 562 2011 => '2011', 563 2012 => '2012', 564 2013 => '2013', 565 2014 => '2014', 566 2015 => '2015', 567 ), 568 2005, 569 2015 570 ), 571 ); 572 } 573 574 /** 575 * Tests Data::years() 576 * 577 * @test 578 * @dataProvider provider_years 579 */ 580 public function test_years($expected, $start = FALSE, $end = FALSE) 581 { 582 $this->assertSame( 583 $expected, 584 Date::years($start, $end) 585 ); 586 } 587 588 public function provider_hours() 589 { 590 return array( 591 array( 592 array( 593 1 => '1', 594 2 => '2', 595 3 => '3', 596 4 => '4', 597 5 => '5', 598 6 => '6', 599 7 => '7', 600 8 => '8', 601 9 => '9', 602 10 => '10', 603 11 => '11', 604 12 => '12', 605 ), 606 ), 607 ); 608 } 609 610 /** 611 * Test for Date::hours 612 * 613 * @test 614 * @dataProvider provider_hours 615 */ 616 public function test_hours($expected, $step = 1, $long = FALSE, $start = NULL) 617 { 618 $this->assertSame( 619 $expected, 620 Date::hours($step, $long, $start) 621 ); 622 } 623 624 /** 625 * Provides test data for test_seconds 626 * 627 * @return array Test data 628 */ 629 public function provider_seconds() 630 { 631 return array( 632 array( 633 // Thank god for var_export() 634 array ( 635 0 => '00', 1 => '01', 2 => '02', 3 => '03', 4 => '04', 636 5 => '05', 6 => '06', 7 => '07', 8 => '08', 9 => '09', 637 10 => '10', 11 => '11', 12 => '12', 13 => '13', 14 => '14', 638 15 => '15', 16 => '16', 17 => '17', 18 => '18', 19 => '19', 639 20 => '20', 21 => '21', 22 => '22', 23 => '23', 24 => '24', 640 25 => '25', 26 => '26', 27 => '27', 28 => '28', 29 => '29', 641 30 => '30', 31 => '31', 32 => '32', 33 => '33', 34 => '34', 642 35 => '35', 36 => '36', 37 => '37', 38 => '38', 39 => '39', 643 40 => '40', 41 => '41', 42 => '42', 43 => '43', 44 => '44', 644 45 => '45', 46 => '46', 47 => '47', 48 => '48', 49 => '49', 645 50 => '50', 51 => '51', 52 => '52', 53 => '53', 54 => '54', 646 55 => '55', 56 => '56', 57 => '57', 58 => '58', 59 => '59', 647 ), 648 1, 649 0, 650 60 651 ), 652 ); 653 } 654 655 /** 656 * 657 * @test 658 * @dataProvider provider_seconds 659 * @covers Date::seconds 660 */ 661 public function test_seconds($expected, $step = 1, $start = 0, $end = 60) 662 { 663 $this->assertSame( 664 $expected, 665 Date::seconds($step, $start, $end) 666 ); 667 } 668 669 /** 670 * Provides test data for test_minutes 671 * 672 * @return array Test data 673 */ 674 public function provider_minutes() 675 { 676 return array( 677 array( 678 array( 679 0 => '00', 5 => '05', 10 => '10', 680 15 => '15', 20 => '20', 25 => '25', 681 30 => '30', 35 => '35', 40 => '40', 682 45 => '45', 50 => '50', 55 => '55', 683 ), 684 5, 685 ), 686 ); 687 } 688 689 /** 690 * 691 * @test 692 * @dataProvider provider_minutes 693 */ 694 public function test_minutes($expected, $step) 695 { 696 $this->assertSame( 697 $expected, 698 Date::minutes($step) 699 ); 700 } 701 702 /** 703 * This tests that the minutes helper defaults to using a $step of 5 704 * and thus returns an array of 5 minute itervals 705 * 706 * @test 707 * @covers Date::minutes 708 */ 709 public function test_minutes_defaults_to_using_step_of5() 710 { 711 $minutes = array( 712 0 => '00', 5 => '05', 10 => '10', 713 15 => '15', 20 => '20', 25 => '25', 714 30 => '30', 35 => '35', 40 => '40', 715 45 => '45', 50 => '50', 55 => '55', 716 ); 717 718 $this->assertSame( 719 $minutes, 720 Date::minutes() 721 ); 722 } 723 724 /** 725 * Provids for test_unix2dos 726 * 727 * @return array Test Data 728 */ 729 public function provider_unix2dos() 730 { 731 return array( 732 array( 733 1024341746, 734 1281786936 735 ), 736 array( 737 2162688, 738 315554400 739 ) 740 ); 741 } 742 743 /** 744 * Test Date::unix2dos() 745 * 746 * You should always pass a timestamp as otherwise the current 747 * date/time would be used and that's oviously variable 748 * 749 * Geert seems to be the only person who knows how unix2dos() works 750 * so we just throw in some random values and see what happens 751 * 752 * @test 753 * @dataProvider provider_unix2dos 754 * @covers Date::unix2dos 755 * @param integer $expected Expected output 756 * @param integer $timestamp Input timestamp 757 */ 758 public function test_unix2dos($expected, $timestamp) 759 { 760 $this->assertSame($expected, Date::unix2dos($timestamp)); 761 } 762 763 /** 764 * Provides test data for test_dos2unix 765 * 766 * @return array Test data 767 */ 768 public function provider_dos2unix() 769 { 770 return array( 771 array( 772 1281786936, 773 1024341746, 774 ), 775 array( 776 315554400, 777 2162688, 778 ), 779 ); 780 } 781 782 /** 783 * Tests Date::dos2unix 784 * 785 * @test 786 * @dataProvider provider_dos2unix 787 * @param integer $expected Expected output 788 * @param integer $timestamp Input timestamp 789 */ 790 public function test_dos2unix($expected, $timestamp) 791 { 792 $this->assertEquals($expected, Date::dos2unix($timestamp)); 793 } 794} 795