Calculate season prices - php

I want to calculate season prices.
The beginning and ending dates of the seasons should be 'the last Saturday of this month' instead of '2016-31-12'.
The only problem for me is that I don't know how to loop trough the array called 'period' when there is a period booked with a different year number.
To clear things up, 'the last Saturday of this month' changes in the next year.
Example:
$beginseason1 = new DateTime('December');
$beginseason1->modify('last saturday of this month');
My code:
<?php
// declare season dates
$startdate = new DateTime('2016-12-31');
$enddate = new DateTime('2018-04-30');
$beginseason1 = new DateTime('2016-01-01');
$endseason1 = new DateTime('2016-03-30');
$beginseason2 = new DateTime('2016-03-31');
$endseason2 = new DateTime('2016-04-30');
$beginseason3 = new DateTime('2016-05-01');
$endseason3 = new DateTime('2016-12-31');
// get period of booked dates and put them in a array
$period = new DatePeriod(
new DateTime($startdate->format('Y-m-d')),
new DateInterval('P1D'),
new DateTime($enddate->format('Y-m-d'))
);
//declare variables below
$price = 0;
$daysinseason1 = 0;
$daysinseason2 = 0;
$daysinseason3 = 0;
// loop trough array and check every date with season prices
foreach($period as $date)
{
if($date->format('m-d') >= $beginseason1->format('m-d') && $date- >format('m-d') <= $endseason1->format('m-d')){
echo $date->format('m-d') . "<br/>";
$price = $price + 25;
$daysinseason1++;
}
if($date->format('m-d') >= $beginseason2->format('m-d') && $date->format('m-d') <= $endseason2->format('m-d')){
echo $date->format('m-d') . "<br/>";
$price = $price + 25;
$daysinseason2++;
}
if($date->format('m-d') >= $beginseason3->format('m-d') && $date->format('m-d') <= $endseason3->format('m-d')){
echo $date->format('m-d') . "<br/>";
$price = $price + 25;
$daysinseason3++;
}
}
echo "season 1: " . $daysinseason1 . "<br/>";
echo "season 2: " . $daysinseason2 . "<br/>";
echo "season 3: " . $daysinseason3 . "<br/>";
?>
My code does the trick but it doesn't matter if the year is 2016 or 2018 31-12 is alway the last Saturday of December.
And also the beginning of season 1 occur in 2016 but the ending in 2017.
How can I program this the right way?

Related

I want to set the winning day of the event as a weekday, but is it possible to resolve the error?

// holiday array
$holy = [
'2020-12-23',
'2020-12-24',
'2020-12-25',
'2020-12-28',
'2020-12-29',
];
$inputDate = '2020-12-23'; // input
$outputDate = get_date($inputDate);
echo "Winning Day: " . $outputDate . "<br />";
echo "<br />";
function get_date($chkDate)
{
global $holy;
$chkDateYoil = date("w", strtotime($chkDate)); // sat(6), sun(0)
if ($chkDateYoil == 6) {
// Saturday when + 2
$timestamp = strtotime($chkDate . " +2 days");
$chkDate = date("Y-m-d", $timestamp);
} else if ($chkDateYoil == 0) {
// Sunday when + 1
$timestamp = strtotime($chkDate . " +1 days");
$chkDate = date("Y-m-d", $timestamp);
}
// If it's a weekday, compare it array
foreach ($holy as $key => $holyday) {
if ($chkDate == $holyday) {
// holiday when + 1
$day_plus = 8 - $chkDateYoil;
$timestamp = strtotime($chkDate." +".$day_plus." days");
$chkDate = date("Y-m-d", $timestamp);
}
}
return $chkDate;
}
Hello, let me ask a question.
The following codes are:
Is the input value weekend?
Or are they included in the array?
in accordance with the judgment
Weekday extraction code.
But there is an error.
in my estimation
December 30th is supposed to come out.
By the way, January 2, 2021 is the result.
Why is that?
sorry
i don't write english very well
Thank you for reading.
The problem is in this line: $day_plus = 8 - $chkDateYoil;, which is calculating the date of the next Monday the first time it's executed.
You're then looping through the rest of the $holy array, and updating $chkDate if necessary, but you're not recalculating the value of $chkDateYoil, so the output depends on the day of the week you run this. Today (23rd December) it stops on 2nd January
Your code can be simplified by just incrementing the date by 1 day and performing the checks again, continuing until you get a result. I've also used the PHP function in_array() to simplify the search of the $holy array, and incorporated it into the same test as Saturday and Sunday.
// holiday array
$holy = [
'2020-12-23',
'2020-12-24',
'2020-12-25',
'2020-12-28',
'2020-12-29',
];
$inputDate = '2020-12-23'; // input
$outputDate = get_date($inputDate);
echo "Winning Day: " . $outputDate . "<br />";
echo "<br />";
function get_date($chkDate)
{
global $holy;
do {
$chkDateYoil = date("w", strtotime($chkDate)); // sat(6), sun(0)
if (($chkDateYoil == 0) || ($chkDateYoil == 6) || (in_array($chkDate, $holy))) {
$timestamp = strtotime($chkDate . " +1 days");
$chkDate = date("Y-m-d", $timestamp);
} else {
return $chkDate;
}
} while (true);
}

