Im currently trying to calculate the amount of periods (each period is 1 week, after a certain date or day). Lets say first period start on 01-01-2013 (tuesday) until 29-01-2013 (tuesday)(4 periods in total).
I have a table that looks like:
id | startDate (datetime) | endDate (datetime)
I have two input fields where a user can fill in a start date and end date. I would like to fill any date between 01-01-2013 and 29-01-2013 and decide how many times it passes a tuesday (the date the period starts) again.
So if I would select 01-01-2013 until 07-01-2013 would result in: 1, but if i would select 06-01-2013 till 09-01-2013 this would result in 2 and 06-01-2013 till 16-01-2013 would result in 3 etc.
To be clear, I dont want to know the amount of weeks between the two dates, only the amount of times it 'crosses' the same day (tuesday) that was given in the database. Every period is 1 week. Is there anyone that could help me out?
Use PHP's date() function.
$startday = strtotime($start_date_from_db);//date from db;
$endday = strtotime($end_date_from_db);//date from db;
$counter = 0;
for($i=$startday; $i<=$endday; $i+=86400) {
$current_day = date('w', $i);
if($current_day == 2) { //0 for sunday, 1 for monday, 2 for tuesday
$counter++;
}
}
When comparing dates a good method is:
1- transform the dates to timestamps:
$timestamp1 = strtotime($date1);
$timestamp2 = strtotime($date2);
2- do the desired operation, in this case:
$timebetween = $timestamp2 - $timestamp1;
3- Transform result (number of seconds) to desired value, in this case:
$weeks= $timebetween / 604800;
Related
I'm trying to get the number of times between two dates. I'm provided with 4 types of info: freq, interval, startDate, and endDate.
For example:
freq = weekly
interval = 1
startDate = 2019-03-10
endDate = 2019-03-24
I'm trying to get the number of times/dates/events are between those two dates with the given info. (The count or the number of events)
In this example, since the frequency is weekly and the interval is 1, it means repeat the event on the startDate every 1 week. If the interval was changed to 2, it would be every 2 weeks. If the frequency was changed to daily, and the interval was 3, it would be every 3 days.
In this example, the first event would be on 2019-03-10 and then the second event would be on 2019-03-17, and then the third would be on 2019-03-24. The count is 3 in this example because there are three dates.
I am trying to find the count.
Thanks
Well, if you use Datetime class or Carbon, you can easily loop through the days/weeks/months between those dates. For example, if your freq = weekly and interval = 1, given the startDate and endDate you provided, the code would be something like this:
use Carbon\Carbon;
$startDate = Carbon::create(2019,03,10,0,0);
$endDate = Carbon::create(2019,03,24,0,0);
$count = 0;
while(! $startDate->greaterThan($endDate) )
{
$count += 1;
if($freq === 'weekly')
{
$startDate->addWeeks($interval);
}
else if($freq === 'monthly')
{
$stardDate->addMonths($interval);
}
}
In this example i've made using carbon because it saves you a lot of time, but you could do this by using PHP Datetime Class.
I am struggling with the price calculation of Woocommerce Bookings for the type "days". If the price on a daterange (e.g. Monday to Wednesday or Wednesday-Saturday or Sunday-Tuesday...) is higher than on the other days.
So far I know how many days:
$days = date_diff($from, $to)->format('%d');
This question helps to get the number of single days: calculate sundays between two dates
But how do I get not only "sundays" but every daterange (e.g. from 6 to 2) with this:
$sundays = intval($days / 7) + ($from->format('N') + $days % 7 >= 7);
I guess I need to iterate through daterange and use this formula but I cannot figure out how.
You can use a completely different approach:
Create a DatePeriod object and loop through the Period object and increment a variable each time you encounter the range.
The following code achieve it but only return the number of complete range:
$from='2018/09/1';
$to='2018/09/31';
$start='Sunday';
$end='Thursday';
$go=false;
$period=new DatePeriod(date_create($from),date_interval_create_from_date_string('1 days'),date_create($to));
$nRange=0;
foreach($period as $date){
if($date->format('l')===$start){
$go=true;
}
if($go&&$date->format('l')===$end){
$go=false;
$nRange++;
}
}
print_r($nRange);
output :
4
It works fine for any chosen range.
However if the need is to get any valid day within the given range complete or not you can alter the previous code this way:
$from='2018/09/17';
$to='2018/09/31';
$start='Sunday';
$end='Thursday';
$day_num=['Monday'=>1,'Tuesday'=>2,'Wednesday'=>3,'Thursday'=>4,'Friday'=>5,'Saturday'=>6,'Sunday'=>7];
$start_num=$day_num[$start];
$end_num=$day_num[$end];
$period=new DatePeriod(date_create($from),date_interval_create_from_date_string('1 days'),date_create($to));
$nRange=0;
if($start_num===$end_num){
$valid_range=array_values($day_num);//keep the number of each day of the week
}
elseif($start_num>$end_num){
$valid_range=array_values($day_num);//keep the number of each day of the week
while($valid_range[0]!==$start_num){//rotate the values to keep the start day first
$pop=array_shift($valid_range);
array_push($valid_range,$pop);
}
$valid_range=array_slice($valid_range,array_search($start_num,$valid_range),$start_num-$end_num);//keep only the days in the chosen range
}else{
$valid_range=array_values($day_num);//keep the number of each day of the week
$valid_range=array_slice($valid_range,array_search($start_num,$valid_range),$end_num-$start_num); //keep only the days in the chosen range
}
$valid_range=array_flip($valid_range);//flip the array to make the search more fast
foreach($period as $date){
if(isset($valid_range[(int)$date->format('N')])){
$nRange++;
}
}
print_r($nRange);//output the number of valid days
ouput:
6
I have a script that a user can setup a frequency as to when they want it to run.
They specify
The month they want it to run
The day of the month
The time (24 hour format)
They do not specify the year, the script needs to find the next closest date that matches.
PHP
The way I propigate the dates is through an array of months the user chooses and I can output all the dates into a nice array
$scheduler_months = unserialize($row['scheduler_months']);
foreach ($scheduler_months as $scheduler_month) {
$next_date[] = $scheduler_month."/".$row['scheduler_date']." ".$row['scheduler_time'];
}
which will out put
Array ( [0] => 2/28 12:00 [1] => 4/28 12:00 [2] => 12/28 12:00 )
So now at this point I need to figure out what the next closest date based on today as the starting point will be, obviously if the next closest date is in the next year it needs to be smart enough to figure that out. I just have no idea how to find the next closest date based on the dates in the array.
It's quite easy to figure out the year of the dates - if you were to convert them to unix time using strtotime you can determine if this year's date was in the past or not and if it were, you can assign that date next year.
$scheduler_months = unserialize($row['scheduler_months']);
$now = strtotime("now"); # get the unix time in seconds 'now'
foreach ($scheduler_months as $scheduler_month) {
# $tmp will be holding the date in the form of YYYY-MM-DD HH:MM
$tmp = date("Y")."-".$scheduler_month."-".$row['scheduler_date']." ".$row['scheduler_time'];
if(strtotime($tmp) - $now < 0) # if date is in the past, assign it to the next year
$tmp = (date("Y")+1)."-".$scheduler_month."-".$row['scheduler_date']." ".$row['scheduler_time'];
$next_date[] = $tmp;
}
# Initialize $smallest and $smallest_key
$smallest = strtotime($next_date[0])-$now;
$smallest_key = 0;
foreach($next_date as $key => $val) {
$time_diff = strtotime($val) - $now;
if($time_diff < $smallest) {
$smallest_key = $key;
$smallest = $time_diff;
}
}
In the first part, I've modified your foreach loop to determine the correct year based on unix time. I've changed the date format to YYYY-MM-DD HH:MM. If the date's unixtime is less than the current unix time, then the next closest date is next year.
In the second part I initilize two variables - $smallest, which holds the smallest time in seconds relative to now and $smallest_key, which holds the array key for the smallest time.
Then I loop over $next_date and I look for the smallest time in seconds from now to either of the dates.
I need to calculate number of days between two dates.
Required date entered by me,fetch the record from the database by the given dates.
If the database have 'startdate' as 1Jan2015 'enddate' as 5Feb2015.
For January month it should return 30 and for February 5 days.
My table:
id Name Type Project Place Start Date End Date Details
1 Sai Local Site Bangalore 2015-09-03 11:32:47 2015-09-05 11:32:47 test
2 Ram Local IGCAR Chennai 2015-04-01 15:15:36 2015-04-09 15:15:36 Installation
3 Mani Local IGCAR Chennai 2015-04-16 15:16:18 2015-05-21 15:16:18 Training
My coding
///////////Employee Outstation(Travel) details/////////////
$employeeTravel = new EmployeeTravelRecord();
//date_start = '2015-04-01' ;
//date_end = '2015-04-30';
$TravelEntryList = $employeeTravel->Find("(travel_date between ? and ? or return_date between ? and ? )",array($req['date_start'], $req['date_end'],$req['date_start'], $req['date_end']));
foreach($TravelEntryList as $Travelentry){
$amount = (strtotime($Travelentry->return_date) - strtotime($Travelentry->travel_date));
}
For second record, it returns correct value, but for third record it calculates including May month. But i want only 30 days of april.
DATEDIFF() returns value in days from one date to the other.
select *,datediff( end Date, Start Date) as days from My table;
Please have a look at this post, you should find what you're looking for :
How to get the number of days of difference between two dates on mysql?
There is a function in PHP called as date_diff for difference between two dates.
<?php
$date1 = date_create("2013-03-15");
$date2 = date_create("2013-12-12");
$diff = date_diff($date1,$date2);
echo $diff->format("%R%a days");
?>
I'm running into a coder's block with PHP dates. Let me first paint the picture of what I want to happen. ex:
$user_join_date = new DateTime('2015-01-31');
$today_date = new DateTime('2015-04-30');
Every day a cron will be run and for this example, on every 31st (or 30th - 28th depending on the month) the system will calculate commission for this user based on orders and volume from the past month BETWEEN '2015-03-31' AND '2015-04-29'.
So what I need is two fold. First, I need to make sure I'm calculating the commission on the correct day ie: the monthly anniversary of their join date OR that same month's equivalent. Second, I need to find the time frame in between which I'll calculate commissions as demonstrated in the mysql snippit above.
For obvious reasons I can't just say:
if ($user_join_date->format('d') == $today_date->format('d')){
calc_commission();
}
Because this wouldn't get run every month. Let me know if I'm unclear on anything.
I think you're saying you want to credit each user on an integral number of months since her signup date. There's an aspect of MySQL's date arithmetic you will find very convenient -- INTERVAL n MONTH addition.
DATE('2015-01-30') + INTERVAL 1 MONTH ==> '2016-02-28'
DATE('2016-01-30') + INTERVAL 1 MONTH ==> '2016-02-29'
This feature deals with all the oddball Gregorian Calendar trouble around weekdays, quite nicely. I'm going to call the date the renewal date.
Now, let us say that the column signup contains the date/time stamp for when the user signed up. This expression determines the most recent monthly renewal date. In particular, if it is equal to CURDATE(), today is the renewal date.
DATE(signup) + INTERVAL TIMESTAMPDIFF(MONTH, DATE(signup), CURDATE()) MONTH
Next: This closely related (duh!) expression is equal to the previous month's renewal date.
DATE(signup) + INTERVAL TIMESTAMPDIFF(MONTH, DATE(signup), CURDATE())-1 MONTH
You could just take CURDATE() - INTERVAL 1 MONTH but this is much more accurate around Gregorian month-end monkey business. Try it: it works right even at the end of February 2016 (leap year day).
Now, you'll want to use transactions that happened beginning on the previous renewal date >=, up until the end of the day before < the present renewal date, in your computation. In MySQL filtering by that date range looks like this.
WHERE transdate >= DATE(signup) +
INTERVAL TIMESTAMPDIFF(MONTH, DATE(signup), CURDATE())-1 MONTH
AND transdate < DATE(signup) +
INTERVAL TIMESTAMPDIFF(MONTH, DATE(signup), CURDATE()) MONTH
$base_dt is your joining date. So If you pass it to checkIt function It will provide you true or false accordingly today's day is billing day or not.
$base_dt = new DateTime('2015-04-30', new DateTimeZone("America/Chicago"));
if(checkIt($base_dt)) {
echo "true";
//this is the day.
} else {
echo "false";
//this is not the day.
}
So the check it function should be like this .....
function checkIt($base_dt) {
$base_d = $base_dt->format('j'); //without zeroes
echo $base_d;
$today = new DateTime('now');
$d = $today->format('j');
echo $d;
if($base_d == $d) {
return true;
} else if($base_d>28) {
$base_dt->modify('last day of this month');
$dif_base = $base_dt->format('j') - $base_d;
//echo $dif_base;
$today->modify('last day of this month');
$diff_today = $today->format('j') - $d;
//echo $diff_today;
if(($base_d==31 && $diff_today==0)||($base_d==30 && $diff_today==0 && $d<30)||($base_d==29 && $diff_today==0 && $d<29)) {
return true;
}
if($dif_base==0 && $diff_today==0) {
return true;
}
}
return false;
}