Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Random time and date between 2 date values

Tags:

php

I'm trying to write a php script (or line of code) to echo a random time and date between 2 dates, eg

2012-12-24 13:03

which would be between my chosen dates of 1st October 2012 and 1st Jan 2013.

Any ideas how best to do this? Thanks in advance.

like image 853
Sara44 Avatar asked Jan 06 '13 21:01

Sara44


3 Answers

Easy :) Just choose 2 random dates, convert to EPOCH, and random between these 2 values :)

EPOCH - The time since 1/1/1970, in seconds.
You can use the strtotime() function to make date-strings turn into epoch time, and the date() function to make it the other way back.

function rand_date($min_date, $max_date) {
    /* Gets 2 dates as string, earlier and later date.
       Returns date in between them.
    */

    $min_epoch = strtotime($min_date);
    $max_epoch = strtotime($max_date);

    $rand_epoch = rand($min_epoch, $max_epoch);

    return date('Y-m-d H:i:s', $rand_epoch);
}
like image 185
Yam Mesicka Avatar answered Sep 28 '22 15:09

Yam Mesicka


You probably want to define a resolution, for example one minute, or three minutes or 15 seconds or one and a half day or what not. The randomness should be applied on the whole period, I've choosen one minute here for exemplary purposes (there are 132480 minutes in your period).

$start    = new Datetime('1st October 2012');
$end      = new Datetime('1st Jan 2013');
$interval = new DateInterval('PT1M'); // Resolution: 1 Minute
$period   = new DatePeriod($start, $interval, $end);
$random   = new RandomIterator($period);

list($result) = iterator_to_array($random, false) ? : [null];    

This for example gives:

class DateTime#7 (3) {
  public $date =>
  string(19) "2012-10-16 02:06:00"
  public $timezone_type =>
  int(3)
  public $timezone =>
  string(13) "Europe/Berlin"
}

You can find the RandomIterator here. Without it, it will take a little longer (ca. 1.5 the number of iterations compared to the example above) using:

$count    = iterator_count($period);
$random   = rand(1, $count);

$limited = new LimitIterator(new IteratorIterator($period), $random - 1, 1);
$limited->rewind();
$result = $limited->current();

I also tried with seconds, but that would take quite long. You probably want first to find a random day (92 days), and then some random time in it.

Also I've run some tests and I could not find any benefit in using DatePeriod so far as long as you're on common resolutions like seconds:

$start    = new Datetime('1st October 2012');
$end      = new Datetime('1st Jan 2013');

$random   = new DateTime('@' . mt_rand($start->getTimestamp(), $end->getTimestamp()));

or minutes:

/**
 * @param DateTime $start
 * @param DateTime $end
 * @param int|DateInterval $resolution in Seconds or as DateInterval
 * @return DateTime
 */
$randomTime = function (DateTime $start, DateTime $end, $resolution = 1) {

    if ($resolution instanceof DateInterval) {
        $interval   = $resolution;
        $resolution = ($interval->m * 2.62974e6 + $interval->d) * 86400 + $interval->h * 60 + $interval->s;
    }

    $startValue = floor($start->getTimestamp() / $resolution);
    $endValue   = ceil($end->getTimestamp() / $resolution);
    $random     = mt_rand($startValue, $endValue) * $resolution;

    return new DateTime('@' . $random);
};

$random = $randomTime($start, $end, 60);
like image 32
hakre Avatar answered Sep 28 '22 15:09

hakre


Assuming you want to include October 1st, but not include Jan 1st...

$start = strtotime("2012-10-01 00:00:00");
$end =  strtotime("2012-12-31 23:59:59");

$randomDate = date("Y-m-d H:i:s", rand($start, $end));

echo $randomDate;
like image 43
Ray Avatar answered Sep 28 '22 15:09

Ray