PHP: Overuse of date manipulation leading to convoluted code I despise playing with dates in PHP so no doubt the below is too convoluted for what is needed. What I am looking for is a general tidy/reduction.

Everything but the wednesday and friday arrays are in a loop. The loop is from a ROQL statement. Oracle SQL for it's RightNow product, which is a very very stripped down version of MySQL from what I understand, meaning we are limited to basic SELECT statements i.e. we can't do anything worthwhile there.


$inc['order_date'] is a string representing a date in the format yyyymmdd
$inc['order_dispatch_date'] is a string representing a date in the format yyyymmdd
$inc['order_address'] is a string representing an address


So the basics of the code is:


Loop through each row in the database
Convert some dates
If the order address in the database is in the wednesday array, set the collection date to the Thursday after
If the order address in the database is in the friday array, set the collection date to the Saturday after
Do some more date conversion/manipulation
END GOAL: Get the difference in days between the order_date and the collection_date


CODE

$wednesday = array("Paris","London","New York");
$friday = array("Munich", "Cardiff", "Sydney"); 

$res = RNCPHP\ROQL::query( "SQL QUERY HERE")-&gt;next();
while($inc = $res-&gt;next()) {        

    $order_date = DateTime::createFromFormat('Ymd', $inc['order_date']);
    $order_date = $order_date-&gt;format('Ymd');

    $order_dispatch_date = DateTime::createFromFormat('Ymd', $inc['order_dispatch_date']);
    $order_dispatch_date = $order_dispatch_date-&gt;format('Ymd');

    if (in_array($inc['order_address'], $wednesday)) {
        $order_collection = date('Ymd', strtotime('next thursday', strtotime($order_dispatch_date)));
    }
    if (in_array($inc['order_address'], $friday)) {
        $order_collection = date('Ymd', strtotime('next saturday', strtotime($order_dispatch_date)));
    }

    $order_collection = new DateTime($order_collection); 
    $order_date   = new DateTime($order_date);

    $interval = $order_date-&gt;diff($order_collection);
    $interval = $interval-&gt;d;
}


FIRST REVISION

if (in_array($inc['order_address'], $wednesday)) {
    $order_collection = new DateTime(date('Ymd', strtotime('next thursday', strtotime($inc['order_dispatch_date']))));
}
if (in_array($inc['order_address'], $friday)) {
    $order_collection = new DateTime(date('Ymd', strtotime('next saturday', strtotime($inc['order_dispatch_date']))));
}

$order_date = new DateTime(date('Ymd', strtotime($inc['order_date'])));
$interval = $order_date-&gt;diff($order_collection)-&gt;d;
I'll provide a snippet with some sample data to demonstrate a few of my suggested techniques.

Code: (Demo)

$incs=[
    ['order_date'=&gt;'20171128','order_dispatch_date'=&gt;'20171129','order_address'=&gt;'Paris'],
    ['order_date'=&gt;'20171128','order_dispatch_date'=&gt;'20171129','order_address'=&gt;'Munich'],
    ['order_date'=&gt;'20171129','order_dispatch_date'=&gt;'20171130','order_address'=&gt;'London'],
    ['order_date'=&gt;'20171129','order_dispatch_date'=&gt;'20171130','order_address'=&gt;'Cardiff'],
    ['order_date'=&gt;'20171130','order_dispatch_date'=&gt;'20171201','order_address'=&gt;'New York'],
    ['order_date'=&gt;'20171130','order_dispatch_date'=&gt;'20171201','order_address'=&gt;'Sydney']
];

$wednesday = array("Paris","London","New York");

foreach($incs as $inc){
    $order_date = DateTime::createFromFormat('Ymdhis', $inc['order_date'].'000000');
    $day_name = in_array($inc['order_address'], $wednesday) ? 'Thursday' : 'Saturday';
    $order_collection = new DateTime($adj_date=date('Y-m-d 00:00:00', strtotime("next $day_name {$inc['order_dispatch_date']}")));

    $interval = $order_date-&gt;diff($order_collection)-&gt;d;
    echo "\n{$inc['order_date']} - $adj_date = $interval";
}


Output:

20171128 - 2017-11-30 00:00:00 = 2
20171128 - 2017-12-02 00:00:00 = 4
20171129 - 2017-12-07 00:00:00 = 8
20171129 - 2017-12-02 00:00:00 = 3
20171130 - 2017-12-07 00:00:00 = 7
20171130 - 2017-12-02 00:00:00 = 2


Now for the fine points:


Because you state that every order_address is in the $wednesday or $friday array, then you should only be checking one of them for best efficiency.  This check will determine the day name that will be fed to strtotime() later.
When generating your DateTime objects, assign them zero-ed times.  This way php will not default them to the "current time" for the given date.  Performing this declaration will avoid getting deviations in the diff() value later.
strtotime() will correctly interpret your Ymd format, so no additional string preparation is necessary.
The syntax for your strtotime() call is a single parameter with next $day_nameand$inc['order_dispatch_date']` all in a single string.
You can sensibly save a line of code by chaining -&gt;d to your $interval declaration.


Here is how I think your new code should look:

$wednesday = array("Paris","London","New York");

$res = RNCPHP\ROQL::query( "SQL QUERY HERE")-&gt;next();
while($inc = $res-&gt;next()) {        

    $order_date = DateTime::createFromFormat('Ymdhis', $inc['order_date'].'000000');
    $day_name = in_array($inc['order_address'], $wednesday) ? 'Thursday' : 'Saturday';
    $order_collection = new DateTime(date('Y-m-d 00:00:00', strtotime("next $day_name {$inc['order_dispatch_date']}")));

    $interval = $order_date-&gt;diff($order_collection)-&gt;d;
}