yii highcharts how to set date format in x-axis - php

I have a line graph and I am trying to set date format in x-axis but it display time instead.
$this->Widget('ext.highcharts.HighchartsWidget', array(
'options'=>array(
'type'=>'spline',
'title' => array('text' => 'Project Report'),
'xAxis' => array(
'type'=> 'datetime',
'dateTimeLabelFormats'=>array( // don't display the dummy year
'month'=> '%e %b',
'year'=> '%y'
),
),
'yAxis' =>array(
'title' => array('text' => 'Percent %'),
'min'=>0,
'max'=>100
),
'series' =>$series['series']
)
));
This displays the following picture
My series array:
$date_from = date("Y, m, d",strtotime($data->StartDATE) - 2*86400);
$date_to = date("Y, m, d",strtotime($data->ProjectEndDate) + 2*86400);
$series['series'][] = array("name"=>$data->PROJECT,"data"=>array(array($date_from,0),array( date("Y, m, d",strtotime( date('Y-m-d') + + 2*86400) ) ,(int) 30),array( $date_to ,100 ))) ;
The output of this array is: Array ( [name] => Fastnet OffshWest Shetland [data] => Array ( [0] => Array ( [0] => 2013, 06, 09 [1] => 0 ) [1] => Array ( [0] => 2013, 06, 20 [1] => 30 ) [2] => Array ( [0] => 2013, 12, 13 [1] => 100 ) ) )
I have also tried
$date_from = gmdate('d.m.Y H:i', strtotime($data->StartDATE) );
$date_to = gmdate('d.m.Y H:i', strtotime($data->ProjectEndDate));
$series['series'][] = array("name"=>$data->PROJECT,"data"=>array(array($date_from,0),array( gmdate('d.m.Y H:i', strtotime( date('Y-m-d') ) ) ,(int) 30),array( $date_to ,100 ))) ;
Does not work either
Here is an example of what I want, however I am missing the enddate information. It is a gant chart. I would also like to include the enddate. Currently shows percentage complete from startdate. I also want to show how much it should be complete using current date in another color if possible.

As I already said, you have to use timestamps for your series :
$date_from = (strtotime($data->StartDATE) - 2*86400)*1000;
$date_to = (strtotime($data->ProjectEndDate) + 2*86400)*1000;
$series['series'][] = array(
"name"=> $data->PROJECT,
"data"=> array(
array(
$date_from,
0
),
array(
(time() + 2*86400))*1000 ,
30,
array(
$date_to,
100
)
)
) ;
Multiply by 1000 for javascript.

Highcharts requires timestamp as x-value to show dates on xAxis. So instead od 2013, 06, 09 should be 1373328000000 (number).

Related

How to get only holiday date from date array

