0

I have the following function that Generateds a random date:

   function createARandomDateBetweenRange(Carbon $start, Carbon $stop, int $weekDay=null) : Carbon
    {
        $randDate = random_int($start->getTimestamp(), $stop->getTimestamp());
        $radomDate = Carbon::createFromTimestamp($randDate);

        return $radomDate
    }

But for some reason I need to be able to select a random Monday, tuesday etc etc from a provided weekday (0 is Sunday, 6 is Saturday)

So I changed the definition as:

use Carbon\Carbon;

    public static function createARandomDateBetweenRange(Carbon $start, Carbon $stop, ?int $weekDay=null) : Carbon
    {
        $randDate = random_int($start->getTimestamp(), $stop->getTimestamp());
        $radomDate = Carbon::createFromTimestamp($randDate);

        if($weekDay!=null && $weeekDay >= Carbon::SUNDAY  && $weekDay <= Carbon::SATURDAY)
        {
          // Modify the date in order to get the correct date here

        }

        return $radomDate;
    }

So how I can get the correct date from a specified range of dated and that random datetime to be a specific weekday I provide as a parameter?

For example when I call the function like:

use Carbon\Carbon;

$now = Carbon::now()
$fiveMonthsLater= new Carbon($now);
$fiveMonthsLater->modify("+5 months");

$randomTuesday=createARandomDateBetweenRange($now,$fiveMonthsLater,Carbon::TUESDAY);

$randomSaturday=createARandomDateBetweenRange($now,$fiveMonthsLater,Carbon::SATURDAY);

echo $randomTuesday->isoFormat("dddd"); //Outputs Tuesday
echo $randomSaturday->isoFormat("dddd"); //Outputs Saturdat

Dimitrios Desyllas
  • 9,082
  • 15
  • 74
  • 164

2 Answers2

1

You could filter the period to the day you want, then randomly choose one.

use Carbon\CarbonPeriod;

$period = CarbonPeriod::between('2000-01-01', '2000-12-31');

// Define your filters
$mondayFilter = function ($date) { return $date->isMonday(); };
$tuesdayFilter = function ($date) { return $date->isTuesday(); };
...

// Apply your filter
$mondays = $period->filter($mondayFilter)->toArray();

// Grab a random date from your filtered period. 
var_dump(
    $mondays[array_rand($mondays)]
);

EDIT

Integrating it into your current example:

use Carbon\CarbonPeriod;

function createARandomDateBetweenRange($start, $end, $filter = null)
{
    $period = CarbonPeriod::between($start, $end);

    if ($filter) {
        $period = $period->filter($filter);
    }

    return $period;
}

// Define your filters
$mondayFilter = function ($date) { return $date->isMonday(); };
$tuesdayFilter = function ($date) { return $date->isTuesday(); };

// Optionally, pass in your filter.
$period = createARandomDateBetweenRange('2001-01-01', '2001-12-31', $tuesdayFilter);

$period = $period->toArray();

var_dump(
    $period[array_rand($period)]
);
waterloomatt
  • 3,662
  • 1
  • 19
  • 25
0

Maybe instead of all that Carbon you could try this? I have just written this on-the-fly but it appears to work well. Hopefully it will give you some ideas.

Basically, it finds the first matching day in the range, then works out how many full weeks fit from that point 'til the end and uses that number for the random part.

// The Function
function nextRandomDay($dayLabel,$from,$to){
    $i=0;
    while(date("l",$from) != $dayLabel && $i<10){
        $i++;
        $from = strtotime("NOW + 1 day",$from);
    }
    if($i>8){return false;} // Invalid day label
    return strtotime("NOW + ".rand(0,floor(($to-$from) / (86400*7)))." weeks",$from);
}

// EXAMPLE
$from   = time(); // Where to start looking from
$to     = strtotime("NOW + 71 days"); // When to stop looking
$day    = "Tuesday"; // Full string day name

if($myDate = nextRandomDay($day,$from,$to)){
    echo "Found a '$day' on ".date("d/m/Y",$myDate)." ($myDate)";
}
Watts Epherson
  • 692
  • 5
  • 9