PHP - Getting the next occurrence of a date between a period - php

I'm working with icalendar events that make use of RRULE to deal with repetitions;
Now, i'm aware that the are some php class like When and RRules etc.. to handle RRULE and i'm already using it, to accomplish the task of generating repeating events, but the problem is about performance with long date-range.
So i thought to speed up the task of generating repetitions by limiting the range ( start & end ) by current calendar views that are [ MONTH, WEEK, DAY ].
Assuming we have a repeating event like
FREQ=DAILY;INTERVAL=1;DTSTART:2009-01-01
what i do is obviously to change the DTSTART to today date and to add an UNTIL date to limit the loop to a close range, and it is working just fine. the problem comes with rules like these:
FREQ=WEEKLY;BYDAY=SU;DTSTART:2009-01-01
or
FREQ=WEEKLY;INTERVAL=5;DTSTART:2009-01-01
with this kind of rules my trick doesn't work because the original start date doesn't match my harcoded today date.
i have tried without luck to make some iteration using DateTime Period and Interval but i can't figure it out.
So what i'm asking is a way to find when a given date will recur in my view range that can be MONTH, WEEK, or single DAY.
thanks in advance hope someone can help me. ;)

I know the question is quite old already, but I'm going to answer just in case.
There is no reliable way to alter the rule like you are trying to do. As you noticed, as soon as you start having anything more than just the basic daily/weekly/monthly/yearly repetition your trick doesn't work anymore. And you haven't even scratched the surface yet, things like BYSETPOS and COUNT are a real nightmare.
You only have two approaches:
Either loop through all occurrences, starting from DTSTART ignoring anything that is before the start of your period, and stopping once you reach the end of the period
Or generate the full list of dates of your period, and test each one against the RRULE. This can be done with a process of elimination (example: your RRULE only occurs on Sunday and the date is not a Sunday? Then discard and move on). However in the most complex cases, the only solution is to revert to option 1 and compute all the occurrences.
While you can code these yourself, I suggest to use a lib for that. I'm the author of php-rrule and with the lib you can use getOccurrencesBetween($begin, $end) (that implements option 1) and occursAt($date) (that implements option 2).

Related

Writing for holes in ranges

I'm trying to write a program that relies on date ranges. I am trying to be able to alert users when there are holes in their ranges but I need a reliable way to find those, and to be able to handle them effectively.
My solution was to change any dates so that any day inserted into the app is rewritten so it is that day at noon. Here is the code for that:
public function reformDate($date){
return strtotime(date("F j, Y", $date)." 12:00pm");
}
This would allow me to deal with a more regular and consistent dataset. Because I only had to see how many days they were apart, rather than seeing how many seconds they were apart and making a decision whether that time quantity represented an intentional gap or not...
I saw, however, when you put something in for today at noon, then if you put something tomorrow at noon, since the values are the same, and based on my restriction:
Select * from times where :date between start and end
It triggers a response. My solution for this was to just add one to the start variable, and detract one from the end variable, so I can easily check if there are overlap by asking if the difference between the start of one and end of another is more than 2.
Anyway, my question is: is this a good way to do this? I'm particularly worried about the number 2 - do I need to worry about using such small units of time (that is unix time, by the way). Alternately, should I create a test that if two time units overlap perfectly - they should be accepted?

php/mysql how to set functions at certain time

I want to organize some kinds of actions in different periods of time, for example i want to make some UPDATES in certain days (the end of the month, the beginning of the next month, one specific day at one specific hour)...
In my example i have to follow some records that have int variable and i want to turn their values to 0 ad a certain time.
I've tried to use the sleep function but it loops over and over and i think this is not a usable solution...
Any solution?
Thanks
You probably need to read about cronjob, the below link should resolve your problem:
http://www.thegeekstuff.com/2011/07/php-cron-job/
This is an interesting link as well : http://net.tutsplus.com/tutorials/php/managing-cron-jobs-with-php-2/
in case you are using windows you can take a look at this : Use php to set cron jobs in Windows

Curve-fitting in PHP