I'm trying to make a holiday array, it is based on work_day.
For example is if in 1 group there's only day 1-2 (sunday-monday), then the other day (tuesday-saturday) is holiday. And based on that days, I want to get a holiday date array from start of the year until now.
I have a table like this:
attendance_group_id | day
GROUP-001 | 1
GROUP-001 | 2
GROUP-002 | 1
GROUP-003 | 1
What I've done first is getting all data from work_day table using code bellow:
foreach ($group_work_hour as $hours) {
foreach ($hours as $hour){
$work_day = (object) array();
$work_day->group_id = $hour->attendance_group_id;
$work_day->day = $hour->day;
$work_day_arr[] = $work_day;
}
}
And the result from code above is like bellow, every group can have day up to 7 day (1-7). 1 for sunday and 7 for saturday.
Array work day
array (
0 =>
(object) array(
'group_id' => '854b5b57-f863-4e48-ba9b-617899c64750',
'day' => 2,
),
1 =>
(object) array(
'group_id' => '854b5b57-f863-4e48-ba9b-617899c64750',
'day' => 3,
),
2 =>
(object) array(
'group_id' => '854b5b57-f863-4e48-ba9b-617899c64750',
'day' => 4,
),
3 =>
(object) array(
'group_id' => '854b5b57-f863-4e48-ba9b-617899c64750',
'day' => 5,
),
4 =>
(object) array(
'group_id' => '854b5b57-f863-4e48-ba9b-617899c64750',
'day' => 6,
),
5 =>
(object) array(
'group_id' => '854b5b57-f863-4e48-ba9b-617899c64750',
'day' => 7,
),
6 =>
(object) array(
'group_id' => 'f3f739d2-77fe-4e1f-b7fc-44242f52610b',
'day' => 2,
),
7 =>
(object) array(
'group_id' => 'f3f739d2-77fe-4e1f-b7fc-44242f52610b',
'day' => 3,
),
8 =>
(object) array(
'group_id' => 'f3f739d2-77fe-4e1f-b7fc-44242f52610b',
'day' => 4,
),
9 =>
(object) array(
'group_id' => 'f3f739d2-77fe-4e1f-b7fc-44242f52610b',
'day' => 5,
),
10 =>
(object) array(
'group_id' => 'f3f739d2-77fe-4e1f-b7fc-44242f52610b',
'day' => 6,
),
And what I've done next is to get every date from start of the year until today and store it to an array.
$now = \Carbon\Carbon::now()->format('Y-m-d');
$start = \Carbon\Carbon::parse($now)->startOfYear()->format('Y-m-d');
$dateRangePeriod = \Carbon\CarbonPeriod::create($start, $now);
$dateRange = [];
foreach ($dateRangePeriod as $key => $date) {
$dateRange[] = $date->format('Y-m-d');
}
The result from code above is like this:
Array date
array (
0 => '2022-04-01',
1 => '2022-04-02',
2 => '2022-04-03',
3 => '2022-04-04',
4 => '2022-04-05',
5 => '2022-04-06',
6 => '2022-04-07',
7 => '2022-04-08',
8 => '2022-04-09',
9 => '2022-04-10',
10 => '2022-04-11',
11 => '2022-04-12',
12 => '2022-04-13',
)
What I want to do next is, I want to get only holiday date from array date above. But I don't know how to do that because from work_day I only get group_id and the number of day.
How to know if the day from array date is the holiday based on array work_day.
I'm trying some way to doing it, but I can't found the solution yet. I've tried like code bellow, but still not working:
// Loop all date from array date
foreach ($dateRange as $range) {
// Get number of day from date
$day = date('N', strtotime($range));
// Loop work day array
foreach ($work_day_arr as $work) {
// When day from work not equals to day from date (this is a right way to check if days from array date is a holiday)?
if($work->day != $day) {
// Check if group_id & off_date (holiday date) is not set
if(!isset($data['attendance_group_id'], $data['off_date'])) {
$data['attendance_group_id'] = $work->group_id;
$data['off_date'] = date('Y-m-d', strtotime($range));
$objData[] = $data;
}
}
}
}
The example result that I want is something like this (excluding holiday date):
From:
array (
0 => '2022-04-01', // holiday date
1 => '2022-04-02',
2 => '2022-04-03',
3 => '2022-04-04',
4 => '2022-04-05',
5 => '2022-04-06', // holiday date
6 => '2022-04-07',
7 => '2022-04-08',
8 => '2022-04-09',
9 => '2022-04-10',
10 => '2022-04-11',
11 => '2022-04-12', // holiday date
12 => '2022-04-13', // holiday date
)
To (excluding holiday date):
array (
0 => '2022-04-02',
1 => '2022-04-03',
2 => '2022-04-04',
3 => '2022-04-05',
4 => '2022-04-07',
5 => '2022-04-08',
6 => '2022-04-09',
7 => '2022-04-10',
8 => '2022-04-11',
)
Another case example
From array work day:
day = 1, which is Sunday
array date:
01-01-2022
02-02-2022 // if this date == sunday, then this is a holiday
03-02-2022
result:
02-02-2022 // only get holiday date

Having trouble wrapping my head around how to write a particular loop

I am querying a SQL database to return open work order operations.
My query is producing the Work Order number, operation status and due date.
I am trying to figure out how to iterate through the array that is returned and:
Gather the sum of operations due within a week
Gather the sum of operations due in the second week
Continue to do this until I have made it through all of the entries, ongoing for as many weeks as necessary.
My SQL query looks something like:
SELECT * FROM OPERATION WHERE RESOURCE_ID = '280LASERS' ORDER BY DUE_DATE;
It will return something like:
W/O # | Setup Hours | Run Hours | Due Date
W159769 | 0.5 | 15.0 | 03/01/2020
W159770 | 1.5 | 9.0 | 04/01/2020
W159771 | 0.75 | 81.0 | 05/01/2020
Either way, what I am trying to accomplish is, query the database, step through my result and get the sum foreach week. While NOW+7days <= DUE_DATE; While NOW+14days <= DUE_DATE...
Week One = 15.5 Hours; Week Two = 10.5 Hours; Week Three = 81.75 Hours
EDIT: I apologize for my mess of a question, this is one of the more intense tasks I have tried to accomplish with SQL and PHP.
We are trying to get a better handle on our capacity, and reporting on our capacity.I am hoping to be able to run a query that pulls all of the '280LASERS' Operations and have some sort of root value (Like todays Date) to compare the DUE_DATE against.My plan is to sort by DUE_DATE and get the SUM(SETUP_HRS + RUN_HRS) until DUE_DATE is greater than (TODAY() + 7) then, get the SUM(SETUP_HRS + RUN_HRS) until DUE_DATE is greater than (TODAY() + 14) then ... I can't achieve this with static variables because the number of weeks can go from 6 weeks out, to more than 30 weeks out, simply depending on the DUE_DATE of the furthest out order.I am so close I can taste it, I would really like to share my code, and the output... but feel I have blown this page up and it is a hot mess. Would it be acceptable for me to delete everything above this and reshare my code as it is, as well as the output I am getting.
I don't think you need a loop. It looks like you could just calculate the week number, group by that, and sum the hours for the week.
MySQL
select
DATEDIFF(due_date, NOW()) DIV 7 + 1 AS week_number,
SUM(setup_hours + run_hours) AS week_hours
from operation
where resource_id = '280LASERS'
group by week_number;
SQL Server
select
DATEDIFF(wk, getdate(), due_date) AS week_number,
SUM(setup_hours + run_hours) AS week_hours
from operation
where resource_id = '280LASERS'
group by DATEDIFF(wk, getdate(), due_date);
so I'm back, I'll add a better commented code, here: can't edit the old answer, since I deleted my account and forgot to cancel :|
Anyways, you asked how to manipulate the data. It's a simple array and all the inner arrays are sums from the start of the week to the end. Now, you could store them with different keys, I just used the default assigning because of simplicity.
$results=array(
array( 'due_date'=>'12/02/2020', 'run_hours'=>12.4, 'setup_hours'=>2.4, ), // 2020-02-12 00:00:00
array( 'due_date'=>'15/02/2020', 'run_hours'=>10.4, 'setup_hours'=>1.4, ), // 2020-02-15 00:00:00
array( 'due_date'=>'18/02/2020', 'run_hours'=>8.4, 'setup_hours'=>3.4, ), // 2020-02-18 00:00:00
array( 'due_date'=>'20/02/2020', 'run_hours'=>2.4, 'setup_hours'=>1.4, ), // 2020-02-20 00:00:00
array( 'due_date'=>'21/02/2020', 'run_hours'=>9.4, 'setup_hours'=>1.4, ), // 2020-02-21 00:00:00
array( 'due_date'=>'24/02/2020', 'run_hours'=>12.4, 'setup_hours'=>1.4, ), // 2020-02-24 00:00:00
array( 'due_date'=>'26/02/2020', 'run_hours'=>11.3, 'setup_hours'=>1.4, ), // 2020-02-26 00:00:00
array( 'due_date'=>'29/02/2020', 'run_hours'=>4.4, 'setup_hours'=>2.4, ), // 2020-02-29 00:00:00
array( 'due_date'=>'02/03/2020', 'run_hours'=>5.7, 'setup_hours'=>4, ), // 2020-03-02 00:00:00
array( 'due_date'=>'04/03/2020', 'run_hours'=>11.5, 'setup_hours'=>3.4, ), // 2020-03-04 00:00:00
array( 'due_date'=>'06/03/2020', 'run_hours'=>7.3, 'setup_hours'=>1.4, ), // 2020-03-06 00:00:00
array( 'due_date'=>'08/03/2020', 'run_hours'=>9.6, 'setup_hours'=>1.4, ), // 2020-03-08 00:00:00
array( 'due_date'=>'12/03/2020', 'run_hours'=>14.7, 'setup_hours'=>1.4, ), // 2020-03-12 00:00:00
array( 'due_date'=>'15/03/2020', 'run_hours'=>12.5, 'setup_hours'=>1.4, ), // 2020-03-15 00:00:00
array( 'due_date'=>'19/03/2020', 'run_hours'=>4.4, 'setup_hours'=>1.4, ), // 2020-03-19 00:00:00
array( 'due_date'=>'21/03/2020', 'run_hours'=>5.6, 'setup_hours'=>4, ), // 2020-03-21 00:00:00
array( 'due_date'=>'24/03/2020', 'run_hours'=>11.4, 'setup_hours'=>1.4, ), // 2020-03-24 00:00:00
array( 'due_date'=>'29/03/2020', 'run_hours'=>7.4, 'setup_hours'=>1.4, ), // 2020-03-29 00:00:00
array( 'due_date'=>'01/04/2020', 'run_hours'=>9.4, 'setup_hours'=>1.4, ), // 2020-04-01 00:00:00
// some far off weeks
array( 'due_date'=>'18/06/2020', 'run_hours'=>9.4, 'setup_hours'=>1.4, ),
array( 'due_date'=>'21/06/2020', 'run_hours'=>9.4, 'setup_hours'=>1.4, ),
array( 'due_date'=>'09/07/2020', 'run_hours'=>9.4, 'setup_hours'=>1.4, ),
array( 'due_date'=>'12/08/2020', 'run_hours'=>9.4, 'setup_hours'=>1.4, ),
);
$time=strtotime(date('Y-m-d')); // get time in same
// wrapping time in strtotime and date trims the seconds to the desired format
$one_week=60*60*24*7;
$sums=array();
foreach($results as $row){
/* php 5.3+ this block of code gets the time of the date, this conversions are made in case a custom non standard date format is made, alternatively one can use strtotime with the correct date format
$date = DateTime::createFromFormat('d/m/Y', $row['due_date']);//use your format and values
if(!$date){
echo 'Not a valid format';
break;
}
$entry_time = strtotime(date('Y-m-d',$date->getTimestamp()));
// if your date format doesnt have hours minutes and seconds then timestamp will add the current h,min,s,
// this may not be desired, so this wrapping it in strtotime and date trims the values
*/
// WARNING: If the format is right weeks will be way off
$entry_time = strtotime($row['due_date']); // if due_date is a valid format, see PHP docs for more information
if (!$entry_time) {
echo "Not a valid date format";
break;
}
$entry_work_hours=$row['run_hours']+$row['setup_hours'];
// if the entry time is by some reason smaller then the current time save it to a special past_due container
if ($entry_time < $time) {
// if a past_due container exists add the sum, otherwise create a past_due container
if (isset($sums['past_due'])) {
$sums['past_due']['sum']+=$entry_work_hours;
} else {
$sums['past_due']= array(
'sum' => $entry_work_hours,
'start' => $row['due_date'], // the earliest event
'end' => date('d/m/Y',$time), // current time, if $entry_time is bigger or equal we're talking about entries that are yet to happen
);
}
} else if ( $entry_time >= $time ){
// getting the future_dues array, every object holds an array/map, that holds the sum, the start of the week and when the week ends
// endings are exclusive ie. if an entry_data falls on the end date it goes to the start of the next container
if (isset($sums['future_dues'])) {
$future_dues=$sums['future_dues'];
} else {
$future_dues = array(
array(
'sum' => 0,
'start' => $time,
'end' => $time+$one_week
)
);
}
// get the last week container, and save the key so we can reassign it back to the $sums array on the right spot
$last_index = count($future_dues)-1;
$future_due = $future_dues[$last_index];
// manipulate the week data
// if the entry time is smaller then the current end of the week add to the sum, otherwise add a new week interval container
if ($entry_time < $future_due['end']) {
$future_due['sum']+=$entry_work_hours;
// reassign week container
$future_dues[$last_index]=$future_due;
} else {
$last_week_end = $future_due['end'];
$new_end = $last_week_end + $one_week;
//do a while loop to get the next week end in which the work is done
while ($new_end < $entry_time) {
// skip this part if empty weeks are not desired
$future_dues[] = array(
'sum' => 0,
'start' => $last_week_end,
'end' => $new_end
);
$last_week_end = $new_end;
$new_end = $new_end + $one_week;
// echo "$new_end < $entry_time".'<br>';
}
// add a new week container, the start of the week is the end of the previous one and the end is 7 days from that
$future_dues[]=array(
'sum' => $entry_work_hours,
'start' => $last_week_end,
'end' => $new_end
);
}
// reassign the whole week containers container to the array
$sums['future_dues']=$future_dues;
}
}
// convert time back to dates
foreach ($sums['future_dues'] as $key => &$due) {
$due['start']=date('d/m/Y',$due['start']);
$due['end']=date('d/m/Y',$due['end']);
}
// use $sums to display the values you need, use:
// echo "<pre>";
// print_r($sums);
// echo "</pre>";
// to better understand how data is stored
echo "<pre>"; // use pre tags to have a nice inline values, this can be rewriten into a table
$past_due=$sums['past_due'];
//past due is a single container
$time_prefix="Time: ";
$working_hours_prefix="Working hours: ";
$time = $time_prefix.$sums['past_due']['start']." - ".$sums['past_due']['end'];
echo $time."<br>";
echo $working_hours_prefix.str_pad($sums['past_due']['sum'],abs(strlen($time)-strlen($working_hours_prefix)),' ',STR_PAD_LEFT);
// make it inline with the time
echo "<br><br>";
$due_dates=$sums['future_dues'];
foreach($due_dates as $week_container){
$time = $time_prefix.$week_container['start']." - ".$week_container['end'];
echo $time."<br>";
echo $working_hours_prefix.str_pad($week_container['sum'],abs(strlen($time)-strlen($working_hours_prefix)),' ',STR_PAD_LEFT);
echo "<br><br>";
//echo $week_container['sum']; /// if you want to show the sum
//echo $week_container['start']; /// if you want to show the start
//echo $week_container['end']; /// if you want to show the end
}
echo "</pre>";
// above is a bit abstracted but it esencially does this
echo "<br><br>";
echo "<br><br>";
$past_due=$sums['past_due'];
$past_start = $sums['past_due']['start'];
$past_end = $sums['past_due']['end'];
$past_sum = $sums['past_due']['sum'];
echo "Time: $past_start - $past_end<br>";
echo "Working hours: $past_sum"; // previous case adds breaks to be inline
echo "<br><br>";
$due_dates=$sums['future_dues'];
foreach($due_dates as $week_container){
$week_start = $week_container['start'];
$week_end = $week_container['end'];
$week_sum = $week_container['sum'];
echo "Time: $week_start - $week_end<br>";
echo "Working hours: $week_sum"; // previous case adds breaks to be inline
echo "<br><br>";
}
Edit:
A new while loop was added to account for empty weeks.
Note d/m/Y is not strtotime recognised format and it will be read as m/d/Y. To convert it refer to this question.
Edit-2:
To answer your comment. Ok so the thing about the spans is that I made them so that if the span went from 2020-01-01 to 2020-01-08 and the second one from 2020-01-08 to 2020-01-15 where should the working hours of 2020-01-08 go to week 1 or week 2?
When you corrected $entry_time < $future_due['end'] to $entry_time <= $future_due['end'] this means that the count is added to week 1, while the original solution would have added it to week 2 as the starting date.
You can try and add 8 days and then subtract one if you wanted the containers to span between 2020-01-01 and 2020-01-08 and 2020-01-09 and 2020-01-16 and have both endings be inclusive. Now, I'm not going to write this part since it really depends on how YOU want define your endings.
And your question if you can change the time to something else then the current time? Sure, just change this line.
$time=strtotime(date('Y-m-d'));
//to
$time=__TIME__YOU_WANT_IN_SECONDS__;
//or
$time = strtotime(__THE_DATE_YOU_WANT__); // eg. 01/01/2020
// now this is the time to compare all other dates to
As Don't Panic pointed out about the due dates, I think you might be displaying it in a dd/mm/YYYY format and I'll work from there.
I'll work with a foreach loop but I think Don't Panic's solution might be more efficient.
Steps:
1. Loop through the values and calculate the time of the date,
2. Compare it with the desired date
3. Add it to the right sum
Notes: date format is important, if hours, minutes and seconds are missing the getTimestamp adds the current values for them
I've added some test data based on my understanding of the problem.
I've also added a past due column in case any date is already past the current time().
The foreach loop checks the if the entry_time is smaller than the current time, this means it is past_due.
If not, we check if the future_dues are set. Future dues represent all the different weeks in the future. If none are set one array with an array is added.
The second array represent the current closest future starting from the current time to the end of 7 days in the future.
Start and end help us read the end results better, they are timestamps. Also a sum key of value 0 is added.
Then we take the last element from the future_dues and see if the due_date is smaller then the end of the week. If it is we add the working hour, otherwise we add a new future_due object.
At the end I added a foreach loop that converts the timestamps to a date format.
$results=array(
array( 'due_date'=>'12/02/2020', 'run_hours'=>12.4, 'setup_hours'=>2.4, ), // 2020-02-12 00:00:00
array( 'due_date'=>'15/02/2020', 'run_hours'=>10.4, 'setup_hours'=>1.4, ), // 2020-02-15 00:00:00
array( 'due_date'=>'18/02/2020', 'run_hours'=>8.4, 'setup_hours'=>3.4, ), // 2020-02-18 00:00:00
array( 'due_date'=>'20/02/2020', 'run_hours'=>2.4, 'setup_hours'=>1.4, ), // 2020-02-20 00:00:00
array( 'due_date'=>'21/02/2020', 'run_hours'=>9.4, 'setup_hours'=>1.4, ), // 2020-02-21 00:00:00
array( 'due_date'=>'24/02/2020', 'run_hours'=>12.4, 'setup_hours'=>1.4, ), // 2020-02-24 00:00:00
array( 'due_date'=>'26/02/2020', 'run_hours'=>11.3, 'setup_hours'=>1.4, ), // 2020-02-26 00:00:00
array( 'due_date'=>'29/02/2020', 'run_hours'=>4.4, 'setup_hours'=>2.4, ), // 2020-02-29 00:00:00
array( 'due_date'=>'02/03/2020', 'run_hours'=>5.7, 'setup_hours'=>4, ), // 2020-03-02 00:00:00
array( 'due_date'=>'04/03/2020', 'run_hours'=>11.5, 'setup_hours'=>3.4, ), // 2020-03-04 00:00:00
array( 'due_date'=>'06/03/2020', 'run_hours'=>7.3, 'setup_hours'=>1.4, ), // 2020-03-06 00:00:00
array( 'due_date'=>'08/03/2020', 'run_hours'=>9.6, 'setup_hours'=>1.4, ), // 2020-03-08 00:00:00
array( 'due_date'=>'12/03/2020', 'run_hours'=>14.7, 'setup_hours'=>1.4, ), // 2020-03-12 00:00:00
array( 'due_date'=>'15/03/2020', 'run_hours'=>12.5, 'setup_hours'=>1.4, ), // 2020-03-15 00:00:00
array( 'due_date'=>'19/03/2020', 'run_hours'=>4.4, 'setup_hours'=>1.4, ), // 2020-03-19 00:00:00
array( 'due_date'=>'21/03/2020', 'run_hours'=>5.6, 'setup_hours'=>4, ), // 2020-03-21 00:00:00
array( 'due_date'=>'24/03/2020', 'run_hours'=>11.4, 'setup_hours'=>1.4, ), // 2020-03-24 00:00:00
array( 'due_date'=>'29/03/2020', 'run_hours'=>7.4, 'setup_hours'=>1.4, ), // 2020-03-29 00:00:00
array( 'due_date'=>'01/04/2020', 'run_hours'=>9.4, 'setup_hours'=>1.4, ), // 2020-04-01 00:00:00
);
$time=strtotime(date('Y-m-d')); // get time in same
// wrapping time in strtotime and date trims the seconds to the desired format
$one_week=60*60*24*7;
$sums=array();
foreach($results as $row){
$date = DateTime::createFromFormat('d/m/Y', $row['due_date']);//use your format and values
if(!$date){
echo 'Not a valid format';
break;
}
$entry_time = strtotime(date('Y-m-d',$date->getTimestamp()));
// if your date format doesnt have hours minutes and seconds then timestamp will add the current h,min,s,
// this may not be desired, so this wrapping it in strtotime and date trims the values
$entry_work_hours=$row['run_hours']+$row['setup_hours'];
if ($entry_time < $time) {
if (isset($sums['future_dues'])) {
$sums['past_due']['sum']+=$entry_work_hours;
} else {
$sums['past_due']= array(
'sum'=> $entry_work_hours,
'start'=> $row['due_date'],
'end' => date('d/m/Y',$time),
);
}
} else if ( $entry_time > $time ){
if (isset($sums['future_dues'])) {
$future_dues=$sums['future_dues'];
} else {
$future_dues = array(
array(
'sum'=>0,
'start'=>$time,
'end'=>$time+$one_week
)
);
}
$last_index = count($future_dues)-1;
$future_due = $future_dues[$last_index];
if ($entry_time < $future_due['end']) {
$future_due['sum']+=$entry_work_hours;
$future_dues[$last_index]=$future_due;
} else {
$future_dues[]=array(
'sum'=>$entry_work_hours,
'start'=>$future_due['end'],
'end'=>$future_due['end']+$one_week
);
}
$sums['future_dues']=$future_dues;
}
}
// if you want to conver them back to dates
foreach ($sums['future_dues'] as $key => &$due) {
$due['start']=date('d/m/Y',$due['start']);
$due['end']=date('d/m/Y',$due['end']);
}
SQL Code seems to get me some good info, here is the final version
SELECT
DATEDIFF(week, getdate(), WORK_ORDER.DESIRED_WANT_DATE) AS week_number,
SUM(OPERATION.SETUP_HRS + OPERATION.RUN_HRS) AS week_hours
FROM OPERATION
JOIN WORK_ORDER ON OPERATION.WORKORDER_BASE_ID = WORK_ORDER.BASE_ID
WHERE OPERATION.RESOURCE_ID = '103TURRET' AND (OPERATION.STATUS = 'R' OR OPERATION.STATUS = 'F') AND WORK_ORDER.SUB_ID = '0'
GROUP BY DATEDIFF(week, getdate(), WORK_ORDER.DESIRED_WANT_DATE)
ORDER BY week_number;
Gives Me
week_number week_hours
-14 0.630
-11 1.640
-8 1.980
-1 0.540
0 3.820
1 18.500
2 15.090
3 3.410
5 16.490
7 0.890
9 17.950
14 5.000
19 5.000
23 6.750
27 5.000
31 5.000
I manually total the negatives + zero week = past due
Thank you very much #Don't Panic for all of your help.
Ehh... if anyone could help me get this to where it always starts on a Monday, rather than the day it is run, I would appreciate it.
Alright, here is the code I have so far. I would like to get it to look better, maybe not show all the different elements in the array... but I am terrified to change much more.
This is some pretty incredible code as far as I am concerned.
<?php //CONNECTION SETTING
$database='VMFG';
$odbc_name='SQLServer';
$odbc_user='sa';
$odbc_password='Password#';
$con = odbc_connect($odbc_name,$odbc_user,$odbc_password);
$query="SELECT OPERATION.WORKORDER_BASE_ID AS 'W/O #', /*STATEMENT TO PULL OPERATIONS AND PARSE WORK ORDER DATES*/
OPERATION.WORKORDER_SUB_ID AS 'SUB ID',
OPERATION.RESOURCE_ID AS 'RESOURCE ID',
OPERATION.SETUP_HRS AS 'SETUP HRS',
OPERATION.RUN AS 'RUN RATE',
OPERATION.RUN_TYPE AS 'U/M',
OPERATION.RUN_HRS AS 'RUN TOTAL',
OPERATION.CALC_START_QTY AS 'START QTY',
OPERATION.CALC_END_QTY AS 'END QTY',
OPERATION.COMPLETED_QTY AS 'QTY COMP',
OPERATION.DEVIATED_QTY AS 'DIFFERENCE',
OPERATION.ACT_SETUP_HRS AS 'SETUP USED',
OPERATION.ACT_RUN_HRS AS 'HRS RUN',
OPERATION.STATUS,
OPERATION.SETUP_COMPLETED AS 'SETUP COMP',
WORK_ORDER.DESIRED_WANT_DATE AS 'DUE DATE'
FROM OPERATION
JOIN WORK_ORDER ON OPERATION.WORKORDER_BASE_ID=WORK_ORDER.BASE_ID
WHERE (OPERATION.STATUS = 'R' OR OPERATION.STATUS = 'F')
AND (OPERATION.RESOURCE_ID = '".$_GET['operation']."')
AND WORK_ORDER.SUB_ID = '0'
ORDER BY STATUS DESC, [DUE DATE];";
?>
<form method="get"> <?//FORM TO CHOOSE OPERATION?>
<table>
<tr>
<td>
<select name="operation">
<option value="103TURRET">103TURRET</option>
<option value="104PRESSBRAKES">104PRESSBRAKES</option>
<option value="280LASERS">280LASERS</option>
<option value="300WELD">300WELD</option>
<option value="701POWDERLINE">701POWDERLINE</option>
<option value="Outside Service">Outside Server</option>
<option value="ANYOSS">ANY OSS</option>
</select>
</td>
<td><input type="submit" value="Submit" name="action" /></td>
<td><a href='index.php'>Start Over</a></td>
<td><a href='/xampp/mpc_db/index.php'>Return to DB</a></td>
</tr>
</table>
</form>
<?php
$exec = odbc_exec($con, $query);
$results = array();
while ($row = odbc_fetch_array($exec)) {
$results[] = $row;
}
//*****************************************************************
$time=strtotime(date('Y/m/d')); // get time in same
//wrapping time in strtotime and date trims the seconds to the desired format
$one_week=604800;
$sums=array();
foreach($results as $row){
/*$date = DateTime::createFromFormat('Y/m/d', $row['DUE DATE']);//use your format and values*/
$date = date($row['DUE DATE']);
if(!$date){
echo 'Not a valid format';
break;
}
$entry_time = strtotime(date('Y/m/d',strtotime($date)));
// if your date format doesnt have hours minutes and seconds then timestamp will add the current h,min,s,
// this may not be desired, so this wrapping it in strtotime and date trims the values
$entry_work_hours=$row['RUN TOTAL']+$row['SETUP HRS'];
if ($entry_time < $time) {
if (isset($sums['past_due'])) {
$sums['past_due']['sum'] += $entry_work_hours;
} else {
$sums['past_due'] = array(
'sum'=> $entry_work_hours,
'start'=> $row['due_date'],
'end' => date('Y/m/d',$time),
);
}
} else if ( $entry_time > $time ){
if (isset($sums['future_dues'])) {
$future_dues=$sums['future_dues'];
} else {
$future_dues = array(
array(
'sum'=>0,
'start'=>$time,
'end'=>$time+$one_week
)
);
}
$last_index = count($future_dues)-1;
$future_due = $future_dues[$last_index];
if ($entry_time < $future_due['end']) {
$future_due['sum']+=$entry_work_hours;
$future_dues[$last_index]=$future_due;
} else {
$future_dues[]=array(
'sum'=>$entry_work_hours,
'start'=>$future_due['end'],
'end'=>$future_due['end']+$one_week
);
}
$sums['future_dues']=$future_dues;
}
}
// if you want to convert them back to dates
foreach ($future_dues as $key => &$due) {
$due['start']=date('Y/m/d',$due['start']);
$due['end']=date('Y/m/d',$due['end']);
}
//**********************************************************************
foreach($sums['past_due'] as $stuff){ //Actually kind-of sort-of********
print_r($stuff); //Looks like exactly**************
echo "<br>"; //What I am trying to create******
} //Past Due Hours!*****************
//**********************************************************************
//**********************************************************************
foreach($future_dues as $edues){ //Actually kind-of sort-of************
print_r($edues); //Looks like exactly******************
echo "<br>"; //What I am trying to create**********
} //Future Hours!***********************
//**********************************************************************
?>
The best part is! My output is readable!
5.26
2020/02/27
Array ( [sum] => 9.26 [start] => 2020/02/27 [end] => 2020/03/05 )
Array ( [sum] => 7.31 [start] => 2020/03/05 [end] => 2020/03/12 )
Array ( [sum] => 6.27 [start] => 2020/03/12 [end] => 2020/03/19 )
Array ( [sum] => 2.14 [start] => 2020/03/19 [end] => 2020/03/26 )
Array ( [sum] => 11.82 [start] => 2020/03/26 [end] => 2020/04/02 )
Array ( [sum] => 6.95 [start] => 2020/04/02 [end] => 2020/04/09 )
Array ( [sum] => 36 [start] => 2020/04/09 [end] => 2020/04/16 )
Array ( [sum] => 0.81 [start] => 2020/04/16 [end] => 2020/04/23 )
Array ( [sum] => 30.98 [start] => 2020/04/23 [end] => 2020/04/30 )
Array ( [sum] => 1.3 [start] => 2020/04/30 [end] => 2020/05/07 )
Array ( [sum] => 3.29 [start] => 2020/05/07 [end] => 2020/05/14 )
Array ( [sum] => 1.57 [start] => 2020/05/14 [end] => 2020/05/21 )
Array ( [sum] => 1.95 [start] => 2020/05/21 [end] => 2020/05/28 )
Array ( [sum] => 0.29 [start] => 2020/05/28 [end] => 2020/06/04 )
Array ( [sum] => 2.19 [start] => 2020/06/04 [end] => 2020/06/11 )
Array ( [sum] => 1.57 [start] => 2020/06/11 [end] => 2020/06/18 )
Array ( [sum] => 1.95 [start] => 2020/06/18 [end] => 2020/06/25 )
Array ( [sum] => 1.3 [start] => 2020/06/25 [end] => 2020/07/02 )
Array ( [sum] => 3.29 [start] => 2020/07/02 [end] => 2020/07/09 )
Array ( [sum] => 0.67 [start] => 2020/07/09 [end] => 2020/07/16 )
Array ( [sum] => 0.33 [start] => 2020/07/16 [end] => 2020/07/23 )
Array ( [sum] => 2.73 [start] => 2020/07/23 [end] => 2020/07/30 )
Array ( [sum] => 17.79 [start] => 2020/07/30 [end] => 2020/08/06 )
Array ( [sum] => 1.57 [start] => 2020/08/06 [end] => 2020/08/13 )
Array ( [sum] => 1.95 [start] => 2020/08/13 [end] => 2020/08/20 )
Array ( [sum] => 1.3 [start] => 2020/08/20 [end] => 2020/08/27 )
Array ( [sum] => 3.29 [start] => 2020/08/27 [end] => 2020/09/03 )
Array ( [sum] => 1.3 [start] => 2020/09/03 [end] => 2020/09/10 )
Array ( [sum] => 3.29 [start] => 2020/09/10 [end] => 2020/09/17 )
Array ( [sum] => 1.57 [start] => 2020/09/17 [end] => 2020/09/24 )
Array ( [sum] => 1.95 [start] => 2020/09/24 [end] => 2020/10/01 )
Although I can not figure out how to manipulate it without breaking it...

Get data from mysql and group them in weeks and also display the dates

I am printing data on weekly basis. I need to add one thing to my query. I want the starting and ending date of the week as well along with data.
At the moment the data is like this
[0] => Array
(
[WEEK] => 7
[total_sub_total] => 110.30
[total_tax] => 9.92
[total_restaurant_delivery_fee] => 0
)
[0] => Array
(
[WEEK] => 8
[total_sub_total] => 6540.00
[total_tax] => 1046.40
[total_restaurant_delivery_fee] => 0
)
I want the dates as well of that week. for example, it should be
[0] => Array
(
[WEEK] => 8,
[starting_week_date] => 2018-02-21 13:18:10,
[ending_week_date] => 2018-02-26 13:18:10,
[total_sub_total] => 6540.00
[total_tax] => 1046.40
[total_restaurant_delivery_fee] => 0
)
Here is the code
public function getWeeklyEarnings($restaurant_id)
{
return $this->find('all', array(
//'contain' => array('OrderMenuItem', 'Restaurant', 'OrderMenuItem.OrderMenuExtraItem', 'PaymentMethod', 'Address','UserInfo','RiderOrder.Rider'),
'conditions' => array(
'Order.restaurant_id' => $restaurant_id,
'Order.status' => 2,
'Order.created > DATE_SUB(NOW(), INTERVAL 4 WEEK)'
),
'fields' => array(
'WEEK(Order.created) AS WEEK',
'sum(Order.sub_total) AS total_sub_total',
'sum(Order.tax) AS total_tax',
'sum(Order.restaurant_delivery_fee) AS total_restaurant_delivery_fee',
),
'group' => array('WEEK(Order.created)'),
'recursive' => 0
));
}
There is no simple function that will yield a week interval (or start/end date of a week) given a week number. You have to find these dates manually.
try this :
'fields' => array(
'WEEK(Order.created) AS WEEK',
'DATE_ADD(Order.created, INTERVAL(1-DAYOFWEEK(Order.created)) DAY) AS week_start',
'DATE_ADD(Order.created, INTERVAL(7-DAYOFWEEK(Order.created)) DAY) AS week_end',
'sum(Order.sub_total) AS total_sub_total',
'sum(Order.tax) AS total_tax',
'sum(Order.restaurant_delivery_fee) AS total_restaurant_delivery_fee'
)
The DAYOFWEEK() function returns an integer ranging from 1 (Sunday) to 7 (Saturday). So if Order.created happens to be Tuesday we get the following statements:
DATE_ADD(Order.created, INTERVAL -2 DAY)
which essentially means “subtract 2 days from Order.created (which is that week’s Sunday) and also:
DATE_ADD(Order.created, INTERVAL 4 DAY)
which yields the date of that week’s Friday.
Or, you can try :
'fields' => array(
'WEEK(Order.created) AS WEEK',
'MIN(Order.created) as week_start',
'MAX(Order.created) as week_end',
'sum(Order.sub_total) AS total_sub_total',
'sum(Order.tax) AS total_tax',
'sum(Order.restaurant_delivery_fee) AS total_restaurant_delivery_fee'
)
But you have to be sure that you have orders on every single day of the week.
I hope this helps.

how would I detect a non-overlap of two time periods?

I have a user input form where user select the date in (YYYY-mm-dd) format, and start time in (H:i) and end time in (H:i) format, or assume i have three variable with following values.
$date = '2012-11-22';
$startTime = '1:00';
$endTime = '4:00';
i now have to compare this values with existing array of values. my existing array look like this.
Array
(
[0] => Array
(
[id] => 1
[start_datetime] => 2012-11-22 02:30:00
[end_datetime] => 2012-11-22 05:00:00
)
[1] => Array
(
[id] => 2
[start_datetime] => 2012-11-22 00:00:00
[end_datetime] => 2012-11-22 02:30:00
)
[2] => Array
(
[id] => 3
[start_datetime] => 2012-11-22 05:00:00
[end_datetime] => 2012-11-22 08:00:00
)
[3] => Array
(
[id] => 4
[start_datetime] => 2012-11-22 08:00:00
[end_datetime] => 2012-11-22 11:00:00
)
[4] => Array
(
[id] => 5
[start_datetime] => 2012-11-22 11:00:00
[end_datetime] => 2012-11-22 17:00:00
)
)
i have to check if the user input selected [date, startTime, and endTime] has any of the slots already booked in the given array of time slots. from what i see the solution is to first split and match the date, if it matches the date then time needs to be matched accordingly. i am confused about how to go with it. i hope to get some simple solution from you guys :)
thank you.
UPDATE:
i tried doing this way.
$arenaSurfaceBooking = array(
array(
'id' => 1,
'start_datetime' => '2012-11-22 02:30:00',
'end_datetime' => '2012-11-22 05:00:00',
),
array(
'id' => 2,
'start_datetime' => '2012-11-22 00:00:00',
'end_datetime' => '2012-11-22 02:30:00',
),
array(
'id' => 3,
'start_datetime' => '2012-11-22 05:00:00',
'end_datetime' => '2012-11-22 08:00:00',
),
array(
'id' => 4,
'start_datetime' => '2012-11-22 08:00:00',
'end_datetime' => '2012-11-22 11:00:00',
),
array(
'id' => 5,
'start_datetime' => '2012-11-22 11:00:00',
'end_datetime' => '2012-11-22 17:00:00',
)
);
foreach($arenaSurfaceBooking as $booking) {
$bookedDateTimestamp = strtotime(date('Y-m-d', strtotime($booking['start_datetime'])));
$inputDateTimestamp = strtotime($context['date']);
$bookedStartTime = strtotime(date('H:i', strtotime($booking['start_datetime'])));
$bookedEndTime = strtotime(date('H:i', strtotime($booking['end_datetime'])));
$userStartTime = strtotime(date('H:i', strtotime($context['start_datetime'])));
$userEndTime = strtotime(date('H:i', strtotime($context['end_datetime'])));
if( $bookedDateTimestamp == $inputDateTimestamp) {
if( $userEndTime <= $bookedStartTime || $userStartTime >= $bookedEndTime) {
echo 'i am booked';
}
}
}
it's not working.
Let's assume the user date/time is formatted like so:
$date = '2012-11-22';
$startTime = '01:00'; // note the extra '0' in front
$endTime = '04:00';
$userStartTime = "$date $startTime";
$userEndTime = "$date $endTime";
Finding overlaps is done this way:
$overlaps = 0;
foreach ($block as $block) {
if ($userStartTime < $block['end_datetime'] && $userEndTime > $block['start_datetime']) {
++$overlaps;
}
}
// if $overlaps > 0 -> there's a booking in the way
This is basically taking a non-overlap condition like this:
$userEndTime <= $block['start_datetime'] || $userStartTime >= $block['end_datetime']
And simply swap the conditions.
This can easily be written into SQL as well to reduce the network overhead between database and application.
Check this out... and modify it according to your requirement to match all existing time... I've matched only one for you...
$date = '2012-11-22';
$startTime = '2:30';
$endTime = '4:00';
$existing[] =
array
(
'id' => 1,
'start_datetime' => '2012-11-22 02:30:00',
'end_datetime' => '2012-11-22 05:00:00'
);
$UserStartTime = strtotime($date." ".$startTime);
$UserEndTime = strtotime($date." ".$endTime);
$ExistingStartTime = strtotime($existing[0]['start_datetime']);
$ExistingEndTime = strtotime($existing[0]['end_datetime']);
if($UserStartTime >= $ExistingStartTime && $UserEndTime <= $ExistingEndTime)
{
echo "BOOKED";
}
else
{
echo "NOT BOOKED";
}
Since the existing array comes from a SQL query:
$date = '2012-11-22';
$startTime = '1:00';
$endTime = '4:00';
if(strlen($startTime==4)){$startTime="0".$startTime;}
if(strlen($endTime==4)){$endTime="0".$startTime;}
$query="SELECT id FROM table WHERE start_datetime='$date $startTime:00' OR end_datetime='$date $endtimeTime:00'";
If the query returns something, the id returned have it booked!
If you want to know if any of the db info matches both datetimes just replace the OR with a AND.
If you want to know if the user time period is between any of the entries of the DB:
$query="SELECT id FROM table WHERE (start_datetime>='$date $startTime:00' AND start_datetime<='$date $endTime:00') OR (end_datetime<='$date $starttimeTime:00' AND end_datetime>='$date $endtimeTime:00') OR (start_datetime<='$date $startTime:00' AND end_datetime>='$date $starttimeTime:00')";
This may help you
$date = '2012-11-22';
$startTime= '1:00:00'; // padded two zero
$endTime = '4:00:00'; // padded two zero
$start_datetime = $date. " ".(strlen(intval(substr($startTime,0,2))) > 1 ? $startTime : "0".$startTime);
$end_datetime = $date. " ".(strlen(intval(substr($endTime,0,2))) > 1? $endTime : "0".$endTime);
for($i = 0;$i<count($your_array);$i++)
{
if($your_array[$i]['start_datetime'] == $start_datetime)
{
// Start date Found
}
if($your_array[$i]['end_datetime'] == $end_datetime)
{
// Start end Found
}
}

