Version: $Id: index.html,v 1.5 2003/10/29 08:36:52 harryf Exp $
API Docs : Examples : Tutorials : Download
PEAR::Calendar is an package for generating Calendars as data structures (it does not render content - that's your job!) allowing you to easily connect up your user interface with an underlying data store (such as MySQL).
It provides a simple API to make generating a calendar much like querying a database - just pick a date you want then render the output with a loop. For example;
require_once('Calendar/Month.php'); $Month = & new Calendar_Month(); $Month->build(); while ( $Day = & $Month->fetch() ) { echo ( $Day->thisDay() ."\n" ); }
$Day->thisYear()
and $Day->thisMonth()
.$Second->lastMonth()
or $Second->nextSecond()
.What if you want WML, SOAP, PDF, GIF, command line, etc. etc.? PEAR::Calendar can be used to generate any output format you like (see the examples for SOAP and WML). Tying it to a particular output content type will limit it's use (a problem that every public domain PHP Calendar library I've looked at suffers from). A PEAR::HTML_Calendar is likely to be developed using PEAR::Calendar.
Leave your attitude towards OOP behind - PHP makes an excellent OO language. On Sourceforge's high overworked servers, it's generating calendars in under 0.1 seconds (see example 3). The code is well optimized and designed only to include the classes needed for the current operation.
All calculations are handled by a class implementing the Calendar_Engine interface. Currently the only implemention is based on PHP's date()
and mktime()
functions (so Unix timestamps are required for that engine).
Because all calculations are externalized, it should be possible to implement different engines (in theory - not tested yet) for example PEAR::Date should be able to be used as the basis for an engine (if not - it needs fixing). Hopefully that also means you can implement something like a Chinese calendar. See the Calendar/Engine/Interface.php
to see what an engine has to provide (note that this file is not used anywhere but simply there to make the engine interface clear to developers). One the engine is written, modification will need to be made to Calendar/Engine/Factory.php
to allow it to be used.
PEAR::Calendar only uses base 10 numbers for calculations - the names of months and days of the week and generated as the calendar is being rendered (by you). You should only need to change PHP's locale with setlocale()
and use the strftime()
function e.g.;
$Day = & new Calendar_Day(2003,10,23); setlocale (LC_TIME, 'de_DE'); // German echo ( strftime('%A %d %B %Y',$Day->getTimeStamp()));(note
setlocale
usage varies depends on OS).
October 2003 M T W T F S S 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31Notice the top left and botton right of this example - these are "EmptyDays". EmptyDays are generated only by two calendar classes:
Calendar_Month_Weekdays
and Calendar_Week
. For example using Calendar_Month_Weekdays
;
require_once('Calendar/Month/Weekdays.php'); $Month = & new Calendar_Month_Weekdays(); $Month->build(); while ( $Day = & $Month->fetch() ) { if ( $Day->isFirst() ) // Check for the start of a week echo ( "\n" ); if ( $Day->isEmpty() ) // Check to see if day is empty echo ( "\t" ); else echo ( $Day->thisDay()."\t" ); if ( $Day->isLast() ) // Check for the end of a week echo ( "\n" ); }Using
Calendar_Week
, you will only get 7 days (use Calendar_Month_Weeks
to get Calendar_Week
objects), so the isFirst()
and isLast()
methods are not applicable.
All calendar objects (except Calendar_Second, which has no "children") have the method build() to build the "children" of that object. For example Calendar_Year::build()
builds Calendar_Month
objects while Calendar_Hour::build()
builds Calendar_Minute objects.
You have the option of passing this method an indexed array of Calendar objects which will be used to "select" the matching built children. For example;
$Month = & new Calendar_Month(2003,10); // Oct 2003 $SelectedDay1 = & new Calendar_Day(2003,10,5); Oct 5th 2003 $SelectedDay2 = & new Calendar_Day(2003,10,21); Oct 21st 2003 // Place in an array... $selection = array($SelectedDay1,$SelectedDay2); $Month->build($selection); while ($Day = & $Month->fetch()) { if ( $Day->isSelected() ) echo ( $Day->thisYear()." ".$Day->thisMonth()." ".$Day->thisDay()." is selected\n" }
Note: date objects you pass to a build()
method replace existing date objects, allowing you to do things like apply a Calendar_Decorator
to them.
build()
explicitly. Why can't children be built automatically?First and foremost, for performance. Building the children has a performance cost and you won't always need to have the children, so it should be called explicitly, other wise you might have $Year->build()
, expecting to get just months but behind the scenes, months built days, which built hours, which build minutes etc.
Also calling build()
yourself give you a chance to "select" some of the children.
Validity is determined by the Calendar_Engine being used as well as the time the date object you're working with represents (e.g. $Month = & new Month(2003,2,29);
is invalid, because Feb 2003 was not a leap year).
For quick validation, you can call the method isValid()
on any date object, which will return FALSE
if there's a problem. For more information of more detailed validation, you can call the method getValidator()
on any date object, which returns an instance of the class Calendar_Validator
. For example;
$Month = & new Month(2003,2,29); if (! $Month->isValid() ) { $Validator = & $Month->getValidator(); while ( $Error = $Validator->fetch() ) { echo ( $Error->toString() ); } }
You can also begin validation by calling getValidator()
then either isValidYear()
, isValidMonth()
, isValidDay()
, isValidHour()
, isValidMinute()
and isValidSecond()
(or isValid()
which calls all of the preceding methods).
Note: the method isValidWeek()
also exists but needs to be explicitly called and expects you to have got your validator from a Calendar_Week
object.
build()
, I just want to get a single child date object with looping through the lot. How?The method fetchAll()
can be called on any date object to get an indexed array of all the children which have been built, allowing you to reference them directly. Be careful with the first index of this array - in some cases it will be [1] not [0], depending on the type of date object built. For example;
$Month = & new Calendar_Month(2003,10); $Month->build(); $days = & $Month->fetchAll(); // Now all in array echo ( $days[1]->thisDay() ); // The first day has index 1 $Hour = & new Calendar_Hour(2003,10,25,15); // Oct 25th 2003, 3pm $Hour->build(); $hours = & $Hour->fetchAll(); // Now all in array echo ( $hours[0]->thisHour() ); // The first hour has index 0The following classes are always built to have the first index as 1:
Calendar_Month
, Calendar_Month_Weekdays
, Calendar_Month_Weeks
, Calendar_Week
and Calendar_Day
Calendar_Hour
, Calendar_Minute
and Calendar_Second
Note also the method size()
can be called on any date object, after build()
has been called, to get the number of children.
A week in PEAR::Calendar is a tabular week - i.e. a week is a single row when displaying a month in calendar in tabular form (see the example above). Any given month will either have 4, 5 or 6 week, depending on the number of days in the month and the day of the week that the 1st of the month falls on.
Calendar_Week::nextWeek()
and Calendar_Week::lastWeek()
sometimes return nothing?If it's the first week of the month, lastWeek()
returns nothing and if it's the last week of the month, nextWeek()
returns nothing. This may change in future but for the time being, it's easier that way.
Calendar_Year
to build Calendar_Month_Weekdays
or Calendar_Month_Weeks
, instead of the default Calendar_Month
objects?When working with a Calendar_Year
, the constants CALENDAR_MONTH_STATE
controls what type of month object is built. You can define CALENDAR_MONTH_STATE
to CALENDAR_USE_MONTH_WEEKDAYS
or CALENDAR_USE_MONTH_WEEKS
for the Calendar_Month_Weekdays
and Calendar_Month_Week
classes, respectively.
Yes. For the classes which are concerned with the notion of a "week", you can can pass a value which defines the first day of the week. For the default timestamp based Calendar engine, this is a number from 0 to 6, 0 being Sunday through to 6 being Saturday.
This value can be passed to the following:
Calendar_Year::build($selection,$firstday)
- the second argument is the first day of the week.
Calendar_Month_Weekdays::Calendar_Month_Weekdays($y,$m,$firstday)
- the third argument to the constructor
Calendar_Month_Weeks::Calendar_Month_Weeks($y,$m,$firstday)
- the third argument to the constructor
Calendar_Week::Calendar_Week($y,$m,$w,$firstday)
- the fourth argument to the constructor