This question already has answers here:
How can I sort arrays and data in PHP?
(14 answers)
Closed 8 years ago.
Im trying to figure out how to sort the array below so that past array items are sent to the end of the array staying in start_date descending order.
Edit. Id probably include a time array key value item in all arrays to sort by start_date.
[216] => Array (
[title] => Production 1
[start_date] => 20th Feb
[end_date] => 23rd Feb 2015
[ticket_link] => http://www.google.co.uk
[writer] => Sarah Ruhl
[thumb_image] => /files/3514/1762/4350/Biz-Bio-Pic.jpg
[past] => 1
)
[218] => Array(
[title] => Production 3
[start_date] => 27th Feb
[end_date] => 2nd Mar 2015
[ticket_link] => www.google.co.uk
[writer] => Sarah Ruhl
[thumb_image] => /files/9414/1762/4351/Dan-Bio-Pic.jpg
[past] => 1
)
[219] => Array (
[title] => Production 4
[start_date] => 3rd Mar
[end_date] => 5th Mar 2015
[ticket_link] => www.google.co.uk
[writer] => Sarah Ruhl
[thumb_image] => /files/4314/1762/4351/Kate-Bio-Pic.jpg
[past] => 0
)
Try this -
function checkdate($a, $b)
{
$a = strtotime($a['start_date']);
$b = strtotime($b['start_date']);
if ($a == $b) {
return 0;
}
return ($a > $b) ? -1 : 1;
}
function checkpast($a, $b)
{
$a_start = strtotime($a['start_date']);
$b_start = strtotime($b['start_date']);
if ($a_start == b_start ) {
return ($a['past'] > $b['past']) ? -1 : 1;
}
}
$array = //your array
usort($array, "checkdate");
usort($array, "checkpast");
Related
I am stumped about how to go about checking to see if multiple *date/time value -ranges- (meaning: start and end times) are in conflict with one another.
Summary & samples of data I need to work with.
I have an (app) events table, that is used to create a form for the user to go through and check off (checkboxes) all the sessions/events they attended.
The names of the checkboxes are generated using info about the session. (month/day start/end times along with a session id)
ie: hours_9_5_p02_800_845
9 = month
5 = date
p02 = session id/event code
800 = start time
845 = end time
all delimited by an underscore ("_")
If the user checks (and submits) multiple sessions, there will be many of these values to check for a time conflict..
hours_9_5_p08_755_800
hours_9_5_p02_800_845
hours_9_5_p02_800_855
hours_9_5_p03_800_845
hours_9_5_p04_820_835
hours_9_5_p04_845_900
hours_9_5_REG_900_915
hours_9_5_REG_1300_1305
hours_9_5_REG_1310_1335
hours_9_5_REG_1320_1335
The above is an example of the fieldlist/array that I 'could' get as a user selection/submission that I need to check for any possible conflicts (obviously the user couldnt be two places at once) :) And the above have many/several overlapping of just the same exact time slots selected.
** I am open to either PHP, (checking after the user submits) or javascript/jQuery (if it can do the date/time RANGE conflict checking, it might be easier to then highlight those rows/elements on the page if done on the front end)
I'd image, first you need to parse those checkbox names/strings from the fieldlist array...
which I have done like so: (php)
function conflictParse($delimiter, $targetString){
//echo 'fired';
$breakDown = explode($delimiter, $targetString);
$startTime = substr_replace($breakDown[4] , ':', -2, 0);
$endTime = substr_replace($breakDown[5] , ':', -2, 0);
$startString = "$breakDown[1]/$breakDown[2]/2015 $startTime";
$endString = "$breakDown[1]/$breakDown[2]/2015 $endTime";
$startFormat = strtotime($startString);
$endFormat = strtotime($endString);
$start = date('m/d/Y G:i',$startFormat);
$end = date('m/d/Y G:i',$endFormat);
return "Session Times: $start -- $end <br>";
}
echo conflictParse('_','hours_9_5_p02_800_845');
but I am not clear on HOW to go about using this RANGE of a date start & end time to check against MULTIPLE other date start/end time RANGES?
maybe just sticking with having PHP parse/check conflict upon submit and then return some array of the (original) names page to the page (for some jQuery to use and highlight the elements..etc (but I can handle that aspect later.. for right now I am need help on how I can get the above parse 'date/time' start/end range values checked for conflicts against other 'date/time' start/end range values
update:
Here is the current nested associative array I have to work with for comparing:
Array (
[0] => Array (
[id] => hours_9_9_p02_800_845
[fullStart] => 09/09/2015 8:00
[fullEnd] => 09/09/2015 8:45
[month] => 9
[date] => 9
[session_code] => p02
[start] => 8:00
[end] => 8:45
[hasConflict] => false
)
[1] => Array (
[id] => hours_9_9_p02_800_855
[fullStart] => 09/09/2015 8:00
[fullEnd] => 09/09/2015 8:55
[month] => 9
[date] => 9
[session_code] => p02
[start] => 8:00
[end] => 8:55
[hasConflict] => false
)
[2] => Array (
[id] => hours_9_9_p03_800_845
[fullStart] => 09/09/2015 8:00
[fullEnd] => 09/09/2015 8:45
[month] => 9
[date] => 9
[session_code] => p03
[start] => 8:00
[end] => 8:45
[hasConflict] => false
)
[3] => Array (
[id] => hours_9_9_p04_820_830
[fullStart] => 09/09/2015 8:20
[fullEnd] => 09/09/2015 8:30
[month] => 9
[date] => 9
[session_code] => p04
[start] => 8:20
[end] => 8:30
[hasConflict] => false
)
[4] => Array (
[id] => hours_9_9_p04_845_900
[fullStart] => 09/09/2015 8:45
[fullEnd] => 09/09/2015 9:00
[month] => 9
[date] => 9
[session_code] => p04
[start] => 8:45
[end] => 9:00
[hasConflict] => false
)
[5] => Array (
[id] => hours_9_9_REG_1300_1315
[fullStart] => 09/09/2015 13:00
[fullEnd] => 09/09/2015 13:15
[month] => 9
[date] => 9
[session_code] => REG
[start] => 13:00
[end] => 13:15
[hasConflict] => false
)
[6] => Array (
[id] => hours_9_9_REG_1300_1330
[fullStart] => 09/09/2015 13:00
[fullEnd] => 09/09/2015 13:30
[month] => 9
[date] => 9
[session_code] => REG
[start] => 13:00
[end] => 13:30
[hasConflict] => false
)
)
I need to convert your js functions over to PHP and of course use the fullStart/fullEnd variables in my time compares I guess..??
(but your function is still confusing me as I see references to event1, event 2.. (to match your example)..
update 2:
The above is my object/array (associative array) that I got from selecting some check boxes, and submitting my form...
Here is my attempt to convert your JS code to PHP based [with some update variablenames]: (and the commented out lines just to try and get some sort of output somewhere)
print_r($conflict_list);
function checkFirst($cf_presX, $cf_presY) {
//$cf_presX['fullStart'] < $cf_presY['fallStart'] ? checkConflict($cf_presX, $cf_presY) : checkConflict($cf_presY, $cf_presX);
echo 'Pres Check: '.$cf_presX[0] . '<br>';
echo 'Pres Check: '.$cf_presY[0] . '<br>';
/*
function checkConflict ($cc_presX, $cc_presY) {
if ($cc_presX.['fullEnd'] > $cc_presY.['fullStart']) {
$cc_presX.['hasConflict'] = true;
$cc_presY.['hasConflict'] = true;
}
}
*/
}
function setConflicts($events) {
for ($i = 0; $i < count($events); $i++) {
for ($j = 0; $i < count($events); $j++) {
// if it is not the same event
// if (i !== j) is the same $age['Peter']
if ($events[$i]['id'] !== $events[$j]['id']) {
checkFirst($events[$i], $events[$j]);
}
}
}
}
setConflicts($conflict_list);
I just keep getting a loop with undefined offset: (counting up to the 100k+ mark)
Notice: Undefined offset: 0 in
C:\wamp\www\projects\misc\conflict_check_new.php on line 49 Pres
Check:
Notice: Undefined offset: 0 in
C:\wamp\www\projects\misc\conflict_check_new.php on line 50 Pres
Check:
Notice: Undefined offset: 0 in
C:\wamp\www\projects\misc\conflict_check_new.php on line 49 Pres
Check:
The same logic could apply in PHP, but assuming you can get your events out into JavaScript and create an array of objects with start and end dates like so:
var events = [
{
id: 'event1',
start: new Date('1/1/1 5:00'),
end: new Date('1/1/1 6:00'),
hasConflict: false
},
{
id: 'event2',
start: new Date('1/1/1 5:30'),
end: new Date('1/1/1 6:30'),
hasConflict: false
},
{
id: 'event3',
start: new Date('1/1/1 7:30'),
end: new Date('1/1/1 8:30'),
hasConflict: false
}
]
You can compare events to see if the one that starts first, has an end time that's later the second one's start time.
function checkFirst (event1, event2) {
event1.start < event2.start
? checkConflict(event1, event2)
: checkConflict(event2, event1)
function checkConflict (first, second) {
if (first.end > second.start) {
first.hasConflict = second.hasConflict = true
}
}
}
Then you can check events against each other. Here's a not particularly efficient, but at least suitable loop:
function flagAllEventsWithConflicts (events) {
events.forEach(event1 => {
events.forEach(event2 => {
event1.id !== event2.id && checkFirst(event1, event2)
})
})
}
Update: The above function can also be written as a nested for loop:
function flagAllEventsWithConflicts (events) {
for (var i = 0; i < events.length; i++) {
for (var j = 0; j < events.length; j++ {
// if it is not the same event
// if (i !== j) is the same
if (events[i].id !== events[j].id) {
checkFirst(events[i], events[j])
}
}
}
}
Then check to see if hasConflict is true or false:
flagAllEventsWithConflicts(events)
console.table(events)
Run this fiddle and checkout the console
I have data in the following form
Array
(
[0] => Array
(
[event_id] => 2042632
[event_name] => Georgia Tech Yellow Jackets vs. North Carolina Tar Heels
[event_payment] => 156
[payment_status] => 1
[event_date] => 2014-01-29
)
[1] => Array
(
[event_id] => 2042632
[event_name] => Georgia Tech Yellow Jackets vs. North Carolina Tar Heels
[event_payment] => 89
[payment_status] => 1
[event_date] => 2014-01-29
)
[2] => Array
(
[event_id] => 2042632
[event_name] => Georgia Tech Yellow Jackets vs. North Carolina Tar Heels
[event_payment] => 772
[payment_status] => 1
[event_date] => 2014-01-29
)
[3] => Array
(
[event_id] => 2042633
[event_name] => Georgia Tech Yellow Jackets vs. North Carolina Tar Heels
[event_payment] => 256
[payment_status] => 0
[event_date] => 2013-12-29
)
)
All I want now to show data in the following format after getting from this array:
January
Event-name, payment, status
georgia.. 1234, 0
georgia.. 3456, 1
December
Event-name, payment, status
georgia.. 1234, 0
georgia.. 3456, 1
and so on and so forth.
please guide me how to do that..
Try
$result = array();
foreach($arr as $ar){
$date = DateTime::createFromFormat("Y-m-d", $ar['event_date']);
$month = $date->format('F');
$year = $date->format('Y');
$result[$year][$month][] = $ar;
}
See demo here
$res= array();
foreach($arr as $key => $val) // $arr is your actual array
{
$month = date('F-Y', strtotime($val['event_date']));
$res[$month][] = $val;
}
Now you get will result as
[January-2014] = array(a1,a2...)
[December-2014] = array(a1,a2...)
Here I only suggest how to sort an array by date. I hope you can do the rest of the work yourself.
function cmp($a, $b) {
return (new DateTime($a['event_date']))->getTimestamp() < (new DateTime($b['event_date']))->getTimestamp()? -1 : 1;
}
usort($array, 'cmp');
$curr_month = 0;
foreach ($array as $elem) {
// output elements of array based on month
// ...
}
Have this array
$date_and_currency_array = Array
(
[0] => Array
(
[number_of_input_row] => 1
[date_day] => 01
[date_month] => 12
[date_year] => 2013
[currency] => BGN
)
[1] => Array
(
[number_of_input_row] => 2
[date_day] => 01
[date_month] => 12
[date_year] => 2012
[currency] => DKK
)
[2] => Array
(
[number_of_input_row] => 3
[date_day] => 11
[date_month] => 12
[date_year] => 2013
[currency] => ILS
)
)
Then
foreach ( $date_and_currency_array as $i => $date_and_currency_value ) {
echo $date_and_currency_value['date_year']. ' __$date_and_currency_value[date_year]<br>';
if ($date_and_currency_value['date_year'] = 2013) {
echo '2013 ....<br>';
}//if
}//foreach
Here if ($date_and_currency_value['date_year'] = 2013) { expect to echo 2013 only 2 times, because there are only two [date_year] => 2013. But 2013 echo 3 times.
Please advice why 2013 echo 3 times.
Thanks to replies. My stupid negligence. Need to rest
Its because your assigning instead of comparing as you missed a = in your if statement
if ($date_and_currency_value['date_year'] == 2013) {
in this if ($date_and_currency_value['date_year'] = 2013) you should add two == that is if ($date_and_currency_value['date_year'] == 2013)
As here you have used single '=' condition will be true for each time the loop rotates so as answer given above you need to use '==' so that it exactly notifies compiler to compare as single '='is assignment operator.
so try out
if($date_and_currency_value['date_year'] == 2013)
{
echo "something";
}
This question already has answers here:
Display all the week numbers between two dates in PHP [duplicate]
(3 answers)
Closed 8 years ago.
Given a start and end date, I need to generate an array with year and week values.
For example:
Start Date: 2013-01-01
End Date: 2013-02-23
Generated Array:
Array ( [0] => Array ( [week] => 01 [year] => 2013 )
[1] => Array ( [week] => 02 [year] => 2013 )
[2] => Array ( [week] => 03 [year] => 2013 )
[3] => Array ( [week] => 04 [year] => 2013 )
[4] => Array ( [week] => 05 [year] => 2013 )
[5] => Array ( [week] => 06 [year] => 2013 )
[6] => Array ( [week] => 07 [year] => 2013 )
[7] => Array ( [week] => 08 [year] => 2013 ) )
Here is the code I'm using to generate this:
public static function getYearWeekRange($startdate, $enddate) {
$array = array();
$starttime = strtotime($startdate);
$endtime = strtotime($enddate);
while ($starttime <= $endtime) {
$year = date('Y', $starttime);
$week = date('W', $starttime);
$array[] = array('week' => $week, 'year' => $year);
$starttime = strtotime('+1 week', $starttime);
}
return $array;
}
My problem is that when I generate certain date ranges, I don't get the correct year value at the start of the 2013 year. For example:
Start Date: 2012-01-01
End Date: 2013-02-23
In this case, where it should have an subarray with year = 2013 and week = 01, it actually has it's year value equal to 2012.
If I were to switch the start date to 2013-01-05 for example, then there is no problem.
Can anyone offer a solution that would guarantee that my year and week values are always correct?
I was able to fix my problem using the following:
public static function getWeekRange($startdate, $enddate) {
$array = array();
$p = new DatePeriod(
new DateTime($startdate),
new DateInterval('P1W'),
new DateTime($enddate)
);
foreach ($p as $w) {
$array[] = array('year' => $w->format('o'), 'week' => $w->format('W'));
}
return $array;
}
I have the following output of an array using PHP. I need to do two things... First, I need to sort the array so it prints by the most recent date. I can't use a simple sort, because the date is outputted in the format mm/dd/yyyy (and not a regular time stamp) ...
Then I need to count how many rows exist for each year.
So, in the example below, I would need to know that there are ...
2 entries from 2010
2 entries from 2011
1 entry from 2012
Stop counting when there are no more rows
Since the year is not separate from the rest of the date digits, this also complicates things...
Array
(
[0] => Array
(
[racer_date] => 11/15/2010
[racer_race] => Test Row 4
[racer_event] => 321
[racer_time] => 16
[racer_place] => 12
[racer_medal] => 1
)
[1] => Array
(
[racer_date] => 7/15/2010
[racer_race] => Test Row 3
[racer_event] => 123
[racer_time] => 14
[racer_place] => 6
[racer_medal] => 0
)
[2] => Array
(
[racer_date] => 7/28/2011
[racer_race] => Test Row
[racer_event] => 123
[racer_time] => 10
[racer_place] => 2
[racer_medal] => 2
)
[3] => Array
(
[racer_date] => 10/9/2011
[racer_race] => Test Row 2
[racer_event] => 321
[racer_time] => 12
[racer_place] => 3
[racer_medal] => 3
)
[4] => Array
(
[racer_date] => 10/3/2012
[racer_race] => World Indoor Championships (final)
[racer_event] => 400m
[racer_time] => 50.79
[racer_place] => 1
[racer_medal] => 1
)
)
function cmp($a, $b)
{
if (strtotime($a["racer_date"]) == strtotime($b["racer_date"])) {
return 0;
}
return (strtotime($a["racer_date"]) < strtotime($b["racer_date"])) ? -1 : 1;
}
usort($array, "cmp");
call your array $array, and above code will sort it..
And to count entities you'll need to run foreach and check date('Y',strtotime($a["racer_date"])) in that foreach which will give you year in 4 digit..