I'm trying to find the next epoch date from a relative day/time (work shift).
foreach($shift->meta_value as $shift_day) {
$start_string = $shift_day['day'] . ' ' . $shift_day['start_hour'] . ':' . $shift_day['start_min'] . $shift_day['start_meridian'];
$showStart[$shift->post_id] = date('U', strtotime($start_string));
$end_string = $shift_day['day'] . ' ' . $shift_day['end_hour'] . ':' . $shift_day['end_min'] . $shift_day['end_meridian'];
$showEnd[$shift->post_id] = date('U', strtotime($end_string));
}
asort($showEnd);
$end = array();
foreach ($showEnd as $key => $val) {
if (date("U", $val) > date("U")) {
$end[$key] = $val;
}
asort($end);
If the day/time has already passed, it needs to find the next occurrence of it. When sorting the 'end' array, it's not giving me the correct value. Any ideas?
Related
I have a query which returns me some data.
//I loop through the query's result and write all data out
while($row =$result->fetch_assoc()){
echo $row['place'] . '|';
echo $row['gets_busy'] . '|';
echo $row['gets_empty '] . '|';
echo $row['time_between'] . '|';
echo "<br>";
}
ROOM01|2021-03-05 12:02:56|2021-03-05 12:04:02|00:01:06|
ROOM01|2021-03-05 12:05:42|2021-03-05 12:07:48|00:02:06|
ROOM01|2021-03-05 12:07:48|2021-03-05 12:12:54|00:05:06|
ROOM02|2021-03-05 12:15:54|2021-03-05 12:17:00|00:01:06|
ROOM02|2021-03-05 12:17:01|2021-03-05 12:23:17|00:05:16|
ROOM02|2021-03-05 12:23:59|2021-03-05 12:25:45|00:01:46|
I want something to write for the user like:
ROOM01 was busy for -> 00:08:18 during 2021-03-05
ROOM02 was busy for -> 00:08:08 during 2021-03-05
Can this be accomplished by PHP?
You can group into another array, by using the places and date as keys.
while($row = $result->fetch_assoc())
{
$place = $row['place']; // shortcut
$start = strtotime($row['gets_busy']); // start timestamp
$stop = strtotime($row['gets_empty']); // end timestamp
$time = $stop - $start; // duration in seconds
$date = date('Y-m-d', $start); // date for grouping
// group by place and date
if (!isset($data[$place][$date])) {
$data[$place][$date] = 0; // init with 0
}
$data[$place][$date] += $time; // add time.
}
// now, display data :
foreach ($data as $place => $dates) {
echo $place . ':<br>';
foreach ($dates as $date => $duration) {
$interval = new DateInterval('PT'.$duration.'S');
echo ' -> ' . $date . ' : ' . $interval->format('%h:%i:%s') . '<br>';
}
}
I don't know what are the errors of this code because it's suddenly not accurate the showing value to the user like this:
$holidays = array();
$query_holiday = "SELECT * FROM holiday_tbl";
$result = mysqli_query($dbcon, $query_holiday);
while($row_holiday = mysqli_fetch_assoc($result))
{
array_push($row_holiday, $holidays);
}
if(strtotime(date("Y-m-d")) > strtotime($row['due_date']))
{
$currentDate = date("Y-m-d");
$days = (strtotime($currentDate) - strtotime($row['due_date'])) / 86400;
$daysTemp = $days;
for($i=1;$i<$days;$i++)
{
$currentDay = date("D", strtotime("+ ".$i." days"));
$date_loop = date("Y-m-d", strtotime("+ ".$i." days"));
if($currentDay == "Sun" || $currentDay == "Sat")
{
$daysTemp--;
}
else if(in_array($date_loop, $holidays))
{
$daysTemp--;
}
}
echo $daysTemp;
}
The current implementation is rather convoluted. In these cases I find it's always better to start over and try to simplify the logic as much as possible. Here is my take on your problem:
function calculate_days_late($due_date = '', $holidays = array(), $current_date = 'today') {
$days_late = 0;
// Get the timestamps for due date and current date
$current_date_ts = strtotime($current_date);
$due_date_ts = strtotime($due_date);
// If current date is not after due date then not late
if ($current_date_ts <= $due_date_ts) {
return $days_late;
}
$loop_date_ts = $current_date_ts;
while ($loop_date_ts > $due_date_ts) {
// If the looping date is not a weekend or holiday then count it
if ( ! in_array(date('D', $loop_date_ts), array('Sat','Sun'))
&& ! in_array(date('Y-m-d', $loop_date_ts), $holidays)) {
$days_late++;
}
$loop_date_ts = strtotime('-1 day', $loop_date_ts);
}
return $days_late;
}
// Test
echo '2017-09-05 = ' . calculate_days_late('2017-09-05', array(), '2017-09-05') . "\n";
echo '2017-09-06 = ' . calculate_days_late('2017-09-05', array(), '2017-09-06') . "\n";
echo '2017-09-07 = ' . calculate_days_late('2017-09-05', array(), '2017-09-07') . "\n";
echo '2017-09-08 = ' . calculate_days_late('2017-09-05', array(), '2017-09-08') . "\n";
echo '2017-09-09 = ' . calculate_days_late('2017-09-05', array(), '2017-09-09') . "\n";
echo '2017-09-10 = ' . calculate_days_late('2017-09-05', array(), '2017-09-10') . "\n";
echo '2017-09-11 = ' . calculate_days_late('2017-09-05', array(), '2017-09-11') . "\n";
echo '2017-09-12 = ' . calculate_days_late('2017-09-05', array(), '2017-09-12') . "\n";
echo '2017-09-13 = ' . calculate_days_late('2017-09-05', array(), '2017-09-13') . "\n";
Working example: https://eval.in/856018
I have an interactive map application I am building and the database is relatively small at about 11mb. However it has a lot of rows of data the require me to go through sort them into counties and years.
My page load speeds are about 10-11 seconds trying to go through all of this data and get it organized so that I can then load it with a javascript library called mapael.
I need some help trying to get the page load speeds faster if there is any way to do that. The query doesn't really seem to be the problem. It's more the going through the data that I believe is causing the problem.
<?php
$mydb = new wpdb('uofimap_data','ob2UoV2X5tNz','uofimap_data','localhost');
$data = $mydb->get_results('
SELECT state,county,ship_date,total_cost, quantity FROM data
ORDER BY county ASC, ship_date ASC
');
$dataArray = array(
2006 => '',
2007 => '',
2008 => '',
2009 => '',
2010 => '',
2011 => '',
2012 => '',
2013 => '',
2014 => '',
);
$prevCounty = null;
$prevState = null;
$prevYear = null;
$countySum = null;
$quantitySum = null;
foreach ($data as $obj) :
//temp array to push everything into dataArray for year structure and keep all data in tact.
$tempArray = array();
//all the information to use for use
$date = date('Y', strtotime($obj->ship_date));
$state = $obj->state;
$county = $obj->county;
$cost = $obj->total_cost;
$quantity = $obj->quantity;
//Print only the needed values which is the sums of that county for that particular year.
if($prevCounty == $county){
if($prevYear == $date){
} else {
array_push($tempArray, $prevCounty, $prevState, $countySum, $quantitySum);
$dataArray[$prevYear][] = $tempArray;
}
} else {
if($prevCounty == null){
//Only needed if first value in database is a solo county / year.
//echo $county . ', ' . $state . ' : ' . $cost . ' ' . $date . ' New Null<br>';
} else {
array_push($tempArray, $prevCounty, $prevState, $countySum, $quantitySum);
$dataArray[$prevYear][] = $tempArray;
}
}
//Set everything
if($prevCounty == $county){
if($prevYear == $date){
$countySum += $cost;
$quantitySum += $quantity;
//echo $county . ' ' . $countySum . ' '. $state . ' ' . $date . ' ' . $quantitySum . ' Previous Year<br>';
} else {
$countySum = $cost;
$quantitySum += $quantity;
//echo $county . ' ' . $countySum . ' '. $state . ' ' . $date . ' ' . $quantitySum . ' Current Year<br>';
}
} else {
$countySum = $cost;
$quantitySum = $quantity;
//echo $county . ' ' . $countySum . ' '. $state . ' ' . $date . ' ' . $quantitySum . ' New County <br>';
}
$prevCounty = $county;
$prevState = $state;
$prevYear = $date;
endforeach;
$mapaelJson = '<script type="text/javascript">';
$mapaelJson .= 'data={';
foreach($dataArray as $key => $value){
$mapaelJson .= '"' . $key . '": {';
$mapaelJson .= '"areas":{';
foreach($value as $key1 => $value1){
$county = $value1[0];
$county = ucwords(strtolower($county));
$state = $value1[1];
$total = $value1[2];
$quantity = $value[3];
//var_dump($value1);
$mapaelJson .= '"'.$county . ', '. $state . '" : {';
$mapaelJson .= '"county" : "' . $county . '",';
$mapaelJson .= '"value" : "' . $total . '",';
$mapaelJson .= '"quantity" : "' . $quantity . '",';
$mapaelJson .= '},';
}
$mapaelJson .= '} },';
}
$mapaelJson .= '};</script>';
echo $mapaelJson;
?>
Have you looked into profilers? If you could create traces using the free version of Blackfire.io or cachegrind files using xdebug that would give you the best ideas to optimise.
Anyhow, for the time being you definitely need to reduce the number of loops and inner loops. Also, as much as you can, try having less indentations (keep the number of level low for more readability). You can use continue quite often in loops, it generally helps.
I am testing the contents of the array, $list, I will return as I cycle through these recursive function calls.
There is a hard limit of 25 records to be fetched at a time.
On calls where the result set is equal to the limit I increment an offset and recurse sending the current array of results as an argument.
From inside these loops I dump the $list var and other details into an email indicating whether recursing or returning and the current counts and a dump of the $list array.
These emails contain exactly what I expect numbers-wise and in $list.
The calling script however seems to get a different $list containing only the last loop. In cases where the result set is over 25 $list is empty. If the whole set is under 25 it is correct in the calling script output.
Can someone please straighten me out on why $list seems different inside the function than it is after it returns?
Calling script:
$levels = get_membership_levels();
if ($levels) {
foreach ($levels as $l) {
echo "<h2>$l</h2>\n";
$members = get_current_members_by_level($l);
echo '<h2>' . count($members) . '</h2>';
Function:
function get_current_members_by_level($level, $offset = 0, $list = array()) {
require_once $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/civicrm/civicrm.settings.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/civicrm/civicrm/CRM/Core/Config.php';
$config = CRM_Core_Config::singleton( );
require_once $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/civicrm/civicrm/api/api.php';
$result = civicrm_api3('Membership', 'get', array(
'membership_type_id' => "$level",
'limit' => 1000,
'offset' => $offset,
'api.Contact.get' => array(array('limit' => 1000, 'sort' => 'last_name')),
));
if ($result['values']) {
foreach ($result['values'] as $k => $v) {
$member = get_member($v['contact_id']);
if ($member) {
$list[]= $member;
}
}
if (count($result['values']) >= 25) {
$offset+= 25;
mail('email#example.com', "Recursing for $level - current set= " . count($result['values']) . ' Total: ' . count($list) . ' Offset= ' . $offset,print_r($list,1));
get_current_members_by_level($level, $offset, $list);
} else {
mail('email#example.com', "Returning result for $level - current set= " . count($result['values']) . ' Total: ' . count($list) . ' Offset= ' . $offset,print_r($list,1));
return $list;
}
}
}
I think the problem in your code is that you dont use the return or your function get_current_members_by_level();
if (count($result['values']) >= 25) {
$offset+= 25;
mail('email#example.com', "Recursing for $level - current set= " . count($result['values']) . ' Total: ' . count($list) . ' Offset= ' . $offset,print_r($list,1));
get_current_members_by_level($level, $offset, $list); // this function return the list but you dont use it.
} else {
mail('email#example.com', "Returning result for $level - current set= " . count($result['values']) . ' Total: ' . count($list) . ' Offset= ' . $offset,print_r($list,1));
return $list;
}
this should be instead
if (count($result['values']) >= 25) {
$offset+= 25;
mail('email#example.com', "Recursing for $level - current set= " . count($result['values']) . ' Total: ' . count($list) . ' Offset= ' . $offset,print_r($list,1));
$list = get_current_members_by_level($level, $offset, $list); // now the new list will be in the var $list
} else {
mail('email#example.com', "Returning result for $level - current set= " . count($result['values']) . ' Total: ' . count($list) . ' Offset= ' . $offset,print_r($list,1));
return $list;
}
strtotime seems to be outputting empty string instead of returning the timestamp for mm/dd/yy. I am having a hard time understanding what this wouldn't work?
The output for the following PHP is:
echo "'" . $month . "/" . $day . "/" . $year . "'"; // '7/22/86'
Isn't strtotime('7/22/86') a valid input for the function?
PHP
$month = 7;
$day = 22;
$year = 86;
$unix_time_stamp = strtotime("'" . $month . "/" . $day . "/" . $year . "'");
echo $unix_time_stamp;
I appreciate any advice in this regard.
Many thanks in advance!