Checking for the 5th recurrence regarding to startdate. Recurring on specific weekday in the month

I have got a script that repeats activitities.
When the repeat settings are:
repeat "the 2nd tuesday every 2 months, stop at 5 instances" (like google calendar would do).
I can accomplish "the 2nd tuesday every 2 months" with the script below:
<?php
$pubDay = 19;
$pubMonth = 7;
$pubYear = 2017;
$repeatMonths = 2;
$newMonth = $pubMonth;
$newYear = $pubYear;
$raisedMonth = $pubMonth + $repeatMonths;
if ( $raisedMonth > 12 ) {
$newMonth = ($raisedMonth) % 12; // off 12 at starts at 1
$newYear = $pubYear + 1;
} else {
$newMonth = $raisedMonth;
}
$occurenceInMonth = ceil($pubDay / 7); // determine the weekday occurence in the month (b.e. the "2nd thursday")
$dates = array();
foreach (getWeekDayDates($pubDow, $newYear, $newMonth) as $weekdaydate) {
$dates[] = $weekdaydate->format("Y-m-d");
}
// we need the x occurence (-1)
$newPubDate = isset($dates[$occurenceInMonth -1]) ? $dates[$occurenceInMonth -1] . " " . $pubHour . ":" . $pubMin : "";
echo $newPubDate;
function getWeekDayDates($weekday, $y, $m) {
return new DatePeriod(
new DateTime("first " . $weekday . " of $y-$m"),
DateInterval::createFromDateString('next ' . $weekday),
new DateTime("next month $y-$m-01")
);
}
?>
This works like a charm.
But now i need to check wether it is the 5th instance, starting at 17-9-2016.
My script is now like this:
// get the end date
$startdate = "2016-09-17";
$repeatMonths = 2;
$endTime = strtotime($startdate . " +" . ($repeatMonths * $reps) . " months");
if ( $endTime >= strtotime($newPubDate) ) {
$doRepeat = true;
}
But this can go wrong!
By example when the repetitons starts (startddate) at saturday 4-7 and it repeats every first sunday.
When the sunday in the last repetition is on the 6th of the month. The script above returns false, but it shouldnt't.
How can i check on a simple way if it is the 5th occurence?
I would create an array which holds DateTime objects of the next 5 "2nd tuesdays of the month":
$startdate = new \DateTime('second tue of february 2017');
$dates = array();
$repetitions = 5;
for ($i=0; $i<$repetitions; $i++) {
$dates[] = clone $date->modify('+1 month');
}
Using this array it should be easy to check, whether the date is reached or not yet.

Calculate the weeks between 2 dates manually in PHP

