i am in need of a search query based on 6 values from 3 columns day, month, year, right now i have got it some how working only for month and year but i can not get the day to perform correctly.
for example if some one wants to search from day, month year to day month year.
my current query
//From
list($fy,$fm,$fd) = explode ('-', 2013-2-20);
//to
list($ty,$tm,$td) = explode ('-', 2014-9-1);
$add = " AND
( month >= '".$fm."'
AND year >='".$fy."') AND (
month <= '".$tm."'
AND year <= '".$ty."'
) ";
as you can see the day is not included, your time is much appreciated.
Going on with what you have. You would just add day in the same way you added month and year:
...
$add = " AND
( month >= '".$fm."'
AND year >='".$fy."'
AND day >='".$fd."') AND (
month <= '".$tm."'
AND year <= '".$ty."'
AND day <= '".$td."'
) ";
...
Since all the items are independent of each other, this works of the literal values are higher/lower in each item. Which is probably not what you want. You will need to convert the strings '2013-2-20' into DATE and then use those. This can be done with str_to_date(). So for example str_to_date('2013-2-20','%Y-%m-%d').
Notice: I'm aware that you cannot change the database but for future references it's a good idea to have a single DATE datatype for your database. It's not good design to separate them into separates things such as day, month, and year. As with using the DATE datatype it can easily find lower and higher dates by simply comparing the dates (along with date functions using dates can be used):
dateObj1 >= dateObj2 // dateObj1 is at a later date than dateObj2
Related
The goal is exclusively to get a range of days, in other words
, start date and end date, as if it were a "calendar matrix", containing the 42 days, being the days of the current month, with the days of the previous month and next month. No need to present (render) a calendar, only get dates.
For example, follow image below.
I need to enter a certain month of a given year, and would need to get this range of days, as picture.
Using PHP Carbon, I easily get the days of the current month, using startOfMonth(), endOfMonth() , subMonth(), addMonth().
Doing this, I get every day of these 3 months, but the goal is to be able to "filter" these days to present only the interval equal to a calendar, but obviously something dynamic, ie, if I use Carbon, would simply inform the desired date , and get "filtered" range, respecting the position of each "cell".
$prev_start = Carbon::now()->subMonth()->startOfMonth();
$prev_end = Carbon::now()->subMonth()->endOfMonth();
$start = Carbon::now()->startOfMonth();
$end = Carbon::now()->endOfMonth();
$next_start = Carbon::now()->addMonth()->startOfMonth();
$next_end = Carbon::now()->addMonth()->endOfMonth();
So here's what you can do:
$monthStart = Carbon::now()->startOfMonth();
$monthEnd = Carbon::now()->endOfMonth();
$calendarStart = $monthStart->startOfWeek(Carbon::SUNDAY);
$calendarEnd = $monthEnd->endOfWeek(Carbon::SATURDAY);
$calendarStart and $calendarEnd should now contain the first and last day that will be displayed in a single screen. This assumes that the calendar will expand the first and last week displayed.
If you are using a calendar that always shows 42 days regardless you can just do:
$monthStart = Carbon::now()->startOfMonth();
$calendarStart = $monthStart->startOfWeek(Carbon::SUNDAY);
$calendarEnd = $calendarStart->addDay(42);
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;
}
I'm trying to get an average of a value for the past 2 months, but not based on CURDATE()/NOW(). It would be dependent on what month the user was looking at in the application:
Ex:
If I'm looking at May, I would want the average of April and March.
If I'm looking at February, I would want the average of January and December (of the previous year).
I have a function that accepts the month and year of the page the user is on (it also accepts the emp_id, but that is irrelevant for this question).
public function getProtectedAmt($month,$year,$id){
$query = "SELECT avg(total_payout) as avg_payout FROM saved_plan_data WHERE emp_id = '$id' AND //this is where i dont know what to query for";
$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_assoc($result);
return $row['avg_payout'];
}
In the table saved_plan_data, there are fields plan_month and plan_year that store INT values of what month/year the employee's total_payout is saved for.
How do I write my WHERE clause to get the AVG for the previous 2 months, depending on what the values of $month and $year are?
I think the easier and more readable solution is this one:
SELECT ...
FROM ...
WHERE
(plan_year, plan_month) IN ((2012, 12), (2013, 1))
You just need to compute the appropriate values.
This is also quite readable:
WHERE CONCAT_WS('-', plan_year, plan_month) IN ('2012-12', '2013-01')
In the function, create two variables $q_month & $q_year.
Set these as comma separated past two months. E.g. if currently the date is May 22, 2013, set the values to $q_month = 4,3 and $q_year = 2013
Use these variables in your query as WHERE Month in ($q_month) and Year in ($q_year)
Edit: Mis-read the question. This would get you the average for the last two months combined.
You could either be very verbose saying where (month and year) or (month and year)
SELECT avg(total_payout) as avg_payout
FROM saved_plan_data
WHERE emp_id=$id
AND (
(plan_month = $month1 AND plan_year = $year1)
OR (plan_month = $month2 AND plan_year = $year2)
)
Or you can cast the plan_month and plan_year as a date and check if the value is between two dates:
SELECT avg(total_payout) as avg_payout
FROM saved_plan_data
WHERE emp_id=$id
AND STR_TO_DATE(CONCAT_WS('-',plan_year,plan_month,'1'),'%Y-%m-%d')
BETWEEN '$year1-$month1-1' AND '$year2-$month2-1'
Also, you really should just store the month and year together. Here is a SO question with good answers about it: mysql datatype to store month and year only
I think the easiest way is to think of the year/month combinations as a number of months since year/month 0. That is, convert to number of months by multiplying the year times 12 and adding the months.
Then the previous two months is easy, and you don't have to worry about year boundaries:
SELECT avg(total_payout) as avg_payout
FROM saved_plan_data
WHERE emp_id = '$id' AND
plan_year*12 + plan_month in ($year*12+month - 1, $year*12+month - 2)
I have a function that is accepting the date and time, and number of occurrences of an episode. I'm using a while loop to try and insert and episode every week on the same day and time. For example if the episode is monday at 7PM, i want to insert in for every monday at 7PM for the number of occurrences given.
Here's my code and while loop:
$sEpsAirDate = strtotime($aVars['air_date'].' '.$aVars['air_time'].$aVars['air_ampm']);
$i = 1;
while ($i <= $aVars['repeat_count']) {
$sEpsAirDate = // How can I alter this variable to change the date to every week?
db_res(
"INSERT INTO `hm_episodes_main` SET
`show_id` = '{$aVars['show_id']}',
`title` = '{$sEpsTitle}.{$i}',
`season` = '{$aVars['eps_season']}',
`uri` = '{$sUri}.{$i}',
`desc` = '{$sEpsDesc}',
`air_date` = '{$sEpsAirDate}'
");
$i++
}
How would I alter the $sEpsAirDate variable to be entered accurately on every day of the week on the given time?
Use mktime():
$next_ep_timestamp = mktime ($hour,$min,$sec, $first_ep_month, $first_ep_day + 7 * $weekcount, $first_ep_year);
"Init" this by setting the respective variables for the date, month and year of the first episode, then you can create new dates for following weeks by adding increments of 7 to the day-parameter in mktime (like shown above).
Then format for output to SQL like this:
$datetime_str = date("Y-m-d H:i:s", $next_ep_timestamp);
//gives a date-str like '2011-10-16 12:59:01'
The first idea that comes to my mind is just adding the seconds in a week to the sEpsAirDate with every iteration in the loop:
$sEpsAirDate += 604800;
If you needed to preserve the first air date you could copy it out into a separate variable and then do something like this (change the LCV $i to start at 0):
$sEpsAirDate = $sEpsFirstAirDate+(604800*$i);
But this method has the potential to create problems with Daylight Savings Time... so it might be safer to break the date into year, month and day variables and then recreate the $sEpsAirDate with every loop iteration by adding ($i*7) to day. ... So something like (again change the LCV $i to start at 0):
$sEpsAirDate = mktime($sEpsAirDateHour, $sEpsAirDateMinute, 0, $sEpsAirDateMonth, $sEpsAirDateDay+($i*7), $sEpsAirDateYear);
Please help a newbee. I have a table named event_calendar with fields named ec_start_date, ec_end_date and ec_event_name. The first two fields are date fields. It is a small table, with less than 100 entries. I want to list events with a start or end date in the current month, then I want to follow with a list of events with a start or end date in the next month. The two list will be headed by the month name. I would like the dates displayed in the list to be in the format dd/mm.
This is the code I've found to identify the months for the list headers.
$thismonth = mktime(0,0,0,date("n"));
$nextmonth = mktime(0,0,0,date("n")+1);
echo "<h2 class='caps'>";
echo date("n", $thismonth);
echo "</h2>";
echo "<h2 class='caps'>";
echo date("m", $nextmonth);
echo "</h2>";
This is the code I use to pull the entries for this month's (August) activities
$query = "SELECT ec_display,ec_event_name,ec_start_date,ec_end_date FROM event_calendar WHERE month(ec_start_date) = 8 OR month(ec_end_date) = 8 ORDER BY ec_start_date";
The problem is, if I replace the number 8 with the variable $thismonth, it fails.
Finally, how can I display only the dd/mm from ec_start_date and ec_end_date?
I greatly appreciate any guidance, but please be specific as I am very new to this! Thank you!
$thismonth contains a UNIX timestamp returned by mktime. The timestamp for hour 0, minute 0, second 0 of month 8 of this year is 1312862400. That's not 8.
Don't put that in your query, put date('n') (8) in it... or just let MySQL do it
$query = "SELECT ec_display,ec_event_name,ec_start_date,ec_end_date FROM event_calendar WHERE month(ec_start_date) = MONTH(CURRENT_DATE) OR month(ec_end_date) = MONTH(CURRENT_DATE) ORDER BY ec_start_date";