I have a query, A user fill records of every day for each month and I want, the user can edit/delete his data till 7th of next month.
I got the diff between dates using date() function, but can't understand how to compare that record fill date is less than 7th of next month.
//$fill_date; get data filled date from database
$filled_date = date("Y-m-d", strtotime($fill_date));
$datestring = $filled_date.' first day of next month';
$dt=date_create($datestring);
$d_mont = $dt->format('Y-m-07'); // give 7th of next month from data insert date
//get next month from fill date
$f_date = date('Y-m-d' , strtotime($fill_date));
if(strtotime($f_date) <= strtotime($d_mont)) {
echo strtotime($f_date)." <= ".strtotime($d_mont);
echo "you can edit";
}
There I share a query which can fetch the data till 7th.May this query help you if found any issue then comment.
this table contains last data till 7th of every month otherwise
no data.
SELECT * from datatable where day(curdate()) <= 7 and cast(datefield as date) >= (curdate() + interval -1 month);
Here is an example code
$curdate = date('Y-m-d', strtotime($fill_date)); // or time() for current date
$month = date('m', strtotime($curdate));
$year = date('Y', strtotime($curdate));
$nextmonth = ($month == 12)? 1: $month+1;
$date2 = date("Y-m-d", mktime(0, 0, 0, $nextmonth, 7, $year));
You can compare the dates with strtotime as you already do
What your asking to do is very confusing, but I understand, because I am cool like that.
The best way to do this to set a flag in the data, have a field in the database that is called locked or such that is a simple boolen value 1=true, 0=false
Then on the 7th of the month at midnight run a cron job that updates all the records before the current month with a 0 and set them to a 1.
It would be pretty trivial to write a cron job to do that maybe 20 lines of code tops.
Brief example (psudo code)
$date = (new DateTime())->modify('first day of this month')->format('Y-m-d');
$Sql = "UPDATE tbl SET locked = 1 WHERE DATE(date_field) < '{$date}' AND locked=0";
$DB->query($Sql);
Cron: if you don't know what it is
https://en.wikipedia.org/wiki/Cron
Use cron to schedule jobs (commands or shell scripts, including PHP )
to run periodically at fixed times, dates, or intervals.
If they can only edit tell the 7th of the next month, then on the 7th of each month all the data from last month is no longer editable.
Then when you pull them to edit, you just do
SELECT * FROM table WHERE locked = 0
That is if you truly what it to stop on the 7th and not a month. AS I said in the comments if I put a record on the 1st that gives me that whole month + 7 days, if I did it on the last day, I would have only 7 days to edit the record.
It's not as trivial to write a date range query for this as it first seems. Because if it's before the 7th, you have to select everything from last month and everything from this month ( tell the current date ). But if it's the 8th, you have to select everything from the beginning of the month tell the current data ( omitting last month ). So the query would change depending on the day it currently is.
To try to filter the data after pulling it out seems like a waste, because you will always pull more records then the user can edit, and then you have to work out the date switch anyway.
An advantage of having a locked field also, it that you can selectively unlock a record for a user so they could edit it again, just by fliping the 1 back to a 0. ( -note- the cron job I outlined above would re-lock it ) The point is it would be possible to allow them to edit specific records without code changes.
IMO, it's the best way to do it.
Related
This is a little complicated to explain, especially in the title - so here it is:
I'm making a PHP Array with 12 indexes, one for every month - each month will show the number of page views that were recorded in the month, to get the month, I'm using the current UNIX time and taking away 2629743 seconds (a month), each time the loop goes around, 2629743 more seconds are added - this should then generate the array such as (1, 4, 5, 9) 1 view in Jan, 4 views in Feb, etc.
If there are no views, I need it to be like (null, null, 9) so no views in Jan, none in Feb, 9 in March - but the indexes completely mess up and the views go in the wrong order.
The code for the loop:
$Month = 1; // Start with January
$MonthTimestamp = 2629743; // Start with the time of ONE month from current time
$ArrayTimeStamp = array();
while ($Month <= 12): // Go from January to February
$Value1 = $now - $MonthTimestamp;
$ViewsThisMonth = mysqli_fetch_object(mysqli_query($db, "SELECT SUM(Views) AS NumberFinalViews FROM BlogViews WHERE TimeRecord >= '$Value1' AND TimeRecord < '$now'"));
$ArrayTimeStamp[] = $ViewsThisMonth->NumberFinalViews;
$MonthTimestamp = $MonthTimestamp + 2629743;
$Month++;
endwhile;
To reiterate, the array needs to store each month of page views that are stored in a database, all page views are stored with a time stamp, these time stamps need to be seperated into the 12 months and then be put into the array.
4 views in Feb need to be in the second index, and the timestamp would be larger than January's timestamp but smaller than March.
All help appreciated!!
Edit: $now is the current UNIX time in seconds.
You should ensure your columns containing time-related data are DATETIME or TIMESTAMP columns. That will make time-based queries easier.
You can move the logic you're implementing in PHP into the query itself:
SELECT SUM(Views) AS NumberFinalViews,
EXTRACT(YEAR_MONTH FROM TimeRecord) AS YearMonth
FROM BlogViews
WHERE TimeRecord BETWEEN '$startMonth' AND '$endMonth'
GROUP BY YearMonth
If TimeRecord is just an integer representing a UNIX timestamp, you need to convert it:
...
EXTRACT(YEAR_MONTH FROM FROM_UNIXTIME(TimeRecord)) AS YearMonth
This returns you a result with the field YearMonth which has values like 201609 (September 2016), and the number of Views in that period, already pre-grouped. You just need to set the $startMonth and $endMonth as the absolute delimiters for the whole period you're querying, no need to do it for each month individually.
Im currently programming a calendar with php and mysql and im stuck with some functionality while selecting all events i want to display. I implemented the possibilty to repeat an event. Therefore i set a timestamp from which the event starts and a timestamp to determine when the event ends. Furthermore i got some integer values which represent the rythm in which the event is repeated.
Then i fetch the events based on a timestamp which is send with a request.
I now want to enable the user to shift events from the weekend to the Friday before the weekend or the monday after the weekend. For example:
From: 1450306800 (today)
until: 0 (infinite)
rythm : 1 (-> every month)
jump:2 (-> on every 2nd day / month)
weekends : 3 (-> shift to next monday)
-> January 2nd 2016 is a saturday and i want to display that event on the next monday.
currently my select looks something like this: (:day -> timestamp from request, :d -> day of month from :day, :weekday -> day of the week from :day)
SELECT * FROM events
WHERE repeat_from <= :day
AND ((repeat_until >= :day) OR (repeat_until = 0))
AND CASE weekends
WHEN 0 THEN (:weekday BETWEEN 1 AND 7)
WHEN 1 THEN (:weekday < 6)
WHEN 2 THEN ??
WHEN 3 THEN ??
AND CASE rythm
WHEN 1 THEN (:d - DAY(FROM_UNIXTIME(repeat_from))) / (jump + 1) = CEIL ((:d - DAY(FROM_UNIXTIME(repeat_from))) / (jump + 1)) ... [all the other cases]
How do i check if the event would have been displayed on saturday or sunday before/after within the select? The only way i can think of is to more or less repeat the whole select from the "...AND CASE rythm..." part which is quite alot.
Or would the best way be, to fetch the event on every monday/friday anyway if it shifts and then check with a php function if the event would have been displayed on saturday or sunday ?
Why don't you do all the calculations and matching on the PHP back-end? With that much cases and clauses in your MySQL query you'll probably get yourself a really slow execution.
Select all Events by your major criteria. In your case that would probably be:
SELECT * FROM
events
WHERE
repeat_from <= :day AND
(
(repeat_until >= :day) OR
(repeat_until = 0)
)
Then just loop through all fetched rows and apply the built-in date() method - much faster and flexible:
# you can match the week number of different dates
$currentWeekNumber = date('W');
$specificDayWeekNumber = date('W', strtotime($specificDate));
# or match the day number
$currentDayNumber = date('N');
$specificDayNumber = date('N', strtotime($specificDate));
The date() method is super flexible and will allow you to check if certain Event date is within the weekend or not, so you can manipulate it further.
If you provide some further explanations and/or examples, I'll try to be more specific with the solution. Cheers.
We have a database of films, and need to select the film with a start and end date within the current week. We have two columns in the SQL table, both of type "date", and are written in the format 2015-01-25 (ISO)(YYYY-MM-DD). We need to select the entry that occurs within the current week. The start date for the film is usually the Friday of the week, and the end date is usually the Sunday of the week. I want to be able to show what the upcoming film for the upcoming weekend will be, no matter what day of the week they check. I have written the following PHP and SQL query, but I'm not getting any data back when I echo the $result.
$date = strtotime("now");
$last = strtotime('next Sunday');
$date = date('Y-m-d',$date);
$last = date('Y-m-d',$last);
$result = mysql_fetch_array(mysql_query("SELECT * FROM campusFilms WHERE startDate BETWEEN $date AND $last"));
Any assistance would be greatly appreciated, and I am happy to elaborate on anything needed. I have searched other StackOverflow questions but none of them quite answered this specific case.
SELECT *
FROM campusFilms
WHERE WEEK('2015-02-05') BETWEEN WEEK(startDate) AND WEEK(endDate);
http://sqlfiddle.com/#!2/476d3/3
This solution cannot use an index so, if performance is an issue, we can look at alternative solutions.
Why not just use YEARWEEK() ?
SELECT whatever_you_need
FROM campusFilms
WHERE YEARWEEK(CURDATE()) BETWEEN YEARWEEK(startDate) AND YEARWEEK(endDate);
yearweek returns the year and week of any given date which will handle multiple years.
If all you care is to find records where startdate is between the Friday and Sunday of the current week, then you don't even need to use PHP to compute dates, you can get mysql to do all the work for you:
SELECT *
FROM campusFilms
WHERE startDate BETWEEN
DATE_ADD(CURDATE(), INTERVAL(-2 + MOD(8-DAYOFWEEK(CURDATE()),7)) DAY)
AND
DATE_ADD(CURDATE(), INTERVAL(MOD(8-DAYOFWEEK(CURDATE()),7)) DAY)
This works regardless of what day of the week it is today. If it's Friday, it'll give you films between today and the day after tomorrow. For Saturdays, it'll give you films between yesterday and tomorrow and for Sundays, it'll give you films between two days ago and today.
I am currently trying to write a little program to track time-off requests for employees. I'm fairly new to MYSQL and PHP, so it's a learning project for me as well. I've run into this problem which I do not seem to be able to figure out.
I want to display time off requests for a given week (Mon-Fri). I've got the requests in a table 'requests', with a 'Starttime' and 'Endtime' in separate fields, both Date/Time.
I can currently easily search and retrieve requests that have either (or both) Starttime or Endtime values that fall within the given ISO week I am looking at (WEEKOFYEAR() ).
What I need to be able to do is search for requests that may include days in the ISO week I am displaying, but not have a Starttime or Endtime during that week.
Example:
Employee takes off Tuesday of Week 24 through Friday of Week 24.
Currently, I would correctly display that the employee was off starting Tuesday and show a return on that Friday, but on Wed and Thursday nothing would be entered.
Employee takes off Friday of Week 30 through Monday of Week 32.
Currently, I would show that employee as not being 'off' during Week 31 because the search would not show a Starttime or Endtime during that week even though they are actually off the entire week. Though the Starttime and Endtime would be noted on the correct days.
Right now, what I do to work around this is run 5 additional queries to check if the date for each day Mon-Fri during Week 31 is contained BETWEEN the Starttime and Endtime of each request in the db.
I hate to run a total of 6 queries to get this information. Is there an easier way to get that information?
I just wrote a calendar app for events and ran into this- how bout something like this:
SELECT * FROM Requests WHERE
Start_Date BETWEEN <first_day_of_week> AND <last_day_of_week>
OR
End_Date BETWEEN <first_day_of_week> AND <last_day_of_week>
OR
<day_of_week_monday> BETWEEN Start_Date AND End_Date
OR
<day_of_week_tuesday> BETWEEN Start_Date AND End_Date
OR
<day_of_week_wedenesday> BETWEEN Start_Date AND End_Date
OR
<day_of_week_thursday> BETWEEN Start_Date AND End_Date
OR
<day_of_week_friday> BETWEEN Start_Date AND End_Date
GROUP BY ID ORDER BY Start_Date ASC, Date ASC
While < value_names > are generated with php via the currently viewed week requested. Should cover your bases.
What format are these dates stored in the DB? Assuming they are using MySQL's DATE format, its pretty easy to do. You can just use comparison operators on the fields and MySQL will do the work for you in one query.
$sql = "SELECT * FROM table WHERE startdate <= $someday AND $someday <= enddate";
Sticking to your week of year way of doing it, you can run a check to see if the current week falls within the range of the starting week off and the ending week off.
SELECT * FROM table WHERE WEEKOFYEAR(Starttime) <= N AND WEEKOFYEAR(Endtime) >= N;
(where N is the week you're displaying)
What you'd want to do, once you get the rows, is parse each day in PHP to see if that day falls between the starttime and endtime.
A good method for that is using:
$start_timestamp = strtotime($row['Starttime']);
$end_timestamp = strtotime($row['Endtime']);
You can use a similar method to get a timestamp of the day you are displaying, and see if it falls between $start_timestamp and $end_timestamp to determine if that day is off.
since you mentioned PHP as the display:
$start=30; //Friday of Week 30
$end=32; //Monday of Week 32
foreach (range($start, $end) as $number) {
echo $number;
}
You would expect to get 30,31,32.
You will have to verify that $start is < $end though as well for December to January weeks.
The range for WEEKOFYEAR() is 1-53. In this case, add 53 to the $end and display mod of $end if greater than 53:
$start=52; //Friday of Week 52, 2009
$end=2; //Monday of Week 2, 2010
If($start>$end) $end+=53;
foreach (range($start, $end) as $number) {
if($number>53){
echo $number%53;}
else{
echo $number;
}
}
You would expect to get 52,53,1,2
Probably need the query to read either like the big one with all the ORs or something like this
WHERE
Starttime <= <value for last day/time of the week>
AND
Endtime >= <value for the first day/time of the week>
That should get all the dates you need that could fall in that week, then you parse the records you get with PHP to find the ones for that actual week... though there may be an easier way to do that.
I need to calculate a difference between a starting date/time and an ending date/time. But, I only want to do this for the 5-day work week (exclude Sat/Sun as days). What is the best way to do this? My thought is that from the date, I'll have to get the day of the week and if it is a weekday, then I add to the accumulator. If it's not, then I don't add anything.
I'm sure someone has done this before, but I couldn't seem to find anything searching. Any links or other help would be very useful.
Many thanks,
Bruce
DAYOFWEEK returns 1 for Sunday and 7 for Saturday. I'm not sure how your schema is set up, but this will perform a TIMEDIFF of two dates that are on a Monday - Friday work week.
select TIMEDIFF(date1,date2) from table
where DAYOFWEEK(date1) not in (1,7) and DAYOFWEEK(date2) not in (1,7)
MySQL DATE/TIME functions
EDIT: From Bruce's comment about holidays. If you have a table full of holiday dates, something like this would work to exclude processing those days:
select TIMEDIFF(date1,date2) from table
where date1 not in (select holiday from holiday_table) and
date2 not in (select holiday from holiday_table) and
DAYOFWEEK(date1) not in (1,7) and DAYOFWEEK(date2) not in (1,7)
NETWORKDAYS() "Returns the number of whole working days between start_date and end_date. Working days exclude weekends and any dates identified in holidays. Use NETWORKDAYS to calculate employee benefits that accrue based on the number of days worked during a specific term." according to the Excel 2007 help file.
The "between" description is a bit inaccurate because it includes the start and end dates, i.e. networkdays(21-01-2010. 22-01-2010) = 2. It also takes no account of times.
Here's a function in PHP that will give the same results. It doesn't work properly if the end date is less than the start date, nor does do anything about holidays (see below the function).
function networkdays($startdate, $enddate)
{
$start_array = getdate(strtotime($startdate));
$end_array = getdate(strtotime($enddate));
// Make appropriate Sundays
$start_sunday = mktime(0, 0, 0, $start_array[mon], $start_array[mday]+(7-$start_array[wday]),$start_array[year]);
$end_sunday = mktime(0, 0, 0, $end_array[mon], $end_array[mday]- $end_array[wday],$end_array[year]);
// Calculate days in the whole weeks
$week_diff = $end_sunday - $start_sunday;
$number_of_weeks = round($week_diff /604800); // 60 seconds * 60 minutes * 24 hours * 7 days = 1 week in seconds
$days_in_whole_weeks = $number_of_weeks * 5;
//Calculate extra days at start and end
//[wday] is 0 (Sunday) to 7 (Saturday)
$days_at_start = 6 - $start_array[wday];
$days_at_end = $end_array[wday];
$total_days = $days_in_whole_weeks + $days_at_start + $days_at_end;
return $total_days;
}
To take holidays into account, you'd have to work out the number of days using this function, then use a query like
Select count (holiday_date) from holidays
where holiday_date between start_date and end_date
and DAYOFWEEK(holiday_date) not in (1,7)
Be careful that there isn't a problem with the end_date being treated as 00:00 (i.e. first thing in the morning) - you may have to condition it to be 23:59:59 so that it works properly. It all depends on how your holidays are stored.
To return the holidays in the same time period and subtract that from the number you first thought of.