phpdatetimerandom-data

Generate random date excluding Sundays


A bit similar to this one, yet different.

I need to generate two random dates:

I am doing this like that:


$createDate = new DateTime();
$updateDate = new DateTime();

$createDate
    ->setTimestamp(rand($startDate, $endDate))
    ->setTime(rand($startHour, $endHour), rand(0, 59), rand(0, 59));

$updateDate
    ->setTimestamp(rand($createDate->getTimestamp(), $endDate))
    ->setTime(rand($startHour, $endHour), rand(0, 59), rand(0, 59));

How to modify the above code to assure that both createDate and updateDate does not fall on Sunday?

As you can figure out from the above code, the $startDate and $endDate are integers and contains timestamps. The $startHour and $endHour are also integers, but contains pure hour numeral only.


Solution

  • How to modify the above code to assure that both createDate and updateDate does not fall on Sunday?

    I modify your code to this:

    $createDate = new DateTime();
    $updateDate = new DateTime();
    
    do {
       $createDate
           ->setTimestamp(rand($startDate, $endDate))
           ->setTime(rand($startHour, $endHour), rand(0, 59), rand(0, 59));
    } while ($createDate->format('N') == 7); // Repeat until createDate is not a Sunday
    
    do {
       $updateDate
           ->setTimestamp(rand($createDate->getTimestamp(), $endDate))
           ->setTime(rand($startHour, $endHour), rand(0, 59), rand(0, 59));
    } while ($updateDate->format('N') == 7); // Repeat until updateDate is not a Sunday
    

    Here, I used do...while loop to keep generating a random date until the generated date is not a Sunday. The format('N') is used to returns the day of the week as an integer, and 7 represents Sunday. The loop will continue until format('N') does not return 7, ensuring that the generated date is not a Sunday*.

    *Note that this may be inefficient if the range of dates between $startDate and $endDate includes many Sundays, as it may take several iterations to find a date that is not a Sunday. In such, you may want to consider generating a list of all weekdays within the date range and then randomly selecting from that list, as answered by @waterloomatt here.

    Additional

    Generally "random" + "loop" = "infinite loop, or at least takes forever sometimes"

    Add counter for a maximum number of attempts to prevent the loop from running indefinitely.

    $createDate = new DateTime();
    $updateDate = new DateTime();
    
    $maxAttempts = 1000; // Maximum number of attempts to generate a non-Sunday date
    $attempts = 0; // Counter for the number of attempts
    
    do {
       $createDate
           ->setTimestamp(rand($startDate, $endDate))
           ->setTime(rand($startHour, $endHour), rand(0, 59), rand(0, 59));
       $attempts++;
    } while ($createDate->format('N') == 7 && $attempts < $maxAttempts); // Repeat until createDate is not a Sunday
    
    $attempts = 0; // Reset the counter for the next date
    
    do {
       $updateDate
           ->setTimestamp(rand($createDate->getTimestamp(), $endDate))
           ->setTime(rand($startHour, $endHour), rand(0, 59), rand(0, 59));
       $attempts++;
    } while ($updateDate->format('N') == 7 && $attempts < $maxAttempts); // Repeat until updateDate is not a Sunday
    

    *The above may still has a possibility of infinite loop if the range of possible dates only includes Sundays and the maximum number of attempts is reached, so you could add additional logic to adjust the range of possible dates or handle the case where no non-Sunday dates are available.