skip to Main Content

I am trying to show the hours and minutes remaining from the current time and 13:00/1pm.

We have two conditions:

  1. If the current hour is < 13:00 (1 pm), the delivery is 7 weekdays and the user is shown how much time is left until the 1 pm deadline (e.g. 1 hour 22 minutes at 11:38).

  2. If the current hour is > 13:00 (1 pm), the delivery is 8 weekdays and the user should be shown how much time is left until the next day at 1 pm (e.g. 23 hours 59 minutes at 13:01).

The second if-statement below shows nothing in the browser (html echo).

Prior to today reaching 13:00 (1 pm), the first if-statement worked and showed e.g. 2 hours remaining at 11:00 (11 am).

add_action( 'woocommerce_after_add_to_cart_form', 'delivery_info' );

function delivery_info() 
{
    date_default_timezone_set( 'Europe/London' );  

    // if 1 pm 
    if ( date('H') < 13 )  {
        $del_day = date( 'l jS F' , strtotime ( '7 weekdays' ) );
        
        $today = strtotime('today 13:00');
        $tomorrow = strtotime('tomorrow 13:00');
        $now = time();
        $timeLeft = ($now > $today ? $tomorrow : $today) - $now;
        $timeResult = (gmdate("H:i:s", $timeLeft));
        
        $hour = date('H', $timeLeft);
        $min = date('i', $timeLeft);
    } 
        
    // if after 1PM
    elseif ( date('H') > 13 )  {
        $del_day = date( 'l jS F' , strtotime ( '8 weekdays' ) );
        
        $today = strtotime('today 13:00');
        $tomorrow = strtotime('tomorrow 13:00');
        $now = time();
        $timeLeft = ($now > $today ? $tomorrow : $today) - $now;
        $timeResult = (gmdate("H:i:s", $timeLeft));
        
        $hour = date('H', $timeLeft);
        $min = date('i', $timeLeft);
    } 
     
    // HTML output
    echo <<<HTML
        <br>
        <div class="woocommerce-message est-delivery"
             style="white-space: pre-line;
                    text-align: left; 
                    display: inline-block;
                    ">
            <h4>Standard Delivery</h4>
            <br>
            <span style='color:#000000'>
                Order arrives <b>{$del_day}</b>,
            </span>
            <br/>
            <span style="color:#47bab5">
                order within {$hour}hrs {$min}mins
            </span>
        </div>
    HTML;
}

What have I done wrong? And is there a better way to achieve the above?

2

Answers


  1. Remove the elseif and use else instead, since there would be an hour of time (13:00:00 - 13:59:59) between < 13 and > 13.

    Additionally, the only code that needs to be in the condition is $del_day =, both of the other blocks are identical, and can be moved outside the if/else condition.

    function delivery_info() {
       date_default_timezone_set( 'Europe/London' );  
        
       if ( date('H') < 13 )  {
          // if before 1PM
          $del_time = strtotime( '7 weekdays' );
       } else {
          // if 1PM or later
          $del_time = strtotime( '8 weekdays' );
       } 
    
       $del_day = date( 'l jS F', $del_time);
       $today = strtotime('today 13:00');
       $tomorrow = strtotime('tomorrow 13:00');
       $now = time();
       $timeLeft = ($now > $today ? $tomorrow : $today) - $now;
       $timeResult = gmdate("H:i:s", $timeLeft);
         
       $hour = date('H', $timeLeft);
       $min = date('i', $timeLeft);
     
       echo "<br><div class='woocommerce-message est-delivery' style='white-space: pre-line;text-align:left;display: inline-block;'><h4>Standard Delivery</h4><br><span style='color:#000000'> Order arrives <b>{$del_day}</b>,</span><br/><span style='color:#47bab5'>order within {$hour}hrs {$min}mins</span></div>";
    }
    
    Login or Signup to reply.
  2. Prior to today reaching 13:00 (1 pm), the first if-statement worked and showed e.g. 2 hours remaining at 11:00 (11 am).

    What have I done wrong?

    There is indeed a mistake that manifests exactly when you reach 13:00 at that minute. If we zoom out on the if clauses:

        // if 1 pm 
        if ( date('H') < 13 )  {
            # ...
        } 
            
        // if after 1PM
        elseif ( date('H') > 13 )  {
            # ...
        } 
    

    We can see that the comments do not reflect the implementation. The first condition is correct according to your question "before 1 pm", but the comment is wrong because it tells "at 1 pm" (bold by me).

    As Will B. already suggested, you can use an if/else instead to not fall into the one hour (!) gap you have here.

    For the full 1 pm hour (13 o’clock), you would not do any calculation.

    And is there a better way to achieve the above?

    Certainly, there are always better ways, but the main point is that you get your code functional first. However, if I may give a couple of pointers:

    Current Time is an Input Parameter

    The current time is an input parameter to your routine, but you don’t make it explicitly visible.

    Better than relying on date() without the second parameter or time() (which is also implicitly the second parameter if you leave it out) at multiple places in between it changes, is to make the current date and time a DateTime object and work with it.

    Same like with calls to date_default_timezone_set(), better have the timezone explicitly with the time value already, not from the runtime environment.

    // Get the current day and time with a timezone
    $currentDateTime = date_create_immutable("@$_SERVER[REQUEST_TIME]")
        ->setTimezone(new DateTimeZone('Europe/London'));
    

    In the example PHP code, the variable $currentDateTime is set to the time of the request (similar to time(), but from the PHP SAPI, not the system/kernel) and then given the timezone you also have for display and calculation purposes.

    Not only has using a variable (parameter) now the benefit you always rely to the same time exactly, it also offers you to better handle changes (e.g. distributing functionality over different functions and methods).

    You also get the full interface of DateTime which includes range/distance calculation.

    You can also be more clever like: When this is about a minute that can make a difference, why not add one minute before doing the checks? The browser will need to send the reply and the user will need to read it and this all will take time, and if the precision is minutes, submitting the request at 12:59:59 will likely not have the order 13:00 (1 pm) any longer. Cf. "Adding minutes to date time in PHP".

    Also your main problem to format the distance in hours and minutes is possible, too, without re-inventing the wheel. Cf. "How to calculate the difference between two dates using PHP?"

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search