I am creating an algorithm that must return two intervals between two dates:
$interval_day (between 6am and 9pm)
$interval_night (between 9pm and 6am)
Currently, I managed to have the overall interval between these two dates for the day. However, I now need a daytime interval and a nighttime interval for the day.
Here is the code I have done to get the interval per day between two dates:
foreach($period as $p => $v){
$day = $v->format('Y-m-d');
$interval = 0;
foreach($rotations as $rotation){
// Get the day of each dates
$date_start = explode(" ", $rotation['date_start'])[0];
$date_end = explode(" ", $rotation['date_end'])[0];
if($date_start == $date_end){
// += interval between the two dates
$interval += strtotime($rotation['date_end']) - strtotime($rotation['date_start']);
}else if($date_start == $day){
// += interval between the start date and midnight
$interval += strtotime($day." 23:59:59") - strtotime($rotation['date_end']);
}else if($date_end == $day){
// += interval between midnight and the end date
$interval += strtotime($rotation['date_end']) - strtotime($day." 00:00:00");
}
}
}
I hope it's clear for you
What I want now is to get 2 intervals instead of one :
1 interval for dates between 6 am and 9 pm as $interval_day
1 interval for dates between 9 pm and 6 am as $interval_night
For exemple:
rotation['date_start'] = 27/07/2018 21:00:00
rotation['date_end'] = 28/07/2018 02:00:00
then
27/07/2018 :
$interval_day = 00:00:00 and $interval_night = 03:00:00
28/07/2018 :
$interval_day = 00:00:00 and $interval_night = 02:00:00
For each day you have to compute 3 overlappings:
overlapping between the interval [date_start time_start,
date_end time_end] for the given day and the interval [date_start 06:00:00, date_end 21:00:00]
overlapping between the interval [date_start time_start, date_end time_end] for the given day and the interval [date_start 00:00:00, date_end 06:00:00]
overlapping between the interval [date_start time_start, date_end time_end) for the given day and the interval [date_start 21:00:00, date_end 23:59:59]
To do that, use the following formula:
overlap = MAX(0,end_1 - start_1 - MAX(0,end_1 - end_2) - MAX(0,start_2 - start_1))
The formula needs integers - i.e. UNIX timestamps.
Related
When the user submits a leave application, needs to select the start and end date. But before saving it needs to check is there any holiday or weekly holiday in between two dates. If a holiday or weekly holiday matches then the total number of holidays will be deducted from the total days.
Weekly Holiday:
id
day
working_status
1
Fri
1
Holiday Table: (Model Name: Holiday)
id
date
publication_status
1
2022-05-26
1
Leave Table:
id
start_date
end_date
total_days
1
2022-05-25
2022-05-28
2
Controller:
$leave = new User;
$leave->start_date = $request->start_date;
$leave->end_date = $request->end_date;
//get and convert day name for weekly holiday compare like Fri, Sat etc.
$start_day = date("D", strtotime($request->start_date));
$end_day = date("D", strtotime($request->end_date));
// get and convert date for monthly holiday compare
$start = strtotime($request->start_date);
$end = strtotime($request->end_date);
$diff = $end - $start;
$diff_in_days = floor($diff/(60*60*24)) + 1;
// Suppose Fri is holiday now we have to count how many Fri day in between start and end date.
here need help
$weekly_holidays = WorkingDay::where('working_status', 1)
->get(['day'])->count();
// we have to count how many Monthly holiday in between start and end date. here need help
$monthly_holidays= Holiday::where('publication_status', 1)->get(['date'])->count();
$total_days = $diff_in_days - ($weekly_holidays + $monthly_holidays);
if($request->halfday == 1){
$leave->total_days = 0.5;
}
else{
$leave->total_days = $total_days;
}
Example:
WorkingDay = day = Fri
Holiday = date = 2022-05-26
start_date = 2022-05-25
end_date = 2022-05-28
total_days = 2
// from 25 to 28, the total days are 4, but 26 is a holiday, and 27 is Friday. Holidays can be multiple dates. If there is multiple holidays between the start and end date, it will calculate according to this.
It's actually easier. You don't need to complicate it. Carbon comes to the rescue here.
$startDate = Carbon::parse('start date here');
$endDate = Carbon::parse('date string here');
$weekdays = $startDate->diffInWeekdays($endDate);
This will give you the day difference in weekdays excluding any weekends.
Now whichever database you use, you would have a function to get the day of the week in number where 0 stands for Sunday and 6 for Saturday.
For Postgres, I will give you an example
weekdays_holiday_count = select count(*) from holidays where date_part('dow', date) not in (0, 6) # 0 for Sunday and 6 for Saturday
This query is counting holidays which came on weekdays. I give you the raw query here. however, the point here is to under the magic of the function.
Now you can do the math easily
$weekdays - $weekdays_holiday_count
Make sure to import Carbon\Carbon at the top.
I am using below code for fetching next monday but i am unable to fetch next sunday on same week. like today is friday and if i search next week then i need to get next week monday to sunday.
SELECT now() + INTERVAL 7 - weekday(now()) DAY
This above give me next monday.
I need to add 7 more days and get sunday date in same format.
2018-07-30 14:45:43 Monday
2018-08-05 14:45:43 Sunday
The strtotime() function is great for vague relative queries like this:
$monday = date('Y-m-d', strtotime('next monday'));
$sunday = date('Y-m-d', strtotime('next monday + 6 days'));
Yields:
2018-07-30
2018-08-05
Add 6 days to get the sunday of the monday. Add 13 days to add the second sunday after the monday:
SELECT (now() + INTERVAL 7 - weekday(now()) DAY) + INTERVAL 6 DAY;
If I understand correctly, you have gotten "2018-07-30 14:45:43" and need to get Sunday. Sunday is six days after Monday, so just add 6 to 7 and get 13.
SELECT now() + INTERVAL 13 - weekday(now()) DAY
How about
select monday, monday + interval 6 day as sunday from
(select now() + INTERVAL 7 - weekday(now()) DAY as monday) s1
I am calculating weekly values comparing the last week and the same days in the year before. As we just have a leap year, my approach causes problems.
I am calculating the dates like this and perform a corresponding select:
$today_raw = date('Y-m-d');
$yearAgo = date('Y-m-d', strtotime('-1 year', strtotime($today_raw)));
$weekAgo = date('Y-m-d', strtotime('-6 day', strtotime($today_raw)));
$weekYearAgo = date('Y-m-d', strtotime('-1 year', strtotime($weekAgo)));
$stmt_currentWeek = $pdo->prepare("SELECT X FROM Y WHERE Z BETWEEN '$weekAgo' AND '$today'");
$stmt_weekLastYear = $pdo->prepare("SELECT X FROM Y WHERE Z BETWEEN '$weekYearAgo' AND '$yearAgo'");
It's obvious that the SELECT returns the wrong number of values as $weekYearAgo is simply wrong as it does not reflect the leap year differences.
What am I doing wrong?
Just use mysql DATE Functions:
$stmt_currentWeek = $pdo->prepare("SELECT X FROM Y WHERE Z >= DATE_SUB(NOW(), INTERVAL 1 WEEK)");
$stmt_weekLastYear = $pdo->prepare("SELECT X FROM Y WHERE Z BETWEEN DATE_SUB(DATE_SUB(NOW(), INTERVAL 1 YEAR), INTERVAL 1 WEEK) AND DATE_SUB(NOW(), INTERVAL 1 YEAR)");
1 Year And 1 Week AGO:
DATE_SUB(DATE_SUB(NOW(), INTERVAL 1 YEAR), INTERVAL 1 WEEK)
1 Year AGO:
DATE_SUB(NOW(), INTERVAL 1 YEAR)
1 Week AGO:
DATE_SUB(NOW(), INTERVAL 1 WEEK)
In the first SQL you dont need Between 1 WEEK AGO and NOW you can just rewrite it to >= 1 WEEK AGO
I am trying to get a query to pull records from last week from thursday morning at 12:00AM to Wednesday night at 12:00pm.
This needs to always run and be current. I have another query for the current week from thursday to wednesday and it actually works. I just need another query that shows results after the week has passed from last week.
I believe this query is for last week but not starting on Thursday and ending on Wednesday.
SELECT collector, SUM('amountcollected') as 'totalsum' FROM commissioninfo
WHERE thedate >= Curdate() - INTERVAL Dayofweek(Curdate())+6 day
AND thedate < Curdate() - INTERVAL Dayofweek(Curdate())-1 day
GROUP BY collector ORDER BY totalsum DESC
There might be a better way to do this using MySQL's own date functions, but I think I would probably just do it like this. I'm assuming that you meant Wednesday night at 11:59:59pm though, not noon:
$lastThursday = new DateTime("Thursday last week");
$wednesday = new DateTime("Wednesday");
$today = new DateTime("now");
$day = $today->format("l");
if ($day == "Sunday" || $day == "Monday" || $day == "Tuesday" || $day == "Wednesday") {
$lastThursday->modify("-1 week");
$wednesday->modify("-1 week");
}
$query = "SELECT collector, SUM('amountcollected') as 'totalsum' FROM commissioninfo WHERE thedate BETWEEN ".$lastThursday->format("Y-m-d")." AND ".$wednesday->format("Y-m-d ")." GROUP BY collector ORDER BY totalsum DESC";
$start = strtotime('this week');
$results =$wpdb->get_results("SELECT count( doctor_name ) AS totalleads FROM `wp-leads-count` WHERE doctor_name ='Sasanthi' and leads_date >='". $start."'");
this is my code to get last week leads count from table doctor name and where date with in this week (means today is thusday then start from previous week)
it not working??
and have do same for function like last month ??
in my db i use this leads_date field as timestamp
you can use the date_sub function from mysql
get all records from last week
SELECT count(doctor_name) AS totalleads FROM `wp-leads-count` WHERE doctor_name ='Sasanthi' and leads_date between date_sub(now(),INTERVAL 1 WEEK) and now()
get all records from last month
SELECT count(doctor_name) AS totalleads FROM `wp-leads-count` WHERE doctor_name ='Sasanthi' and leads_date between date_sub(now(),INTERVAL 1 MONTH) and now()
try
$daynumber = date('N', date('d'));// getting today day number
$prevweek = $daynumber+7; // starting from prev week
echo $prevdate = strtotime('-'.$prevweek.' days'); // prev week date
echo strtotime("-1 month"); // last month
For more :-
Getting last month's date in php
day of the week to day number (Monday = 1, Tuesday = 2)