From 1a8feb646edca8a01408bf8a7d2ed7981769ae5b Mon Sep 17 00:00:00 2001 From: Charles Sanquer Date: Mon, 10 Mar 2014 09:07:23 +0100 Subject: [PATCH] add Maximum Timestamp option to get always same unix timestamp when using a fixed seed fix and improve unit tests when setting endMaximumTimestamp change static maximumEndTimestamp to an optional parameter $max in each datetime methods some improvements to DateTimeProvider max timestamp --- readme.md | 36 ++++---- src/Faker/Provider/DateTime.php | 105 +++++++++++++++-------- test/Faker/Provider/DateTimeTest.php | 122 +++++++++++++++++++++++++++ 3 files changed, 211 insertions(+), 52 deletions(-) create mode 100644 test/Faker/Provider/DateTimeTest.php diff --git a/readme.md b/readme.md index 488b39ac..1c81a696 100644 --- a/readme.md +++ b/readme.md @@ -139,25 +139,25 @@ Each of the generator properties (like `name`, `address`, and `lorem`) are calle ### `Faker\Provider\DateTime` - unixTime // 58781813 - dateTime // DateTime('2008-04-25 08:37:17') - dateTimeAD // DateTime('1800-04-29 20:38:49') - iso8601 // '1978-12-09T10:10:29+0000' - date($format = 'Y-m-d') // '1979-06-09' - time($format = 'H:i:s') // '20:49:42' + unixTime($max = 'now') // 58781813 + dateTime($max = 'now') // DateTime('2008-04-25 08:37:17') + dateTimeAD($max = 'now') // DateTime('1800-04-29 20:38:49') + iso8601($max = 'now') // '1978-12-09T10:10:29+0000' + date($format = 'Y-m-d', $max = 'now') // '1979-06-09' + time($format = 'H:i:s', $max = 'now') // '20:49:42' dateTimeBetween($startDate = '-30 years', $endDate = 'now') // DateTime('2003-03-15 02:00:49') - dateTimeThisCentury // DateTime('1915-05-30 19:28:21') - dateTimeThisDecade // DateTime('2007-05-29 22:30:48') - dateTimeThisYear // DateTime('2011-02-27 20:52:14') - dateTimeThisMonth // DateTime('2011-10-23 13:46:23') - amPm // 'pm' - dayOfMonth // '04' - dayOfWeek // 'Friday' - month // '06' - monthName // 'January' - year // '1993' - century // 'VI' - timezone // 'Europe/Paris' + dateTimeThisCentury($max = 'now') // DateTime('1915-05-30 19:28:21') + dateTimeThisDecade($max = 'now') // DateTime('2007-05-29 22:30:48') + dateTimeThisYear($max = 'now') // DateTime('2011-02-27 20:52:14') + dateTimeThisMonth($max = 'now') // DateTime('2011-10-23 13:46:23') + amPm($max = 'now') // 'pm' + dayOfMonth($max = 'now') // '04' + dayOfWeek($max = 'now') // 'Friday' + month($max = 'now') // '06' + monthName($max = 'now') // 'January' + year($max = 'now') // '1993' + century // 'VI' + timezone // 'Europe/Paris' ### `Faker\Provider\Miscellaneous` diff --git a/src/Faker/Provider/DateTime.php b/src/Faker/Provider/DateTime.php index 299edc40..d40b7cc7 100644 --- a/src/Faker/Provider/DateTime.php +++ b/src/Faker/Provider/DateTime.php @@ -6,66 +6,88 @@ class DateTime extends \Faker\Provider\Base { protected static $century = array('I','II','III','IV','V','VI','VII','VIII','IX','X','XI','XII','XIII','XIV','XV','XVI','XVII','XVIII','XIX','XX','XX1'); + protected static function getMaxTimestamp($max = 'now') + { + if (is_numeric($max)) { + return (int) $max; + } + + if ($max instanceof \DateTime) { + return $max->getTimestamp(); + } + + return strtotime(empty($max) ? 'now' : $max); + } + /** * Get a timestamp between January 1, 1970 and now * + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" + * * @example 1061306726 */ - public static function unixTime() + public static function unixTime($max = 'now') { - return mt_rand(0, time()); + return mt_rand(0, static::getMaxTimestamp($max)); } /** * Get a datetime object for a date between January 1, 1970 and now * + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example DateTime('2005-08-16 20:39:21') * @return \DateTime */ - public static function dateTime() + public static function dateTime($max = 'now') { - return new \DateTime('@' . static::unixTime()); + return new \DateTime('@' . static::unixTime($max)); } /** * Get a datetime object for a date between January 1, 001 and now * + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example DateTime('1265-03-22 21:15:52') * @return \DateTime */ - public static function dateTimeAD() + public static function dateTimeAD($max = 'now') { - return new \DateTime('@' . mt_rand(-62135597361, time())); + return new \DateTime('@' . mt_rand(-62135597361, static::getMaxTimestamp($max))); } /** + * get a date string formatted with ISO8601 + * + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example '2003-10-21T16:05:52+0000' */ - public static function iso8601() + public static function iso8601($max = 'now') { - return static::date(\DateTime::ISO8601); + return static::date(\DateTime::ISO8601, $max); } /** * Get a date string between January 1, 1970 and now * * @param string $format + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example '2008-11-27' */ - public static function date($format = 'Y-m-d') + public static function date($format = 'Y-m-d', $max = 'now') { - return static::dateTime()->format($format); + return static::dateTime($max)->format($format); } /** * Get a time string (24h format by default) * * @param string $format + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example '15:02:34' */ - public static function time($format = 'H:i:s') + public static function time($format = 'H:i:s', $max = 'now') { - return static::dateTime()->format($format); + return static::dateTime($max)->format($format); } /** @@ -77,10 +99,15 @@ class DateTime extends \Faker\Provider\Base * @example DateTime('1999-02-02 11:42:52') * @return \DateTime */ - public static function dateTimeBetween($startDate = "-30 years", $endDate = "now") + public static function dateTimeBetween($startDate = '-30 years', $endDate = 'now') { $startTimestamp = $startDate instanceof \DateTime ? $startDate->getTimestamp() : strtotime($startDate); - $endTimestamp = $endDate instanceof \DateTime ? $endDate->getTimestamp() : strtotime($endDate); + $endTimestamp = static::getMaxTimestamp($endDate); + + if ($startTimestamp > $endTimestamp) { + throw new \InvalidArgumentException('Start date must be anterior to end date.'); + } + $timestamp = mt_rand($startTimestamp, $endTimestamp); $ts = new \DateTime('@' . $timestamp); @@ -90,87 +117,97 @@ class DateTime extends \Faker\Provider\Base } /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example DateTime('1964-04-04 11:02:02') * @return \DateTime */ - public static function dateTimeThisCentury() + public static function dateTimeThisCentury($max = 'now') { - return static::dateTimeBetween("-100 year"); + return static::dateTimeBetween('-100 year', $max); } /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example DateTime('2010-03-10 05:18:58') * @return \DateTime */ - public static function dateTimeThisDecade() + public static function dateTimeThisDecade($max = 'now') { - return static::dateTimeBetween("-10 year"); + return static::dateTimeBetween('-10 year', $max); } /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example DateTime('2011-09-19 09:24:37') * @return \DateTime */ - public static function dateTimeThisYear() + public static function dateTimeThisYear($max = 'now') { - return static::dateTimeBetween("-1 year"); + return static::dateTimeBetween('-1 year', $max); } /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example DateTime('2011-10-05 12:51:46') * @return \DateTime */ - public static function dateTimeThisMonth() + public static function dateTimeThisMonth($max = 'now') { - return static::dateTimeBetween("-1 month"); + return static::dateTimeBetween('-1 month', $max); } /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example 'am' */ - public static function amPm() + public static function amPm($max = 'now') { - return static::dateTime()->format('a'); + return static::dateTime($max)->format('a'); } /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example '22' */ - public static function dayOfMonth() + public static function dayOfMonth($max = 'now') { - return static::dateTime()->format('d'); + return static::dateTime($max)->format('d'); } /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example 'Tuesday' */ - public static function dayOfWeek() + public static function dayOfWeek($max = 'now') { - return static::dateTime()->format('l'); + return static::dateTime($max)->format('l'); } /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example '7' */ - public static function month() + public static function month($max = 'now') { - return static::dateTime()->format('m'); + return static::dateTime($max)->format('m'); } /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example 'September' */ - public static function monthName() + public static function monthName($max = 'now') { - return static::dateTime()->format('F'); + return static::dateTime($max)->format('F'); } /** + * @param \DateTime|int|string $max maximum timestamp used as random end limit, default to "now" * @example 1673 */ - public static function year() + public static function year($max = 'now') { - return static::dateTime()->format('Y'); + return static::dateTime($max)->format('Y'); } /** diff --git a/test/Faker/Provider/DateTimeTest.php b/test/Faker/Provider/DateTimeTest.php new file mode 100644 index 00000000..1b1f6180 --- /dev/null +++ b/test/Faker/Provider/DateTimeTest.php @@ -0,0 +1,122 @@ +assertInternalType('int', $timestamp); + $this->assertTrue($timestamp >= 0); + $this->assertTrue($timestamp <= time()); + } + + public function testDateTime() + { + $date = DateTimeProvider::dateTime(); + $this->assertInstanceOf('\DateTime', $date); + $this->assertGreaterThanOrEqual(new \DateTime('@0'), $date); + $this->assertLessThanOrEqual(new \DateTime(), $date); + } + + public function testDateTimeAD() + { + $date = DateTimeProvider::dateTimeAD(); + $this->assertInstanceOf('\DateTime', $date); + $this->assertGreaterThanOrEqual(new \DateTime('0000-01-01 00:00:00'), $date); + $this->assertLessThanOrEqual(new \DateTime(), $date); + } + + public function testIso8601() + { + $date = DateTimeProvider::iso8601(); + $this->assertRegExp('/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-Z](\d{4})?$/', $date); + $this->assertGreaterThanOrEqual(new \DateTime('@0'), new \DateTime($date)); + $this->assertLessThanOrEqual(new \DateTime(), new \DateTime($date)); + } + + public function testDate() + { + $date = DateTimeProvider::date(); + $this->assertRegExp('/^\d{4}-\d{2}-\d{2}$/', $date); + $this->assertGreaterThanOrEqual(new \DateTime('@0'), new \DateTime($date)); + $this->assertLessThanOrEqual(new \DateTime(), new \DateTime($date)); + } + + public function testTime() + { + $date = DateTimeProvider::time(); + $this->assertRegExp('/^\d{2}:\d{2}:\d{2}$/', $date); + } + + /** + * + * @dataProvider providerDateTimeBetween + */ + public function testDateTimeBetween($start, $end) + { + $date = DateTimeProvider::dateTimeBetween($start, $end); + $this->assertInstanceOf('\DateTime', $date); + $this->assertGreaterThanOrEqual(new \DateTime($start), $date); + $this->assertLessThanOrEqual(new \DateTime($end), $date); + } + + public function providerDateTimeBetween() + { + return array( + array('-1 year', false), + array('-1 year', null), + array('-1 day', '-1 hour'), + array('-1 day', 'now'), + ); + } + + public function testFixedSeedWithMaximumTimestamp() + { + $max = '2014-03-01 12:00:00'; + + mt_srand(1); + $unixTime = DateTimeProvider::unixTime($max); + $datetimeAD = DateTimeProvider::dateTimeAD($max); + $dateTime1 = DateTimeProvider::dateTime($max); + $dateTimeBetween = DateTimeProvider::dateTimeBetween('2014-03-01 06:00:00', $max); + $date = DateTimeProvider::date('Y-m-d', $max); + $time = DateTimeProvider::time('H:i:s', $max); + $iso8601 = DateTimeProvider::iso8601($max); + $dateTimeThisCentury = DateTimeProvider::dateTimeThisCentury($max); + $dateTimeThisDecade = DateTimeProvider::dateTimeThisDecade($max); + $dateTimeThisMonth = DateTimeProvider::dateTimeThisMonth($max); + $amPm = DateTimeProvider::amPm($max); + $dayOfMonth = DateTimeProvider::dayOfMonth($max); + $dayOfWeek = DateTimeProvider::dayOfWeek($max); + $month = DateTimeProvider::month($max); + $monthName = DateTimeProvider::monthName($max); + $year = DateTimeProvider::year($max); + $dateTimeThisYear = DateTimeProvider::dateTimeThisYear($max); + mt_srand(); + + //regenerate Random Date with same seed and same maximum end timestamp + mt_srand(1); + $this->assertEquals($unixTime, DateTimeProvider::unixTime($max)); + $this->assertEquals($datetimeAD, DateTimeProvider::dateTimeAD($max)); + $this->assertEquals($dateTime1, DateTimeProvider::dateTime($max)); + $this->assertEquals($dateTimeBetween, DateTimeProvider::dateTimeBetween('2014-03-01 06:00:00', $max)); + $this->assertEquals($date, DateTimeProvider::date('Y-m-d', $max)); + $this->assertEquals($time, DateTimeProvider::time('H:i:s', $max)); + $this->assertEquals($iso8601, DateTimeProvider::iso8601($max)); + $this->assertEquals($dateTimeThisCentury, DateTimeProvider::dateTimeThisCentury($max)); + $this->assertEquals($dateTimeThisDecade, DateTimeProvider::dateTimeThisDecade($max)); + $this->assertEquals($dateTimeThisMonth, DateTimeProvider::dateTimeThisMonth($max)); + $this->assertEquals($amPm, DateTimeProvider::amPm($max)); + $this->assertEquals($dayOfMonth, DateTimeProvider::dayOfMonth($max)); + $this->assertEquals($dayOfWeek, DateTimeProvider::dayOfWeek($max)); + $this->assertEquals($month, DateTimeProvider::month($max)); + $this->assertEquals($monthName, DateTimeProvider::monthName($max)); + $this->assertEquals($year, DateTimeProvider::year($max)); + $this->assertEquals($dateTimeThisYear, DateTimeProvider::dateTimeThisYear($max)); + mt_srand(); + } +}