I have a MySql table called today_stats. It has got Id, date and clicks. I'm trying to create a script to get the values and try to predict the next 7 days clicks. How I can predict it in PHP?
Different types of curve fitting described here:
http://en.wikipedia.org/wiki/Curve_fitting
Also: http://www.qub.buffalo.edu/wiki/index.php/Curve_Fitting
This has less to do with PHP, and more to do with math. The simplest way to calculate something like this is to take the average traffic for a given day over the past X weeks. You don't want to pull all the data, because fads and page content changes.
So, for example, get the average traffic for each day over the last month. You'll be able to tell how accurate your estimates are by comparing them to actual traffic. If they aren't accurate at all, then try playing with the calculation (ex., change the time period you're sampling from). Or maybe it's a good thing that your estimate is off: your site was just featured on the front page of the New York Times!
Cheers.
The algorithm you are looking for is called Least Squares
What you need to do is minimize the summed up distances from each point to the function you will use to predict the future values. For the distance to be always positive, not the absolute value is taken into calculation, but the square of the value. The sum of the squares of the differences has to be minimum. By defining the function that makes up that sum, deriving it, solving the resulting equation, you will find the parameters for your function, that will be CLOSEST to the statistical values from the past.
Programs like Excel (maybe OpenOffice Spreadsheet too) have a built-in function that does this for you, using polynomial functions to define the dependence.
Basically you should take Time as the independent value, and all the others as described values.
This is called econometrics, because its widespread in economics. This way, if you have a lot of statistical data from the past, the prediction for the next day will be quite accurate (you will also be able to determine the trust interval - the possible error that may occur). The following days will be less and less accurate.
If you make different models for each day of week, include holidays and special days as variables, you will get a much higher precision.
This is the only RIGHT way to mathematically forecast future values. But from all this a question arises: Is it really worth it?
Start off by connecting to the database and then retrieving the data for x days previously.
Then you could attempt to make a line of best fit for the previous days and then just use that and extend into the future. But depending on the application, a line of best fit isn't going to be good enough.
a simple approach would be to group by days and average each value. This can all be done in SQL

How to handle dates that repeat indefinitely

I am implementing a fairly simple calendar on a website using PHP and MySQL. I want to be able to handle dates that repeat indefinitely and am not sure of the best way to do it.
For a time limited repeating event it seems to make sense to just add each event within the timeframe into my db table and group them with some form of recursion id.
But when there is no limit to how often the event repeats, is it better to
a) put records in the db for a specific time frame (eg the next 2 years) and then periodically check and add new records as time goes by - The problem with this is that if someone is looking 3 years ahead, the event won't show up
b) not actually have records for each event but instead when i check in my php code for events within a specified time period, calculate wether a repeated event will occur within this time period - The problem with this is that it means there isn't a specific record for each event which i can see being a pain when i then want to associate other info (attendance etc) with that event. It also seems like it might be a bit slow
Has anyone tried either of these methods? If so how did it work out? Or is there some other ingenious crafty method i'm missing?
I'd take approach b and if someone adds something to it, I'd create a "real" event entry.
Edit:
How many periodic events do you expect and what kind of periodic events would that be? (eg: every monday, every two weeks etc.)
I would create a single record for a repeated event. Then in case more info has to be added to a specific date, I would create a record for the attachment with a reference to the repeated event.
Third vote for option B - rationale being that the data should only ever be queried for a limited timeframe (i.e. start and end). For performance reasons I'd suggest that, in addition to storing the date/time of the first occurrence, number of occurrences and frequency that you also maintain the last occurrence in the database.
C.
From my experience, generating recurring dates and checking if a specific date is in that pattern isn't all that bad performance-wise. There's only 365 days in a year. 10,000 days is already almost 30 years. which means, the size of the input/output is relatively small in a practical scenario.
This library may help (but it's javascript): http://github.com/mooman/recurring_dates

How do I get the difference (in seconds) between 2 dates without using: strtotime, the Zend Framework or a PEAR package?

As the title states, I want to get the difference (in seconds) between 2 (specifically between now and a date in the past) dates without using: strtotime, the Zend Framework or a PEAR package.
I don't want to get into the details of my reason but the gist of it is that I'm working with very old dates (and I do mean old, I'm talking before 0 A.D.).
It is preferred that the returned result be highly accurate down to the second of the textual timestamp given. The format to call the function should be similar to:
$bar = foo("YYYY-MM-DD HH:MM:SS", "AD"); // Where AD is Anno Domini
$baz = foo("YYYY-MM-DD HH:MM:SS", "BC"); // Where BC is Before Christ
The first person who offers a working that features:
High readability
No magic (ternary operators, etc.)
Will have their answer up-voted and accepted. Their name will be credited in the header of the source file which uses their code.
EDIT (Re: Fame):
Someone said having a name credited in the header looks bad and can be edited out. I'm talking about the header of the source file that utilizes the function I want. This isn't about "fame". Credit should be given where credit is due and I have no need to lie about who authored a work.
EDIT (Re: Accurateness):
No reason other than I want to keep with the "letter of the message" as best as I am able.
EDIT (Re: Magic):
Magic is different things to different people. In regards to the ternary operator, please respect my opinion as I respect yours. Thank you.
EDIT (Re: Old Dates and One Second Accuracy):
As a student of history, it makes sense to me. The desire for "one second accuracy" is not an absolute. Perfection, while attainable, is not required.
I'd suggest splitting each datetime into parts (year, month, date, hours, minutes, seconds). Then, with each part, do a basic sum of most more minus less recent (remembering that a BC date is effectively a negative number).
You'll never get it absolutely correct. You're going to have to consider leap years, and whether a century year is a leap year, the switch between Gregorian/Julian dates etc.
Plus I'd love to know your reasoning for the limitations and high accuracy requirement!
For all such matters see Calendrical Calculations (Google for it).
Oh, and there was no year 0 AD, the calendar went from 1BC to 1AD, or rather, we modern westerners define the calendar that way, at the time most of the world was using other systems.
Or, make calls to on-line calculators such as this one and save yourself a lot of time.
Some languages and databases do date arithmetic, some don't. If you store your dates in a database, try postgres :
pg=> SELECT now() - 'January 8, 52 BC'::DATE;
-----------------------------
754835 days 20:27:31.223035
If you don't use a DB, then it gets a bit more problematic. PHP's date arithmetic is ... well, I'd rather not talk about it. Python's is very good, but it starts at year 1BC.
You might have to roll your own...
why don't you subtract the timestamps?
mktime(16,59,0,8,7,2001) - mktime(16,59,0,8,7,2000) = seconds between them

Categories