Identify Clash from Day and Time Array

I have checked other SO questions but can't seem to find anything related to this - point me in the right direction if I missed something.
I currently have the following array containing a day and time (requested meeting time):
Array (
[0] =>
day => 'Thursday',
start_time => '14:00',
end_time => '15:00'
[1] =>
day => 'Thursday',
start_time => '16:30',
end_time => '17:30'
)
The user is required to attend both of these times. What I am attempting to do is compare against another array containing a users current appointments and detect if there is a clash / time overlap issue
Array (
[0] =>
day => 'Monday',
start_time => '09:00',
end_time => '13:00'
[1] =>
day => 'Wednesday',
start_time => '10:45',
end_time => '11:15'
[2] =>
day => 'Thursday',
start_time => '16:45',
end_time => '17:45'
)
Using the above example I want to identify there is a clash with the second timeslot [1] => of the first array (proposed meetings) which clashes with the third timeslot [2] => of the second array (current meetings).
I have seen examples with timestamps and full dates, but not just days and start / end times.
If they are all in a database, a query for conflicts could look like:
SELECT `plan`.*
FROM `plan`
JOIN `current` ON `plan`.`day`=`current`.`day`
WHERE
`plan`.`start_time` < `current`.`end_time`
AND `plan`.`end_time` > `current`.`start_time`
where current is the table with the current schedule and plan is the table with the user's schedule. I haven't tested this just because I don't have an example, but this should return rows where the day is the same and plan times overlap current times.
edit: You might also want to do stuff like mark current as tentative if they are not required. you can put that into the query where clause.
Also the > and < mean that the start and end minute are not inclusive. so if one ends at the same time as another begins, this will not flag them as a conflict. If you want the start/end minute to be inclusive, change them to >= and <=.
You can do it this way
$slot1 = Array (
0 => array (
'day' => 'Thursday',
'start_time' => '14:00',
'end_time' => '15:00'
),
1 => array (
'day' => 'Thursday',
'start_time' => '16:30',
'end_time' => '17:30'
)
);
$slot2 = Array (
0 => array (
'day' => 'Monday',
'start_time' => '09:00',
'end_time' => '13:00'
),
1 => array (
'day' => 'Wednesday',
'start_time' => '10:45',
'end_time' => '11:15'
),
2 => array (
'day' => 'Thursday',
'start_time' => '16:45',
'end_time' => '17:45'
)
);
echo "<pre>";
$format = "l H:s";
foreach($slot1 as $value)
{
$slot1Start = DateTime::createFromFormat ($format , $value ['day'] . " " . $value['start_time'] );
$slot1End = DateTime::createFromFormat ( $format , $value ['day'] . " " . $value['end_time'] );
foreach($slot2 as $value2)
{
$slot2Start = DateTime::createFromFormat ( $format , $value2 ['day'] . " " .$value2['start_time'] );
$slot2End = DateTime::createFromFormat ( $format , $value2 ['day'] . " " .$value2 ['end_time'] );
if ($slot1Start <= $slot2End && $slot1End >= $slot2Start) {
echo sprintf ( "Even Overlap on %s %s-%s AND %s %s-%s", $value ['day'], $value ['start_time'], $value ['end_time'],
$value2 ['day'], $value2 ['start_time'], $value2 ['end_time'] ), PHP_EOL;
}
}
}
Output
Even Overlap on Thursday 16:30-17:30 AND Thursday 16:45-17:45
There are your a bit modified arrays code
$current_sheduler = Array (
[0] =>
day => 'Thursday',
start_time => '14:00',
end_time => '15:00'
[1] =>
day => 'Thursday',
start_time => '16:30',
end_time => '17:30'
)
$user_plans = Array (
[0] =>
plan_name => 'event1',
day => 'Monday',
start_time => '09:00',
end_time => '13:00'
[1] =>
plan_name => 'event2',
day => 'Wednesday',
start_time => '10:45',
end_time => '11:15'
[2] =>
plan_name => 'event3',
day => 'Thursday',
start_time => '16:45',
end_time => '17:45'
)
Here is way to process your arrays and catches if event planned by user matches time from your first array
foreach($user_plans as $plan){
foreach($current_sheduler as current){
if($plan['day']==$current['day']){
if(
($plan['start_time']>=$current['start_time']) &&
($plan['end_time']<=$current['end_time'])
){
echo "Event {$plan['plan_name']} is working now!";
}
}
}
}
This is general logic, for situation, when match means full period match only.
Another notice: befor compare times, you need to recount them into counted minutes format.

Categories