Jump to content

Early booking reservation system using DateTime


bg17aw

Recommended Posts

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

 

 

Link to comment
Share on other sites

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().

Link to comment
Share on other sites

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 by bg17aw
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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%
  • Like 1
Link to comment
Share on other sites

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 by Barand
Link to comment
Share on other sites

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. 

Link to comment
Share on other sites

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 by Jacques1
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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

Link to comment
Share on other sites

 

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

Link to comment
Share on other sites

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);
}
Link to comment
Share on other sites

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 by Jacques1
Link to comment
Share on other sites

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 by bg17aw
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.