Example
7.30pm, second Monday each month
or
7.30pm, first & third Thursday each month.
Basically I want a upcoming events list for the next month.
How do I handle reoccurring events in PHP/MySQL?
Assuming a linux like environment: Have a cron job execute your php script.
I think cron has a pretty flexible way of recording schedules for repeating tasks, it might be worth diving into how it works (it is open source).
I also found this class for parsing crontab entries - http://www.phpclasses.org/browse/package/2568.html - I can't vouch for how good the code is, it's quite old (but crontab doesn't change much). The example given uses a MySQL database to store the tasks, so it might be worth at least looking at for ideas.
Related
I am working on a scheduler-like code (in PHP if that matters) and encountered an interesting thing: it's easy to reschedule a recurring task, but what if, for some reason, it was run significantly later, than it was supposed to?
For example, let's say a job needs to run every hour and it's next scheduled run is 13.05.2021 18:00, but it runs at 13.05.2021 20:00. Now normal rescheduling logic will be taking the original scheduled time and adding recurrence frequency (1 hour in this case), but that would make the new time 13.05.2021 19:00, which can cause to run this job twice. We could, theoretically, use the time for "last run" but it can be something like 13.05.2021 20:03, which would make new time 13.05.2021 21:03.
Now my question is: what logic can we use so that in this case next time would be 13.05.2021 21:00? I've tried googling something like this, but was not able to find anything. And I do see, that Event Scheduler in Windows, for example, does reschedule jobs in a way, that I want to do that.
I actually found a pretty easy way to do what I needed, so posting it as an answer.
If we have a value of frequency in seconds (in my case, at least) and we have the original nextrun, which is when a task was supposed to be run initially, then the logic is as follows:
We need to get current time (time(), UTC_TIMESTAMP() or whatever).
We need to compare current time against nextrun and get the difference between them in seconds.
We then calculate how many iterations of the task could have been completed in the amount of those seconds by dividing the time difference by frequency.
We round up the resulting value (ceil()). If we have a value lower than 1, we may want to sanitize it.
We multiply this rounded up value by frequency, which will give us a different result than on step 2, which is the salt of this method.
We add the resulting number of seconds to nextrun.
And that's it. This does not guarantee, that you won't ever have a task run twice, if it ended just a few seconds before the time value on step 6, but to my knowledge MS Event Scheduler has the same "flaw".
Since I am doing this calculation in SQL, here's how this would look in SQL (at least for MySQL/MariaDB):
UPDATE `cron__schedule` SET `nextrun`=TIMESTAMPADD(SECOND, IF(CEIL(TIMESTAMPDIFF(SECOND, `nextrun`, UTC_TIMESTAMP())/`frequency`) > 0, CEIL(TIMESTAMPDIFF(SECOND, `nextrun`, UTC_TIMESTAMP())/`frequency`), 1)*`frequency`, `nextrun`)
To explain by referencing the logic above:
UTC_TIMESTAMP()
TIMESTAMPDIFF(SECOND, `nextrun`, UTC_TIMESTAMP()) - time comparison in seconds.
TIMESTAMPDIFF(...)/`frequency`
CEIL(...) to round up the value. IF(...) is used to sanitize, since we can get 0 seconds, that will result in us not changing the time, at all.
CEIL(...)*`frequency`
TIMESTAMPADD(...)
I do not like having to use TIMESTAMPDIFF(...) twice because of IF(...), but I do not know a way to avoid that without moving to a stored procedure, which feels like an overkill. Besides, as far as I know, MySQL should calculate this value only once regardless. But, if someone can advise me on a cleaner approach, I'll update the answer.
There isn't a right or wrong in this situation, it really depends on your business logic and how you want to build this.
WordPress and Drupal, two of the largest CMSs out there have faced this problem, too, which boils down to "poor man's cron" versus "system cron". For a "poor man's cron", these systems rely on someone hitting the website in order to "wake" the scheduler up, and if no one visits your site in a month, your tasks don't run, either. Both of these systems instead recommend using the system's cron to be more consistent and "wake up" the scheduler at certain intervals. I would encourage you to explore this in your system, too.
The next problem is, how are you storing your recurrence? Do you have (effectively) a table with every possible run time? So for an hourly run there's 24 entries? Or is there just a single task that has an ideal run date/time? The latter is generally easier to control compared to the former which has a lot of duplicated data being stored.
Then, do tasks reschedule themselves, does the scheduler do that, or is there a middle ground where the scheduler asks the task for the next best run? Figuring this out is very important and there's some nuances.
Another thing to think about, what happens if a task runs earlier than planned? For instance, does the world break if a task runs as 01:00 and 01:15, or is it just sub-optimal.
Generally when I build these types of systems, my tasks conform to a pattern (interface in OOP) and support a "next run time". The scheduler pulls all of the tasks from a data store that have an expired "next run time" and runs them. Doing this, there's no chance for a single task to exist at both 01:00 and 02:00 because it will only exist in the data store once, for instance at 01:00. If the scheduler then wakes up at 01:15, it finds the 01:00 task which has expired and runs it, and then it asks the task for the next run. The task looks at the clock (or time as provided by the scheduler if you are running in a distributed environment) and the task performs its own logic to determine that. If the logic is every hour, you can add 60 minutes from "now" and then remove the minutes portions, so 01:15 becomes 02:00.
Throw some exception handling and possibly database transactions into this mix to guarantee that a task can't fail but still get rescheduled, too.
So I have a particular field in my database table which I would like to reset to 0 after a fixed period of time, like e.g 1 week. MY language is php. Is there any way to do it? Please help me
Okay, so basically I have a column "activation points". These points increase whenever a user does some sort of activity. But I need to reset the points to 0 every week
There is no really nice way to do this with PHP.
You have a few options:
Use MySQL's newly added, built-in, scheduler: Event Scheduler.
Use software from sources other than PHP or MySQL, like cron jobs.
Use a PHP library like PHPScheduler which isn't a true scheduler.
Option 1 is probably your best bet. It is built into MySQL, and you don't have to worry about messing with any other software that you aren't already using.
Option 2 is easy to implement, but does involve using another tool other than just PHP and MySQL. You can learn how to set up cron jobs with this post.
Option 3 is not recommended by me, unless you just absolutely want to use PHP to do this. But you will be limited on the customization of the scheduling. PHPScheduler isn't technically a true scheduler, and you can read why in this post. That post linked is older though, so it will mention that there is no scheduling available in MySQL, but since that post was made, Event Scheduler has been made.
To use Event Scheduler (Option 1), you should refer to this really really good tutorial and if you have any problems, this documentation.
Here's a preview of how easy it is to use Event Scheduler:
CREATE EVENT nazzus_cool_event
ON SCHEDULE EVERY 1 MINUTE
STARTS CURRENT_TIMESTAMP
ENDS CURRENT_TIMESTAMP + INTERVAL 1 HOUR
DO
INSERT INTO messages(message,created_at)
VALUES('Nazzus cool event just happened again!',NOW());
This code will create an event called nazzus_cool_event, and it will occur every 1 minute(s) starting at CURRENT_TIMESTAMP (now), and ending an hour from now. It will insert some data into the messages table.
It's very simple but you should definitely have a quick look at this great tutorial so that you can see some more of its great features.
You can write a simple mysql statement that will updated your field to 0 and put it on cronjob that will run every week.
edit:
Make sql statement that will reset your column, put it in php file and call it on cronjob, you can check it here , you can always use some free online solutions for cronjob like this one
My website involves scheduling recurring lessons and events. At present I have built a table using php and javascript which scans through my mysql DB, time slot by timeslot, day by day to see if there is an event scheduled or if the timeslot is free.
It works fine, but is quite clunky and ugly and to be honest, not user friendly enough. I have now built the rest of the site using JQuery along with php, JS, HTML.
I have searched far and wide for a JQuery module to sort me out for this, but every calendar/scheduler I find is for ongoing time, i.e. like the Outlook Calendar.
I want one that ONLY displays Monday - Sunday, with time intervals of a half hour - what's the best way for me to achieve this?
Many thanks in advance,
Brett
may be this can be of help if you haven checked it out already https://github.com/robmonie/jquery-week-calendar/wiki/
So I am really stumped because I have basic ideas but I am looking for some of your expertise.
What I am trying to do: I want to basically write an app using Twilio which you dont really need to know about because that is another issue. What that app does is call on a php file in my web host and "triggers the php code"
What I need help with here is how can I keep record in php of the calendar of the week for my computer. What I mean by that is if someone like an admin has a specific code that I have written for them, and that code runs automatically all week, but a specific week they dont want that code to run, instead they want a different code to run that week. How can I use php to find when a week has ended or keep track of the week using that calendar in bottom right of your computer screen so that my program will know after an admin wants a different code run from the usual code that the week is over no need to run that admin irregular code any more go back to your usual automated running code.
If you still dont know what I am talking. I will try to explain more. Think of 2 separate codes. One Custom and the other automated. The automated runs all the time automatically. But one day the admin chooses for that week he doesnt want to follow the regular shcedule of running the automated code as usual, instead for that week he would like to run the custom code and after the week is over go back to running the automated code as usual.
I hope that makes it more clear. I know that in PHP gives the date. But I really need expert opinion on how to do this.
Generally for something like this, I'd generate a "nextrun_datetime" for each and every script/user combination. By default it would have a repeat interval, in your case, 7 days.
If a user doesn't want to run it this week, they can "push" it out N days and the normal update interval would apply afterwards. To get the one-time shot, I'd allow an update interval of 0 or -1 to denote that.
With this sort of thing, whenever a script is updated (or saved, run, rescheduled), you can calculate the next date if there is one. From there, it's a relatively simple cron job that should check the last N minutes for any scripts to be run.
Unless your client machines are running on a completely different calendar than the server, why bother with wondering what the client's date is? Unless the client and server are in different time zones, the client date is going to be the same as the server date, except for a few hours around midnight.
As well, why depend on the client to trigger the server-side code? If this is a regularly occuring thing, use cron or whatever's available on the server to run the code automatically. If an admin wants to override WHICH code gets run, then you can provide an interface to change what's executed. Click a button on a site and a flag is set somewhere that tells the timed job to run script B instead of script A.
I've done something similar. Based on the day (e.g. monday, sunday) I would do something different in php.
this is how I did it:
$today = date('w');
if ($today== 0){
//its sunday
exec('rmdir C:\myApp\oldLogs');
}
else{
echo '1 -> monday, 2-> tuesday etc...'
}
you can also make a date from a string for example
$date = strtotime("8 days ago 14:00");
/*
or "Monday next week", "+1 week 2 days 4 hours 2 seconds","yesterday noon","10 September 2000" etc...
*/
I am working on an intranet web application using PHP/MySQL. My question is about scheduled events: I have 2 important dates per year (let me call them date_01 and date_02) where the system has to change the start-time of check-in for the employees. For example, at date_01 check-in starts at x-time while at date_02 check-in starts at y-time. It is like summer check-in time is different than winter check-in time ...
From software engineering point of view, what do you think is the best way of achieving this? -> Cron job?
-> MySQL scheduled events?
-> A certain PHP trick if possible?
-> Your suggestions?
Thanks
I think you don't need scheduled tasks at all. You can have a table like this:
check_ins (valid_from, valid_until, check_in_start_time)
And then do something like this when you need to get current check-in start time in your web application:
select check_in_start_time
from check_ins
where
now() >= valid_from and
now() < valid_until
I usually do that kind of tast with the system's cron
Make a file with the classic mark for external interpreter, then the php code inside tags
#!/usr/bin/php -f
<?php
function hello_world(){ echo "hi!"; }
hello_world();
?>
Then make it executable with chmod a+x my_php_files_with_commands.php and add an entry to the cron for the desired schedule. You get instant access to your application's php functions, just add the require() calls you need and play arround with it. Database access, file access, whatever... except (obviously) anything that has to do with sessions. Carefull with that.
EDIT: for the people that says not to do this as a cron... do you realize then the code will be executed if someone does something in the intranet in the chosen day? This means you are going to NEED someone actually doing something with the intranet, instead of the action beign executed at the chosen day. What if that day no one enters the intranet?
I wouldn't implement it a a scheduled job at all - I'd make the code deal with the scenario depending on the date it is processing.
Modifying te state of the system at this level means you're going to get in a mess if the rollover fails to occur. It also means that you can't easily measure historic data.
It's hard to say exactly how you should implement this without understanding more about what the system is doing. One way would be to hard-code the logic, e.g. in MySQL....
SELECT emp_id,
STRTODATE(CONCAT(DATE_FORMAT(clock_in_time, '%Y-%m-%d '),
IF(DATE_FORMAT(clock_in_time, '%m')
BETWEEN '05' AND '08', '08:00', '09:00')))
AS expected_clockin,
clock_in_time AS actual
FROM clockin
Or alternatively use a lookup table....
SELECT a.emp_id,
STRTODATE(CONCAT(DATE_FORMAT(a.clock_in_time, '%Y-%m-%d '),
b.start_time)
AS expected_clockin,
a.clock_in_time AS actual
FROM clockin a INNER JOIN lookup b
ON a.clock_in_time BETWEEN b.period_start AND b.period_end