I'm trying to calculate the number of months and weeks since a particular date instead of from the beginning of the year.
It shouldn't follow calendar months but should instead count a month as every 4 weeks, and begin from a specified date. I need to be able to display the number of months, and also what week it is (1, 2, 3 or 4).
I want to put in a start date, and have it then count what month and week is it from that start date e.g if the start date is set to Mon 1st August it should show Month 1, Week 1 and so on.
My code is below. I tested it with some different start dates. Here's a list of what the code below generates and what it should display
Jun-20: Should be Week 2 - Shows as Week 0
Jun-27: Should be Week 1 - Shows as Week 3
Jul-04: Should be Week 4 - Shows as Week 2
Jul-11: Should be Week 3 - Shows as Week 1
Jul-18: Should be Week 2 - Shows as Week 0
$monthNumber = 5;
$monthStartDate = '2016-06-13';
$currentStartWeekDate = date('l') != 'Monday' ? date("Y-m-d", strtotime("last monday")) : date("Y-m-d"); // get the current week's Monday's date
$weekDateCounter = $monthStartDate;
$currentWeekNumber = 0;
while ($weekDateCounter != $currentStartWeekDate){
$currentWeekNumber += 1;
$weekDateCounter = date("Y-m-d", strtotime($weekDateCounter . "+7 days"));
//
if ($currentWeekNumber == 4){
$currentWeekNumber = 0; // reset week number
$monthNumber += 1; // increment month number
}
}
I am really at a loss with this and could use any help!
Your approach seems overly complicated:
function weekCounter($startDate,$endDate=null){
//use today as endDate if no date was supplied
$endDate = $endDate? : date('Y-m-d');
//calculate # of full weeks between dates
$secsPerWeek = 60 * 60 * 24 * 7;
$fullWeeks =
floor((strtotime($endDate) - strtotime($startDate))/$secsPerWeek);
$fullMonths = floor($fullWeeks/4);
$weeksRemainder = $fullWeeks % 4; // weeks that don't fit in a month
//increment from 0-base to 1-base, so first week is Week 1. Same with months
$fullMonths++; $weeksRemainder++;
//return months and weeks in an array
return [$fullMonths,$weeksRemainder];
}
You can call the function this way, and capture months and weeks:
//list() will assign the array members from weekCounter to the vars in list
list($months,$weeks) = weekCounter('2016-06-07'); //no end date, so today is used
//now $months and $weeks can be used as you wish
echo "Month: $months, Week: $weeks"; //outputs Month: 2, Week: 2
Live demo
The DateTime classes could make this much simpler for you. Documentation for them is here: http://php.net/manual/en/book.datetime.php
Try this out:
$date1 = new DateTime('2016-04-01');
$date2 = new DateTime('2016-07-24');
$diff = $date1->diff($date2);
$daysInbetween = $diff->days;
$weeksInbetween = floor($diff->days / 7);
$monthsInbetween = floor($weeksInbetween / 4);
print "Days inbetween = $daysInbetween" . PHP_EOL;
print "Weeks inbetween = $weeksInbetween" . PHP_EOL;
print "Months inbetween = $monthsInbetween" . PHP_EOL;
print "Total difference = $monthsInbetween months and "
. ($weeksInbetween - ($monthsInbetween * 4)) . " weeks" . PHP_EOL;
<?php
/**
* AUTHOR : VEDAVITH RAVULA
* DATE : 13122019
*/
function get_weeks($startDate = NULL,$endDate = NULL)
{
if(is_null($startDate) && is_null($endDate))
{
$startDate = date('Y-m-01');
$endDate = date('Y-m-t');
}
$date1 = new DateTime($startDate);
$date2 = new DateTime($endDate);
$interval = $date1->diff($date2);
$weeks = floor(($interval->days) / 7);
if(($date1->format("N") > 1) && ($date1->format("D") != "Sun"))
{
$diffrence = "-".( $date1->format("N"))." Days";
$date1 = $date1->modify($diffrence);
}
for($i = 0; $i <= $weeks; $i++)
{
if($i == 0)
{
$start_date = $date1->format('Y-m-d');
$date1->add(new DateInterval('P6D'));
}
else
{
$date1->add(new DateInterval('P6D'));
}
echo $start_date." - ".$date1->format('Y-m-d')."\n";
$date1->add(new DateInterval('P1D'));
$start_date = $date1->format('Y-m-d');
}
}
//function call
get_weeks("2021-11-01", "2021-11-14");

PHP. How to get a bimonthly recurring event?

