WFP Posted August 29, 2021 Share Posted August 29, 2021 (edited) Hi all - I've adapted & made some basic code to forecast a delivery date for my customers but needs a little refinement - can you help? Goals & Rules > All Sat, All Sunday & Friday after 2pm = orders will arrive Tuesday (shipped Monday and Arrive Tuesday) > Monday - Friday orders before 2pm will arrive the next day (posted on 'd' arrive d+1 includes Sat). > Monday - Thursday orders after 2pm will arrive in 2 days (posted on 'd+1' and arrive d+2) Feature to be added > Bank Holidays (enter an array of all bank holiday dates upfront which will extend the delivery as per the above rules) > My current server time does not seem to recoginse changes in GMT & BST. So, when the UK is in GMT its fine (2pm = 2pm) but when we move to BST the time is 3pm but the code is reading 2pm as server looks like its still in GMT. How can this be set automatically to the correct time in the UK without editing the code for BST / GMT every time. Code so Far if(preg_match('%(Sat|Sun)%', date('D'))){ $next_working_day = date('D dS M', strtotime('next Tuesday')); } else{ if (date('H') < 14) { $next_working_day = date('D dS M', strtotime('+1 day')); } /* --for late friday orders going Mon-- */ else{ if(preg_match('%(Fri)%', date('D'))){ $next_working_day = date('D dS M', strtotime('next Tuesday')); } else {$next_working_day = date('D dS M', strtotime('+2 day'));} } } echo $next_working_day; print '</strong></p><hr>'; } Edited August 29, 2021 by WFP Quote Link to comment https://forums.phpfreaks.com/topic/313621-easy-forecast-delivery-day-code/ Share on other sites More sharing options...
Barand Posted August 29, 2021 Share Posted August 29, 2021 Check your default timezone setting in your php.ini file. Sounds like it's set to UTC or GMT instead of Europe/London. You can check with echo date_default_timezone_get(); $now = new DateTime(); // using default timezone echo $now->format('H:i:s T') . '<br>'; // 17:05:29 BST $now->setTimezone(new DateTimeZone('UTC')); echo $now->format('H:i:s T') . '<br>'; // 16:05:29 UTC Quote Link to comment https://forums.phpfreaks.com/topic/313621-easy-forecast-delivery-day-code/#findComment-1589448 Share on other sites More sharing options...
Barand Posted August 29, 2021 Share Posted August 29, 2021 1 hour ago, WFP said: enter an array of all bank holiday dates upfront No need to do that when you can calculate them... function bankHols($yr) { // CALC PUBLIC HOLS FOR $yr $hols = array(); $newyr = "$yr-01-01"; switch (date('w', strtotime($newyr))) { case 6: $newyr = "{$yr}-01-03"; break; case 0: $newyr = "{$yr}-01-02"; break; } $hols['New Year'] = $newyr; $easter = easter_date($yr); $hols['Easter'] = array(date('Y-m-d', strtotime('-2 days', $easter)), date('Y-m-d', strtotime('+1 days', $easter))); $mayday = (new DateTime("first monday of may $yr"))->format('Y-m-d'); $hols['May Day'] = $mayday; $sbank = (new DateTime("last monday of may $yr"))->format('Y-m-d'); $hols['Spring Bank'] = $sbank; $abank = (new DateTime("last monday of august $yr"))->format('Y-m-d'); $hols['August Bank'] = $abank; $x1 = "$yr-12-25"; $x2 = "$yr-12-26"; switch (date('w', strtotime($x1))) { case 5: $x2 = "$yr-12-28"; break; case 6: $x1 = "$yr-12-27"; $x2 = "$yr-12-28"; break; case 0: $x1 = "$yr-12-26"; $x2 = "$yr-12-27"; break; } $hols['Christmas'] = array($x1,$x2); return $hols; } $holidays = bankHols(2021); 1 Quote Link to comment https://forums.phpfreaks.com/topic/313621-easy-forecast-delivery-day-code/#findComment-1589449 Share on other sites More sharing options...
WFP Posted August 29, 2021 Author Share Posted August 29, 2021 (edited) ok great yes server was set in UTC, its on wordpress and even with settings set to london it was still returning UTC. So i added before my script the below which works fine now so 1 problem fixed date_default_timezone_set("Europe/London"); Ref the bank hols Amazing little tip there, spoon feeding abit here but im still learning at my limits - how can i integrate your function into my initial loop? p.s. I am also from cheshire UK! Edited August 29, 2021 by WFP Quote Link to comment https://forums.phpfreaks.com/topic/313621-easy-forecast-delivery-day-code/#findComment-1589451 Share on other sites More sharing options...
Solution Barand Posted August 29, 2021 Solution Share Posted August 29, 2021 (edited) 4 hours ago, WFP said: - how can i integrate your function into my initial loop? I'd revise the function so it just gave a plain array of dates, then nudge the delivery by a day if the due date is the holiday array. So array is ... Array ( [0] => 2021-01-01 [1] => 2021-04-02 [2] => 2021-04-05 [3] => 2021-05-03 [4] => 2021-05-31 [5] => 2021-08-30 [6] => 2021-12-25 [7] => 2021-12-26 [8] => 2021-12-27 [9] => 2021-12-28 ) My solution: (If you don't want to be spoon-fed, ignore) $hols = bankHols(date('Y')); $test_dates = [ '2021-08-30 14:00', '2021-08-30 14:01', '2021-08-31 14:00', '2021-08-31 14:01', '2021-09-01 14:00', '2021-09-01 14:01', '2021-09-02 14:00', '2021-09-02 14:01', '2021-09-03 14:00', '2021-09-03 14:01', '2021-09-04 14:00', '2021-09-04 14:01', '2021-09-05 14:00', '2021-09-05 14:01', '2021-03-30 14:00', '2021-03-30 14:01', '2021-03-31 14:00', '2021-03-31 14:01', '2021-04-01 14:00', '2021-04-01 14:01', '2021-04-02 14:00', '2021-04-02 14:01', '2021-04-03 14:00', '2021-04-03 14:01', '2021-04-04 14:00', '2021-04-04 14:01', '2021-12-23 14:00', '2021-12-23 14:01', '2021-12-24 14:00', '2021-12-24 14:01' ]; echo '<pre>'; foreach ($test_dates as $d) { $ordered = new dateTime($d); echo 'Ordered: ' . $ordered->format('D d M g:i a') ; $del = deliveryDate($ordered, $hols); echo ' — Delivery: ' . $del->format('D') . '<br>'; } echo '</pre>'; function deliveryDate($ordered, $hols) { $delivery = clone $ordered; if ($delivery->format('H:i') > '14:00') { // if it's after 2pm. treat is as the next day $delivery->modify('+1 day'); } if (in_array($delivery->format('w'), [0,6])) { // if it's Sat or Sun, treat it as Monday $delivery->modify('next monday'); } do { // add a day for delivery until the date isn't a holiday. $delivery->modify('+1 day'); } while (in_array($delivery->format('Y-m-d'), $hols)); return $delivery; } function bankHols($yr) { // CALC PUBLIC HOLS FOR $yr $dates = array(); $newyr = "$yr-01-01"; switch (date('w', strtotime($newyr))) { case 6: $newyr = "{$yr}-01-03"; break; case 0: $newyr = "{$yr}-01-02"; break; } $dates[] = $newyr; $easter = easter_date($yr); array_push($dates, date('Y-m-d', strtotime('-2 days', $easter)), date('Y-m-d', strtotime('+1 days', $easter))); $mayday = (new DateTime("first monday of may $yr"))->format('Y-m-d'); $dates[] = $mayday; $sbank = (new DateTime("last monday of may $yr"))->format('Y-m-d'); $dates[] = $sbank; $abank = (new DateTime("last monday of august $yr"))->format('Y-m-d'); $dates[] = $abank; $x1 = "$yr-12-25"; $x2 = "$yr-12-26"; array_push($dates, $x1, $x2); switch (date('w', strtotime($x1))) { case 5: $x2 = "$yr-12-28"; break; case 6: $x1 = "$yr-12-27"; $x2 = "$yr-12-28"; break; case 0: $x1 = "$yr-12-26"; $x2 = "$yr-12-27"; break; } array_push($dates, $x1, $x2); return $dates; } Edited August 29, 2021 by Barand Quote Link to comment https://forums.phpfreaks.com/topic/313621-easy-forecast-delivery-day-code/#findComment-1589452 Share on other sites More sharing options...
WFP Posted August 30, 2021 Author Share Posted August 30, 2021 thank you! very helpful indeed i would not have been able to join all the dots together like that Quote Link to comment https://forums.phpfreaks.com/topic/313621-easy-forecast-delivery-day-code/#findComment-1589456 Share on other sites More sharing options...
Barand Posted August 30, 2021 Share Posted August 30, 2021 (edited) Be aware that on Friday 3 June, 2022 there is an extra "Jubilee" bank holiday for that year only and the May 30 (Monday) spring bank holiday moves to the following Thursday (June 2). After the line $hols = bankHols(date('Y')); add // Adjust for 2022 only $spring = array_search('2022-05-30', $hols); if ($spring) { $hols[$spring] = '2022-06-02'; // revise date $hols[] = '2022-06-03'; // add Jubilee hol } Edited August 30, 2021 by Barand Quote Link to comment https://forums.phpfreaks.com/topic/313621-easy-forecast-delivery-day-code/#findComment-1589461 Share on other sites More sharing options...
WFP Posted September 1, 2021 Author Share Posted September 1, 2021 hi there - after a few hours of trying tonight I am struggling to integrate the code for my final result of outputting the code as Add to Basket now for FREE Delivery to you (est.) : Fri 03rd Sep So i assume I dont need the 'test dates' var and I can instead use the $dates but I'm missing something to link them together as below it outputs Add to Basket now for FREE Delivery to you (est.) : (<-nothing returned) $hols = bankHols(date('Y')); foreach ($dates as $d) { $ordered = new dateTime($d); $del = deliveryDate($ordered, $hols); } function deliveryDate($ordered, $hols) { $delivery = clone $ordered; if ($delivery->format('H:i') > '14:00') { // if it's after 2pm. treat is as the next day $delivery->modify('+1 day'); } if (in_array($delivery->format('w'), [0,6])) { // if it's Sat or Sun, treat it as Monday $delivery->modify('next monday'); } do { // add a day for delivery until the date isn't a holiday. $delivery->modify('+1 day'); } while (in_array($delivery->format('Y-m-d'), $hols)); return $delivery; } function bankHols($yr) { // CALC PUBLIC HOLS FOR $yr $dates = array(); $newyr = "$yr-01-01"; switch (date('w', strtotime($newyr))) { case 6: $newyr = "{$yr}-01-03"; break; case 0: $newyr = "{$yr}-01-02"; break; } $dates[] = $newyr; $easter = easter_date($yr); array_push($dates, date('Y-m-d', strtotime('-2 days', $easter)), date('Y-m-d', strtotime('+1 days', $easter))); $mayday = (new DateTime("first monday of may $yr"))->format('Y-m-d'); $dates[] = $mayday; $sbank = (new DateTime("last monday of may $yr"))->format('Y-m-d'); $dates[] = $sbank; $abank = (new DateTime("last monday of august $yr"))->format('Y-m-d'); $dates[] = $abank; $x1 = "$yr-12-25"; $x2 = "$yr-12-26"; array_push($dates, $x1, $x2); switch (date('w', strtotime($x1))) { case 5: $x2 = "$yr-12-28"; break; case 6: $x1 = "$yr-12-27"; $x2 = "$yr-12-28"; break; case 0: $x1 = "$yr-12-26"; $x2 = "$yr-12-27"; break; } array_push($dates, $x1, $x2); return $dates; } echo 'Add to Basket now for FREE Delivery to you (est.) : ' . $delivery ; Quote Link to comment https://forums.phpfreaks.com/topic/313621-easy-forecast-delivery-day-code/#findComment-1589570 Share on other sites More sharing options...
Barand Posted September 1, 2021 Share Posted September 1, 2021 Where is $dates defined? If you are "adding to basket now..." then you only need the current date $ordered = new DateTime(); echo deliveryDate($ordered, $hols)->format('D jS M'); Quote Link to comment https://forums.phpfreaks.com/topic/313621-easy-forecast-delivery-day-code/#findComment-1589572 Share on other sites More sharing options...
WFP Posted September 1, 2021 Author Share Posted September 1, 2021 seems to be working thanks! Quote Link to comment https://forums.phpfreaks.com/topic/313621-easy-forecast-delivery-day-code/#findComment-1589573 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.