bg17aw Posted March 3, 2017 Share Posted March 3, 2017 I want to offer a discount based on early booking but not sure how to get the discount that applies based on the current date. I have seen some usort examples but not very familiar to me. I want to keep using DateTime objects (not timestamps). $today = new DateTime(); $data['earlybooking'] = array( array('percentage' => '25', 'beforedate' => '10-12-2016' ), array('percentage' => '15', 'beforedate' => '31-03-2017' ), array('percentage' => '10', 'beforedate' => '30-04-2017' ), array('percentage' => '20', 'beforedate' => '31-01-2017' ) ); // foreach ? Or maybe usort? // usort example: http://stackoverflow.com/questions/7127764/sort-array-of-objects-by-date-field Any ideas? Thanks Quote Link to comment Share on other sites More sharing options...
Barand Posted March 3, 2017 Share Posted March 3, 2017 Firstly, you need to change those dates - they are not sortable. You need yyyy-mm-dd Quote Link to comment Share on other sites More sharing options...
bg17aw Posted March 3, 2017 Author Share Posted March 3, 2017 Firstly, you need to change those dates - they are not sortable. You need yyyy-mm-dd No, that not an issue when you are dealing with DateTime objects. Thanks for your input anyway Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted March 3, 2017 Share Posted March 3, 2017 No, that not an issue when you are dealing with DateTime objects. And yet you are using strings, not DateTime objects. So the real question is how to map those strings to DateTime objects, yes? Because usort() has nothing to do with your problem. As soon as the array elements can be compared with the standard operators, you just call sort(). Quote Link to comment Share on other sites More sharing options...
bg17aw Posted March 3, 2017 Author Share Posted March 3, 2017 (edited) And yet you are using strings, not DateTime objects. So the real question is how to map those strings to DateTime objects, yes? Because usort() has nothing to do with your problem. As soon as the array elements can be compared with the standard operators, you just call sort(). No, that's not an issue, there is actually a link in my code to an example on how to sort array of DateTime objects on date. The real question is how do I get the discount percentage I need, the only issue being a date (the booking date, which would be today) can be "beforedate" one, two or more dates. That is the only issue, sorry if it is not clear enough, I am not an English native and so on. So I can have a function like this: foreach ($earlybooking as $key => $val) { if ( new DateTime($val['beforedate']) >= $today) return $val['percentage']; } but would not be enough, because for example for today 03-03-2017, there are two possible answers. Edited March 3, 2017 by bg17aw Quote Link to comment Share on other sites More sharing options...
ginerjm Posted March 3, 2017 Share Posted March 3, 2017 There are never two possible answers if you keep your thinking straight. A date string with - in it will translate as dd-mm-yyyy or (if written better) yyyy-mm-dd. Decide which you are using and then stay that way. AS has been pointed out you are storing date values as strings and not datetime objects which is confusing to us as well as to you apparently. There would be no confusion if the array used dt objs instead of strings. Quote Link to comment Share on other sites More sharing options...
Barand Posted March 4, 2017 Share Posted March 4, 2017 You need to sort the array into ascending date order. Then loop through the array until you come to a date that is >= today. This is the percent that you want so you can now break out of the loop. Given the data you posted (but correcting the date format) you would have $data = array( array('percentage' => '25', 'beforedate' => '2016-12-10' ), array('percentage' => '15', 'beforedate' => '2017-03-31' ), array('percentage' => '10', 'beforedate' => '2017-04-30' ), array('percentage' => '20', 'beforedate' => '2017-01-31' ) ); // SORT BY DATE usort ($data, function($a, $b) { return strcmp($a['beforedate'], $b['beforedate']); }); // VIEW RESULTS $today = new DateTime(); $today->setTime(0,0,0); // don't want the time portion foreach ($data as $rec) { if ($today <= new DateTime($rec['beforedate'])) { $discount = $rec['percentage']; break; } } echo "Applicable discount today is {$discount}%"; //--> 15% 1 Quote Link to comment Share on other sites More sharing options...
Barand Posted March 4, 2017 Share Posted March 4, 2017 (edited) Alternative solution mysql> SELECT * FROM bookingdates; +-----------------+------------+------------+ | bookingdates_id | beforedate | percentage | +-----------------+------------+------------+ | 1 | 2017-12-10 | 25 | | 2 | 2017-01-31 | 20 | | 3 | 2017-03-31 | 15 | | 4 | 2017-04-30 | 10 | +-----------------+------------+------------+ SELECT percentage FROM bookingdates WHERE beforedate = ( SELECT MIN(beforedate) FROM bookingdates WHERE beforedate >= CURDATE() ); +------------+ | percentage | +------------+ | 15 | +------------+ Edited March 4, 2017 by Barand Quote Link to comment Share on other sites More sharing options...
bg17aw Posted March 4, 2017 Author Share Posted March 4, 2017 There are never two possible answers if you keep your thinking straight. A date string with - in it will translate as dd-mm-yyyy or (if written better) yyyy-mm-dd. Decide which you are using and then stay that way. AS has been pointed out you are storing date values as strings and not datetime objects which is confusing to us as well as to you apparently. There would be no confusion if the array used dt objs instead of strings. There is absolutely no confusion, and definetely not regarding the date format, you are missing the point here. The only issue is how to get the percentage taking into account that current date will be "before" more than one of the "beforedates". That's it. Please see Barand answer, he got it. Don't assume you know more than the person who asked the question. Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted March 4, 2017 Share Posted March 4, 2017 (edited) There is absolutely no confusion, and definetely not regarding the date format, you are missing the point here. You realize that Barand's entirey suggestion is based on changing the date format, right? So, yes, you are indeed horribly confused. Edited March 4, 2017 by Jacques1 Quote Link to comment Share on other sites More sharing options...
Barand Posted March 4, 2017 Share Posted March 4, 2017 Quite true. If I used the original unsortable date formats ... $data = array( array('percentage' => '25', 'beforedate' => '10-12-2016' ), array('percentage' => '15', 'beforedate' => '31-03-2017' ), array('percentage' => '10', 'beforedate' => '30-04-2017' ), array('percentage' => '20', 'beforedate' => '31-01-2017' ), ); ...the result is 10% as the result of sorting those dates is 10-12-2016 30-04-2017 31-01-2017 31-03-2017 Quote Link to comment Share on other sites More sharing options...
bg17aw Posted March 4, 2017 Author Share Posted March 4, 2017 You realize that Barand's entirey suggestion is based on changing the date format, right? So, yes, you are indeed horribly confused. Dude, the date format is irrelevant, I already mentioned I want to use DateTime objects and provided a link with the code to sort using those. If you're using DateTime objects, the format is irrelevant. Barand solution is not the solution I'll be using, I was only pointing out the issue was HOW to get the percentage when the condition is met more than once. I was not asking how I can sort the array, but if I need to, is there another way. Barand is doing string comparison, which of course is totally wrong when dealing with dates, I would advise to always stick to DateTime objects when dealing with datetime in PHP. Again, I already indicated a solution of sorting using DateTime objects: usort($array, function($a, $b) { return $a['date']->format('U') - $b['date']->format('U'); }); Or, another example: usort($arr, function($a, $b) { $ad = new DateTime($a['dateTime']); $bd = new DateTime($b['dateTime']); if ($ad == $bd) { return 0; } return $ad < $bd ? -1 : 1; }); You could also use this if you're worried about format: foreach ($data as $rec) { if ($today <= DateTime::createFromFormat('d-m-Y', $rec['beforedate'])) { $discount = $rec['percentage']; break; } } Take it easy, Just because Barand didn't provide a solution using DateTime objects it doesn't mean it would never work. I certainly do not want strcomp or strtotime Quote Link to comment Share on other sites More sharing options...
bg17aw Posted March 4, 2017 Author Share Posted March 4, 2017 Quite true. If I used the original unsortable date formats ... $data = array( array('percentage' => '25', 'beforedate' => '10-12-2016' ), array('percentage' => '15', 'beforedate' => '31-03-2017' ), array('percentage' => '10', 'beforedate' => '30-04-2017' ), array('percentage' => '20', 'beforedate' => '31-01-2017' ), ); ...the result is 10% as the result of sorting those dates is 10-12-2016 30-04-2017 31-01-2017 31-03-2017 Thanks. That's because you are using string comparison, I want to avoid any solution not involving the use of DateTime objects Quote Link to comment Share on other sites More sharing options...
bg17aw Posted March 4, 2017 Author Share Posted March 4, 2017 I'll probably go with this solution, this would eliminate the need to sort the array: function get_earlybooking_percentage($earlybooking) { $today = new DateTime(); $matching = array(); foreach ($earlybooking as $item) { if ($today < DateTime::createFromFormat('d-m-Y', $item['beforedate'])) { $matching[] = $item['percentage']; } } return max($matching); } Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted March 5, 2017 Share Posted March 5, 2017 (edited) This time, I'm going to avoid cheap jokes about Wordpress users who think they're programmers. Let me put it this way: If you ever want to solve real problems and get past the copy-and-paste-from-Stackoverflow stage, there's a lot for you to learn. What you just can't seem to understand is the concept of choosing the right data structure. You've now spent at least two days working on a trivial interval search, and you still haven't managed to do anything but add another layer of duct tape to your code. Have you never wondered why you need so much time and help for simple problems? I'll give you a hint: Storing dates as strings in an unsorted array is probably the dumbest possible structure for an interval search. Edited March 5, 2017 by Jacques1 Quote Link to comment Share on other sites More sharing options...
bg17aw Posted March 5, 2017 Author Share Posted March 5, 2017 (edited) This time, I'm going to avoid cheap jokes about Wordpress users who think they're programmers. Let me put it this way: If you ever want to solve real problems and get past the copy-and-paste-from-Stackoverflow stage, there's a lot for you to learn. What you just can't seem to understand is the concept of choosing the right data structure. You've now spent at least two days working on a trivial interval search, and you still haven't managed to do anything but add another layer of duct tape to your code. Have you never wondered why you need so much time and help for simple problems? I'll give you a hint: Storing dates as strings in an unsorted array is probably the dumbest possible structure for an interval search. You're very wise to avoid cheap jokes. Not wise enough to avoid wasting my time and yours. Surely you do realize you posted about 5 times in this topic without any contribution. Just innuendos and cheap jokes you don't make but mention anyway i couldn't take a hint or anything else useful from your posts, no offence. Thanks a lot to Barand who gave it a shot. I also took the time to post my solution. Hope you find some better use of your time. I surely didn't spend two days working on a trivial interval search I could have just copy pasted Barand solution or the Stackoverflow ones, but I actually came up with my own and pretty happy with it. The data structure is good enough, to save in the DB and retrieve easily. As you can see in my solution above, I do NOT have to change the date format as you kept on saying for some reason. Peace! PS: the "I know there is a better way to do it but not telling" attitude childish and froned upon on all forums. This will not bring a lot of new members in here. I probably avoid this community because of people like you Edited March 5, 2017 by bg17aw Quote Link to comment Share on other sites More sharing options...
Jacques1 Posted March 5, 2017 Share Posted March 5, 2017 The effeminate special-little-snowflake attitude isn't going to help you in any IT community. If you want people to take you seriously, learn to shut up and listen. There's nothing worse than newbies who try to sound smart when they clearly have no idea what they're talking about. I do NOT have to change the date format I said data format, not date format. Stop babbling, then you might actually get what people are telling you. Quote Link to comment 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.