Search code examples
phparraysdatedate-rangehyphenation

Convert an array of datetimes into a comma-separated string of hyphenated range expressions


I have an array of performance dates for an event such as:

2014-01-20 20:00:00
2014-01-21 20:00:00
2014-01-22 14:00:00
2014-01-22 20:00:00
2014-01-23 20:00:00
2014-01-25 20:00:00
2014-01-26 20:00:00
2014-01-31 20:00:00
2014-02-01 20:00:00

Is there a straightforward way in php to turn this into a human-readable string such as;

20th-23rd Jan 8pm, 22nd Jan 2pm, 25th-26th Jan 8pm, 31st Jan - 1st Feb 8pm

Note the array will always be in datetime order, although not necessarily contiguous. Matinee performances throw in an extra complication as they need to be dealt with separately.


Solution

  • We’ll convert the strings to timestamps with array_map and strtotime and then group together the consecutive elements in the array which are in an Arithmetic Progression with common difference = 86400 (because 86400 seconds = 1 day):

    $arr = array(
        "2014-01-20 20:00:00",
        "2014-01-21 20:00:00",
        "2014-01-22 14:00:00",
        "2014-01-22 20:00:00",
        "2014-01-23 20:00:00",
        "2014-01-25 20:00:00",
        "2014-01-26 20:00:00",
        "2014-01-31 20:00:00",
        "2014-02-01 20:00:00"
    );
    $arr = array_map("strtotime", $arr);
    $_arr = array();
    $size = sizeof($arr);
    $val = $arr[0];
    for($i = 0; $i < $size; $i++){
        if(!array_key_exists($i+1, $arr) || $arr[$i+1]-$arr[$i] != 86400){
        $d1 = date("jS", $val);
        $d2 = date("jS", $arr[$i]);
        $m1 = date("M", $val);
        $m2 = date("M", $arr[$i]);
        $t = date("ga", $val);
            if($m1 == $m2){
                if($d1 == $d2){
                $_arr[] = $d1." ".$m1." ".$t;
                }
                else{
                $_arr[] = $d1."-".$d2." ".$m1." ".$t;
                }
            }
            else{
            $_arr[] = $d1." ".$m1."-".$d2." ".$m2." ".$t;
            }
            if(array_key_exists($i+1, $arr)){
            $val = $arr[$i+1];
            }
        }
    }
    print(implode(", ", $_arr));
    

    The output will be:

    20th-21st Jan 8pm, 22nd Jan 2pm, 22nd-23rd Jan 8pm, 25th-26th Jan 8pm, 31st Jan-1st Feb 8pm

    See the code at work here.