I'm trying many approaches but then I get stuck half way.
Let's say order was created today. I need to display when the next recurring order will happen. So I have order created June 13, 2012. Then I have set the schedule to bimonthly recurring order, every 1st of month. How to calculate when the next recurring order will happen? The answer is August 1st.
If someone can outline an approach it would be very useful, it doesn't have to be code. This is what I have so far...
// first, get starting date
$start_date_month = date('m', strtotime($start_date));
// get this year
$this_year = date('Y');
// if this month is december, next month is january
$this_month = date('m', $timestamp_month);
if($this_month == 12){
$next_month = 1;
// if this month is not december add 1 to get next month
}else{
$next_month = $this_month + 1;
}
// get array of months where recurring orders will happen
$months = array();
for ($i=1; $i<=6; $i++) {
$add_month = $start_date_month+(2*$i); // 2, 4, 6, 8, 10, 12
if($add_month == 13){$add_month = 1;$year = $this_year+1;}
elseif($add_month == 14){$add_month = 2;$year = $this_year+1;}
elseif($add_month == 15){$add_month = 3;$year = $this_year+1;}
elseif($add_month == 16){$add_month = 4;$year = $this_year+1;}
elseif($add_month == 17){$add_month = 5;$year = $this_year+1;}
elseif($add_month == 18){$add_month = 6;$year = $this_year+1;}
elseif($add_month == 19){$add_month = 7;$year = $this_year+1;}
elseif($add_month == 20){$add_month = 8;$year = $this_year+1;}
else{$year = $this_year;}
echo $what_day.'-'.$add_month.'-'.$year.'<br />';
$months[] = $add_month;
}
echo '<pre>';
print_r($months);
echo '</pre>';
I don't want to simply find what's the date in two months from now. Let's say order created June 1. Next recurring order is August 1. Then let's say now, today is September 1st, but next recurring order is October 1st. See my dilemma?
Just take the current month, so since it's June, we get 6. 6 mod 2 == 0. Next month is July, we get 7. 7 mod 2 == 1.
So just check if current month % 2 == (first month % 2).
Then just check if it's the 1st of the month.
In PHP modulus is defined with the percentage symbol.
$month = date('n');
$createdMonth = 6;
if($month % 2 == $createdMonth % 2){
// stuff
}
You might find the library called When useful for this (I'm the author).
Here is code which will get you the next 2 recurring monthly dates (from todays date):
include 'When.php';
$r = new When();
$r->recur(new DateTime(), 'monthly')
->count(2)
->interval(2) // every other month
->bymonthday(array(1));
while($result = $r->next())
{
echo $result->format('c') . '<br />';
}
// output
// 2012-08-01T13:33:33-04:00
// 2012-10-01T13:33:33-04:00
Taking this a step further, you likely only want to find the 2 first business days:
include 'When.php';
$r = new When();
$r->recur(new DateTime(), 'monthly')
->count(2)
->interval(2) // every other month
->byday(array('MO', 'TU', 'WE', 'TH', 'FR')) // week days only
->bymonthday(array(1, 2, 3)) // the first weekday will fall on one of these days
->bysetpos(array(1)); // only return one per month
while($result = $r->next())
{
echo $result->format('c') . '<br />';
}
// output
// 2012-08-01T13:33:33-04:00
// 2012-10-01T13:33:33-04:00
Also note, the code is currently under a rewrite -- it works well but it is a little confusing and not well documented.
strtotime to the rescue:
<?php
date_default_timezone_set('Europe/London');
$d = new DateTime('2012-01-31');
$d->modify('first day of +2 months');
echo $d->format('r'), "\n";
?>
Let's say you want the next six orders:
$order_date = '6/13/2012';
$start = date('Y-m-01', strtotime($order_date));
$order_count = 6;
$future_orders = array();
$next = strtotime('+2 months', strtotime($start));
while(count($future_orders) < $order_count){
$future_orders[] = date('m/d/Y',$next);
$next = strtotime('+2 months', $next);
}
This can, obviously, be improved upon, but it should get you started ...
I got this:
$today = new DateTime();
$target_date = $today->modify("first day of +2 months");
echo "Your event is on " . $target_date->format("d/m/Y") . "!";

end date validation

I would like validate the current date with question posted date if date difference is greater then 1 day then it needs to show in over due question also this will not consider the array of dates which are already i having in my array.
Like if a question posted on 20-July-11.
exemption date array {'21-July-11', ... etc}
current date is 22-July-11
then the output needs to be shown like question is waiting for 1 day instead of 2 days.
can any one help on it.
That is some example code I have created for you to calculate the due date. When you submit a question, calculate the due date that way and store it in the database with entry for that question...
<?php
$daysDue = 2;
$exDatesArray = array("2011-07-21", "2011-07-23"); //array with all your holiday dates.
$question_1_Date = "2011-07-21";
$question_2_Date = "2011-07-18";
$question_3_Date = "2011-07-20";
echo "Holidays on: ";
foreach( $exDatesArray AS $exdate )
{
echo $exdate . ", ";
}
echo "<br/><br/>";
echo "submit date -> due date<br/>";
echo $question_1_Date . " -> " . calculateDueDate( $question_1_Date, $exDatesArray, $daysDue ) . "<br/>";
echo $question_2_Date . " -> " . calculateDueDate( $question_2_Date, $exDatesArray, $daysDue ) . "<br/>";
echo $question_3_Date . " -> " . calculateDueDate( $question_3_Date, $exDatesArray, $daysDue );
function calculateDueDate( $date, $exDates, $daysDue )
{
//start with day 1
$count = 1;
//now we loop from day one to due days
while( $count <= $daysDue )
{
//add one day to start date
$date = add_date( $date, 1 );
//check if that new date is a holiday
if( !in_array($date , $exDates) )
{
//only if it is not a holiday we increase counter, otherwise we dont count that day towards due period
$count++;
}
}
//return calculated due date
return $date;
}
function add_date($date,$days)
{
$cd = strtotime($date);
return date('Y-m-d', mktime(0,0,0,date('m',$cd),date('d',$cd) + $days, date('Y',$cd)));
}
?>
Output:
Holidays on: 2011-07-21, 2011-07-23,
submit date -> due date
2011-07-21 -> 2011-07-24
2011-07-18 -> 2011-07-20
2011-07-20 -> 2011-07-24
//convert date to unixtime (seconds)
$question_sec = strtotime($question);
//subtract
$diff = time() - $question_sec;
$days = $diff / 60*60*24;
echo "$days old";

Categories