I'm sorting an array as:
function date_compare($a, $b)
{
$t1 = strtotime($a['date']);
$t2 = strtotime($b['date']);
return $t1 - $t2;
}
usort($array, 'date_compare');
However, as you can see the output below, dates are not sorted. Any idea why? Thanks
Array
(
[0] => Array
(
[id] => 16870
[date] => Tue, 22 Mar 2011 13:12:19 +1100
[bar] => Foo
)
[1] => Array
(
[id] => 16871
[bar] => foo
[date] => Mon, 21 Mar 2011 23:06:32 -0500 (CDT)
)
[2] => Array
(
[id] => 16872
[bar] => foo
[date] => Tue, 22 Mar 2011 00:37:01 -0500 (CDT)
)
}
They're sorted just fine if you take the timezone into account, which strtotime does.
As others have pointed out, the dates are being sorted properly. You may want to do something like:
foreach ($dates as $i => $date)
{
$dates[$i]['ts'] = strtotime($date['date']);
$dates[$i]['date'] = date('Y-m-d H:i:s', $dates[$i]['ts']);
}
usort($dates, function($a, $b) { return $a['ts'] - $b['ts']; });
Here I'm creating a ts property for each date so strtotime() doesn't need to be called twice per sort comparison. Second, I'm changing the date to be in the local timezone. You can adjust the format string as you want.
Alternatively, you could just unset() the date component of the array and call date() directly on the ts component when you want to print it.
Related
I have read a standard RSS feed into simpleXML and get the following after converting to an array:
[0] => SimpleXMLElement Object (
[guid] => https://www.zazzle.com/scissors_by_any_other_name_dreadful_pun_t_shirt-235586301981812394
[pubDate] => Wed, 23 Aug 2017 13:41:08 GMT
[title] => SimpleXMLElement Object ( )
[link] => https://www.zazzle.com/scissors_by_any_other_name_dreadful_pun_t_shirt-235586301981812394
[author] => HightonRidley
[description] => SimpleXMLElement Object ( )
[price] => $30.15
)
[1] => SimpleXMLElement Object (
[guid] => {not enough reputation points to show link}
[pubDate] => Sat, 19 Aug 2017 15:53:19 GMT
[title] => SimpleXMLElement Object ( )
[link] => {not enough reputation points to show link}
[author] => HightonRidley
[description] => SimpleXMLElement Object ( )
[price] => $15.65 )
)
This is the code used to create and display the above
$sortable = array();
foreach($product_grid->channel->item as $node) {
$sortable[] = $node;
}
print_r($sortable);
To prove to myself it's working and accessible as intended I used this
foreach ($sortable as $rssitem) {
echo "<br>" . $rssitem->pubDate;
}
echo "<br>".$sortable[0]->pubDate;
echo "<br>".$sortable[1]->pubDate;
and got this output
Wed, 23 Aug 2017 13:41:08 GMT
Sat, 19 Aug 2017 15:53:19 GMT
Wed, 23 Aug 2017 13:41:08 GMT
Sat, 19 Aug 2017 15:53:19 GMT
...but when I try to sort using usort, I get no output and Firefox console tells me I have a server error 500
Here's how I'm using usort
usort($sortable, function($a, $b)
{
return strtotime($a->pubDate) > strtotime($b->pubDate);
});
I've checked various questions/answers on using usort here and as many other places as I can find online but to no avail.
Can someone please tell me how to reference the various elements of $sortable from within that anonymous function. I will be doing other sorts using other elements once I get this first one cracked.
Thanks!
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");
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 some date, like:
20 November 06:10
12 November 08:12
10 October 13:23
There all in the past 6 months, Now I want to strtotime() them, but they are all un complete (lack of year), how to make some process so that I could strtotime() them?
Try this:
$dates = array("10 October 13:23", "12 November 08:12", "10 October 13:23");
foreach($dates as $d){
$exploded = explode(" ", $d);
$newDate = array_slice($exploded, 0,2,true)+array(2=>"2012")+array(3 => $exploded[2]);
//print_r($newDate);
$time = strtotime(implode($newDate));
echo $time."<br/>";
}
The output i got is:
1349868180
1352704320
1349868180
The logic is:
You lack the year, so I exploded the dates into an array to slice them, insert the year (the +array(2=>"2012") part) and glue them again with implode, and then run the strtotime.
This work only for this year, so you can use this logic to add the year to all your dates, or in the future there will be absolutely no way to filter dates from different years.
I added the dates into an array for loop through all of them, you can use the loop other ways, depending on where you have all your dates stored. For example if they are in a database you can include the script in the while($row = mysqli_fetch_assoc($result)) part where $d would be $row['date'] instead.
You should use the DateTime class and its createFromFormat and getTimeStamp methods instead of strtotime.
print_r(date_parse_from_format("d F H:i", '20 November 06:10'));
gives you:
Array
(
[year] =>
[month] => 11
[day] => 20
[hour] => 6
[minute] => 10
[second] => 0
[fraction] =>
[warning_count] => 0
[warnings] => Array
(
)
[error_count] => 0
[errors] => Array
(
)
[is_localtime] =>
)
I need to create a PHP function that will loop through a multi-dimensional array and return a value which represents the sum of a certain key, where the value of another key is <= the date value passed into the function. Here is a sample array of the data array:
Array
(
[Nov 18, 2011] => Array
(
[C] => 100
[I] => 100
[M] => 100
)
[Nov 22, 2011] => Array
(
[C] => 200
[I] => 200
)
[Nov 29, 2011] => Array
(
[C] => 300
[I] => -300
)
)
There will never be more than these 3 categories [C], [I] and [M] and the values for each date should be considered a running sum.
So, how do I calculate the value of the [C] category as of the Nov 22, 2011 date? The correct value is of course 300. (Being 100 from Nov 18 + 200 from Nov 22)
What if I needed to calculate the value of [I] as of Nov 29, 2011? The correct answer in this example would be 0. (Being 100 + 200 - 300)
I'm open to ideas on how best to achieve this. My instinct is to have some kind of function and then pass in the category and date values. Thanks.
Depends on how many times you're likely to want to do this and if you'll need to do it for each category, etc whether or not you use a function or just a simple loop.
Either way you could put the following into a function and just pass in $target_date and the category (replacing the hard-coded "C" I'm using for this example):
$c_total = 0;
foreach($main_array as $date => $sub_array)
{
if($date <= $target_date)
{
$c_total += $sub_array["C"];
}
}
EDIT: For clarity here's the function using strtotime() to convert the date values to timestamps for easier comparison:
function getCategoryTotal($target_date, $category)
{
$c_total = 0;
$target_date = strtotime($target_date);
foreach($main_array as $date => $sub_array)
{
if(strtotime($date) <= $target_date)
{
$c_total += $sub_array[$category];
}
}
return $c_total;
}