I posted a question some time ago on representing data per date horizontally on a datatable.
See here: datatables dates at the top and data cells going from left to right
With the help of that thread I was able to get the data to display how I wanted it. With the dates showing at the top, the service provided on the left and all data associated with any date between the 2 date paramters inside the main body. (If there is no data in a particular date then the < td > will display 0. See here:
http://www.phpwin.org/s/ewbAS6
After manipulating this code further I made the dates of the search dynamic by proving a form with a start date and an end date, and a dropdown with the options of:
Daily
Weekly
Monthly
Quaterly
Yearly
this allows the interval of dates at the top to become dynamic. Of course all this is doing is changing the value of the 2nd parameter inside the date while loop.
WHILE (strtotime($date) <= strtotime($end_date)) {
echo '<th>' . $date . '</th>';
$date = date('Y-m-d', strtotime($date . ' +1day'));
}
with the parameter set at Weekly, the value of +1day becomes +1week, at Monthly; the value becomes +1month and so on.
MY ISSUE:
When the interval is set to daily, the dates with their corresponding attendance counts are displayed correctly but once you try to increase the interval to +1week and above the data does not round up to the week shown. Check this:
[LINK1]Per day: http://www.phpwin.org/s/ewbAS6
[LINK2]Per month: http://www.phpwin.org/s/xRo3I6
Looking at the array (modified on the LINK2)
$result[] = array('Service Name' => 'Health', 'date' => '2017-04-04', 'Attendance' => 5);
$result[] = array('Service Name' => 'Payroll', 'date' => '2017-04-16', 'Attendance' => 5);
$result[] = array('Service Name' => 'Saturday Youth Meeting', 'date' => '2017-04-03', 'Attendance' => 1);
$result[] = array('Service Name' => 'Saturday Youth Meeting', 'date' => '2017-05-03', 'Attendance' => 3);
$result[] = array('Service Name' => 'Payroll', 'date' => '2017-05-03', 'Attendance' => 2);
$result[] = array('Service Name' => 'Payroll', 'date' => '2017-04-11', 'Attendance' => 3);
$result[] = array('Service Name' => 'Payroll', 'date' => '2018-04-03', 'Attendance' => 10);
You can see in the array that there are multiple attendance entries in April, totaling 14 Attendances in that month however during LINK2 where the interval is increased to a month instead of showing 14 for April (which would be the sum of all the dates in that particular month) it shows the value 1.
My live version takes the array from a database so I used the YEAR(), MONTH(), WEEK() and DAY() function on the date and used group by. The query executes how I want it but having issues working on the PHP end.
Related
I'm trying to make an calendar scheduler for student teacher for their future lessons together.
I'm trying to add day, time and DATE(most important). Right now I added day and time in each of their following meetings. For ex. every Monday at 08:00 and every Wednesday at 10:00. But what I cannot add is Date . Here is some of my coding.
$student = Auth::user()->student;
$teacher = Teacher::where('id',$id)->first();
$lessons = $request->lessons_booked;
$times = $request->times;
$timesArrLength = count($times);
$stuTeachArr = array();
for($i = 1;$i<= $lessons;$i++){
$studentTeacher = StudentTeacher::create([
'student_id' => $student->id,
'teacher_id' => $teacher->id,
'subject_id' => $request->subject_id,
'place_of_tutoring_id' => $request->place_of_tutoring_id,
'lessons_booked' => $lessons,
'lesson_nr' => $i,
'time_id' => $times[($i-1) % $timesArrLength]['id'],
'day' => $times[($i-1) % $timesArrLength]['day'],
'date' => '2021-01-01', // add date here
'lessons_left' => $request->lessons_booked - $i,
'status' => 'active'
]);
array_push($stuTeachArr,$studentTeacher);
}
// $stuTeachArr['booked_teacher'] = $studentTeacher;
return $stuTeachArr;
What I want is to add DATE for every lesson that will happen from now until they finish with their lessons(For ex. every Monday and every Wednesday as mentioned before).
Any suggestion to change the way I'm doing would be welcomed.
I'm Using PHP RRule for Recurrence in my Project.
Here Daily and Weekly Recurrence are working fine.
I don't know how to use monthly Recurrence in my scenario.
Monthly scenario:
First Sunday of every 2 Months
Code:
$dow=array("SU");
$rrule = new RRule([
'FREQ' => 'MONTHLY',
'BYMONTHDAY' => 2,
'INTERVAL' => 2,
'BYDAY' => $dow,
'DTSTART' => '2016-12-01',
'UNTIL' => '2017-12-31'
]);
foreach ( $rrule as $occurrence ) {
echo "</br>";
echo $occurrence->format('D Y-m-d');
}
echo $rrule->humanReadable(),"\n";
//OUTPUT
Sun 2017-04-02
every 2 months on Sunday on the 2nd of the month, starting from 12/1/16, until 12/31/17
You don't need BYMONTHDAY, you need BYDAY with a number prefix.
In your situation: 'BYDAY' => '1SU' means "the first Sunday". 2SU the second Sunday, -1SU the last Sunday etc.
More information:
https://github.com/rlanvin/php-rrule/issues/19
https://www.rfc-editor.org/rfc/rfc5545#section-3.3.10
What would be the best way to find the difference in the two dates start_date and account_add_date then insert into a column called account_age?
What I need is for a user to select a start_date say its January.
Then the date when they added account_add_date say March.
The difference is 2 months so in account_age would be 2,
then in April that 2 would be a 3. May 4, June 5 and so on
Dose anyone know how to do this ?
My current insert query MODEL
function create_bank()
{
$this->load->helper('date');
$new_bank_acc_insert_data = array(
'bank_name' => $this->input->post('bank_name'),
'interest' => ($this->input->post('interest') / 100),
'start_amount' => $this->input->post('start_amount'),
'length' => $this->input->post('length'),
'start_date' => date('Y-m-d',strtotime($this->input->post('start_date'))),
'mem_id' => $this->session->userdata('id'),
'account_add_date' => $this->current_date()
);
$insert = $this->db->insert('bank', $new_bank_acc_insert_data);
return $insert;
}
Idea on finding account age
SELECT DATEDIFF('start_date','account_add_date')
SELECT
(
12* (YEAR(account_add_date) - YEAR(start_date)) +
(MONTH(account_add_date) - MONTH(start_date))
) AS differenceInMonth
FROM
YOUR_TABLE
Although DATEDIFF function returns the difference in two dates in days which is more accurate comparing to the difference in month
Explanation:
Example:
start_date = 2014 March
account_add_date = 2015 January
YEAR(account_add_date) = 2015
YEAR(start_date) = 2014
MONTH(account_add_date) = 1
MONTH(start_date) = 3
So according to the query:
12 * (2015-2014) + (1-3) = 12 * 1 - 2 = 10 (Months)
I have to display date alone in sfWidgetFormDate but I want date and month to be passed in hidden.
I have given as:
$this->widgetSchema['fellowship_admission_date'] = new sfWidgetFormFilterDate(array(
'from_date' => new sfWidgetFormDate(array('format' => '%year%')),
'to_date' => new sfWidgetFormDate(array('format' => '%year%')),
'with_empty' => false
))
It displaying only year but I want to pass month and day in 'from_date' and 'to_date' default as '1' as hidden.
Why don't you display the entire date, and hide day and month with jQuery?!
It could be a good and fast solutions...
I am building a small class combination to calculate the precise date of the beginning of a semester. The rules for determining the beginning of the semester goes as follow :
The monday of week number ## and after dd-mm-yyyy date
ie: for winter its week number 2 and it must be after the january 8th of that year
I am building a resource class that contain these data for all the semesters (4 in total). But now I am facing an issue based on the public holidays. Since some of those might be on a Monday, in those cases I need to get the date of the Tuesday.
The issue I am currently working on is the following :
The target semester begins on or after august 30 and must be on week 35.
I also have to take account of a public holiday which happen on the first monday of september.
The condition in PHP terms is the following
if (date('m', myDate) == 9 // if the month is september
&& date('w', myDate) == 1 // if the day of the week is monday
&& date('d', myDate) < 7 // if we are in the first 7 days of september
)
What would be the best way to "word" this as a condition and store it in an array?
EDIT
I might not have been clear enough, finding the date is not the problem here. The actual problem is storing a condition in a configuration array that looks like the following :
$_ressources = array(
1 => array(
'dateMin' => '08-01-%',
'weekNumber' => 2,
'name' => 'Winter',
'conditions' => array()
),
2 => array(
'dateMin' => '30-04-%',
'weekNumber' => 18,
'name' => 'Spring',
'conditions' => array()
),
3 => array(
'dateMin' => '02-07-%',
'weekNumber' => 27,
'name' => 'Summer',
'conditions' => array()
),
4 => array(
'dateMin' => '30-08-%',
'weekNumber' => 35,
'name' => 'Autumn',
'conditions' => array("date('m', %date%) == 9 && date('w', %date%) == 1 && date('d', %date%) < 7")
)
);
The issue I have with the way it's presented now, is that I will have to use the eval() function, which I would rather not to.
You said:
The target semester begins on or after august 30 and must be on week 35.
If that's the case you can simple check for week number.
if(date('W', myDate) == 35)
Or if your testing condition is correct then you should compare day number till 7 as it starts from 1.
if((date('m', myDate) == 9 // september
&& date('w', myDate) == 1 // monday
&& date('d', myDate) <= 7 // first 7 days of september
)
And then in the if statement, once you have found the monday which would be OK IF its not a public holiday, do this
if(...){
while(!array_search (myDate, aray_of_public_holidays))
date_add($myDate, date_interval_create_from_date_string('1 days'));
}
Here the array_of_public_holidays contains the list of public holidays.
Update with Code
Following code should work for your purposes
<?php
// array with public holidays
$public_holidays = array(/* public holidays */);
// start on 30th august
$myDate = new DateTime('August 30');
// loop till week number does not cross 35
while($myDate->format('W') <= 35){
// if its a monday
if($myDate->format('w') == 1){
// find the next date not a public holiday
while(array_search($myDate, $public_holidays))
$myDate->add(date_interval_create_from_date_string('1 days'));
// now myDate stores the valid semester start date so exit loop
break;
}
// next date
$myDate->add(date_interval_create_from_date_string('1 days'));
}
// now myDate is the semester start date
?>
Update according to updated question
Following code should work for your needs. You do not need to store the condition in your array as PHP code. The following code shows how it can be done
// semester conditions
$sem_conditions = array(
1 => array(
'dateMin' => '08-01-%',
'weekNumber' => 2,
'name' => 'Winter'
),
2 => array(
'dateMin' => '30-04-%',
'weekNumber' => 18,
'name' => 'Spring'
),
3 => array(
'dateMin' => '02-07-%',
'weekNumber' => 27,
'name' => 'Summer'
),
4 => array(
'dateMin' => '30-08-%',
'weekNumber' => 35,
'name' => 'Autumn'
)
);
// array with public holidays format (d-M)
$public_holidays = array('05-09', '10-01');
// store sem starts
$sem_starts = array();
// for each semester
foreach($sem_conditions as $sem){
// start date
$myDate = date_create_from_format('d-m', substr($sem['dateMin'], 0, -2));
// loop till week number does not cross $sem['weekNumber']
while($myDate->format('W') <= $sem['weekNumber']){
// if its a monday
if($myDate->format('w') == 1){
// find the next date not a public holiday
while(array_search($myDate->format('d-m'), $public_holidays) !== false)
$myDate->add(date_interval_create_from_date_string('1 days'));
// now myDate stores the valid semester start date so exit loop
break;
}
// next date
$myDate->add(date_interval_create_from_date_string('1 days'));
}
// add to sem starts
$sem_start[$sem['name']] = $myDate->format('d-m-Y');
}
var_dump($sem_start);
The target semester begins on or after august 30 and must be on week 35
The start of the semester is the minimal date between week 35 and August 30:
$week35 = new DateTime("January 1 + 35 weeks");
$august30 = new DateTime("August 30");
$start = min($week35, $august30);
Alternatively:
$start = min(date_create("January 1 + 52 weeks"), date_create("August 30"));