Vlado Keselj's home page >> Software
[Directory with downloads]

Calendar::Schedule

Calendar::Schedule is Perl module used to manage a personal calendar of appointments.


NAME

Calendar::Schedule - manage calendar schedules

SYNOPSIS

    use Calendar::Schedule qw/:all/;

    my $TTable = Calendar::Schedule->new();

    # manually adding an entry
    $TTable->add_entry('2003-09-09 Tue 18-20 Some meeting');
                              
    # reading entries from a file
    $TTable->add_entries_from("$ENV{'HOME'}/.calendar");

    # producing entries in HTML tables, one table per week
    $TTable->set_first_week('now');
    print "<p>\n" . $TTable->generate_table();
    print "<p>\n" . $TTable->generate_table();
    print "<p>\n" . $TTable->generate_table();

    # for more examples, see EXAMPLES section

The file .calendar may look like this:

  # comments can start with #
  * lines starting with * are treated as general todo entries ...
  # empty lines are acceptable and ignored:

  Mon 9:00-10:00 this is a weekly entry
  Mon 13-14 a biweekly entry :biweekly :start Mar 8, 2004
  Mon,Wed,Fri 15:30-16:30 several-days-a-week entry
  Wed :biweekly garbage collection

  2004-03-06 Sat 14-16 fixed entry. The week day is redundant, but may\
        help to detect errors (error will be reported if a wrong\
        weekday is entered).  BTW, an entry can go for several lines as\
        long as there is a backslash at the end of each line.

  May   6      birthday (yearly entry)

  # more examples in "Example entries" section

DESCRIPTION

The module is created with a purpose to provide functionality for handling a personal calendar schedule in a transparent and simple way. The calendar data is assumed to be kept in a plain file in a format easy to edit and understand. It was inspired by the calendar program on older Unix-like systems, which used ~/.calendar file to produce entries for each day and send them in the morning by email.

Inspired by the ~/.calendar file, the format for recording scheduled events is very simple, mostly contained in one line of text.

The module currently supports generation of HTML weekly tables with visual representation of scheduled events. The generated table is generated in a simple HTML table, with a use of colspan and rolspan attributes to represent overlapping events in parallel in the table.

Planned Future Work

In the development of the recording format for the event, there is an attempt to model the data representation of the iCalendar standard (RFC2445). Examples of the iCalendar fields are: DTSTART, DTEND, SUMMARY, RRULE (e.g. RRULE:FREQ=WEEKLY, RRULE:FREQ=WEEKLY;INTERVAL=2 for biweekly, RRULE:FREQ=WEEKLY;UNTIL=20040408 ) etc. More examples:

  RRULE:FREQ=MONTHLY;BYDAY=TU;BYSETPOS=3

Every third Tuesday in a month.

EXAMPLES

First example:

    use Calendar::Schedule qw/:all/;

    my $TTable = Calendar::Schedule->new();

    # manually adding an entry
    $TTable->add_entry('2003-09-09 Tue 18-20 Some meeting');
                              
    # reading entries from a file
    $TTable->add_entries_from("$ENV{'HOME'}/.calendar");

    # producing entries in HTML tables
    $TTable->set_first_week('2003-12-15');
    print "<p>\n" . $TTable->generate_table();
    print "<p>\n" . $TTable->generate_table();
    print "<p>\n" . $TTable->generate_table();

Example with generating a weekly schedule (example2):

    use Calendar::Schedule;
    $TTable = Calendar::Schedule->new();
    $TTable->{'ColLabel'} = "%A";
    $TTable->add_entries(<<EOT
    Mon 15:30-16:30 Teaching (CSCI 3136)
    Tue 10-11:30 Teaching (ECMM 6014)
    Wed 13:30-14:30 DNLP
    Wed 15:30-16:30 Teaching (CSCI 3136) :until Apr 8, 2005
    Thu 10-11:30 Teaching (ECMM 6014)
    Thu 16-17 WIFL
    Fri 14:30-15:30 MALNIS
    Fri 15:30-16:30 Teaching (CSCI 3136)
    EOT
    );
    print "<p>\n" . $TTable->generate_table();

This will produce the following HTML code (if run before Apr 8, 2005):

  Monday Tuesday Wednesday Thursday Friday Saturday Sunday
08:00              
10:00   Teaching (ECMM 6014)   Teaching (ECMM 6014)      
11:30              
12:00              
13:30     DNLP        
14:30         MALNIS    
15:30 Teaching (CSCI 3136)   Teaching (CSCI 3136)   Teaching (CSCI 3136)    
16:00   WIFL    
16:30            
17:00              

Conflicts

Time conflicts are handled by producing several columns in a table for the same day. For example, the following code (example3):

    use Calendar::Schedule;
    $TTable = Calendar::Schedule->new();
    $TTable->{'ColLabel'} = "%A";
    $TTable->add_entries(<<EOT

    Mon 15:30-16:30 Teaching (CSCI 3136)
    Tue 10-11:30 Teaching (ECMM 6014)
    Wed 13:30-14:30 DNLP
    Wed 15:30-16:30 Teaching (CSCI 3136) :until Apr 8, 2005
    Thu 10-11:30 Teaching (ECMM 6014)
    Thu 16-17 WIFL
    Fri 14:30-15:30 MALNIS
    Fri 15:30-16:30 Teaching (CSCI 3136)
    Wed 15-16 meeting
    Wed 15:30-18 another meeting

    EOT
    );
    print "<p>\n" . $TTable->generate_table();

will produce the following table (if run before Apr 8, 2005):

  Monday Tuesday Wednesday Thursday Friday Saturday Sunday
08:00                  
10:00   Teaching (ECMM 6014)       Teaching (ECMM 6014)      
11:30                  
12:00                  
13:30     DNLP            
14:30             MALNIS    
15:00       meeting        
15:30 Teaching (CSCI 3136)   Teaching (CSCI 3136) another meeting   Teaching (CSCI 3136)    
16:00     WIFL    
16:30              
17:00                
18:00                  

Example entries

These are some example of simple entries that are accepted by the add_entry function or add_entries_from for reading from a file. Each entry is on a line by itself, but it can be continued in the the following lines by using \ (backslash) at the end of the current line. The time specificantions are generally at the beginning of an entry. Examples:

  # comments can start with #
  # empty lines are acceptable and ignored:

  Mon 9:00-10:00 this is a weekly entry
  Mon 13-14 a biweekly entry :biweekly :start Mar 8, 2004
  Mon,Wed,Fri 15:30-16:30 several-days-a-week entry
  Wed :biweekly garbage collection

  2004-03-06 Sat 14-16 fixed entry. The week day is redundant, but may\
        help to detect errors (error will be reported if a wrong\
        weekday is entered).  BTW, an entry can go for several lines as\
        long as there is a backslash at the end of each line.

  May 6  an example birthday (yearly entry)

  Wed 13:30-14:30 DNLP
  Wed 15:30-16:30 Teaching (CSCI 3136) :until Apr 8, 2005
  Wed 3-4:30pm meeting
  Mon,Wed,Fri 10:30-11:30 meeting (product team)
  Mon 13-14 seminar :biweekly :start Mar 8, 2004
  Tue,Thu 10-11:30 Class (ECMM 6014) Location: MCCAIN ARTS&SS 2022 :until Apr 8, 2004
  1st,3rd Tue 10-11 meeting
  1st,last Mon,Fri 4-5 meeting (4 meetings every month)
  4th Thu 11:30-13 meeting (fcm)

STATE VARIABLES

StartTime

Used as $obj->{StartTime}. Start time for various uses. Usually it is the the beginning of the first interesting week.

DefaultRowLabels

Used as $obj->{DefaultRowLabels}. Includes pre-defined labels for rows of the generated HTML schedule tables. The pre-defined value is:

    $self->{DefaultRowLabels} = [qw( 08:00 12:00 17:00 )];

METHODS

new()

Creates a new Calendar::Schedule object and returns it.

set_first_week(time)

sets start time at the last Monday before given date. It is used in generate_table. Examples:

 $TTable = Calendar::Schedule->new();
 $TTable->set_first_week('now');
 $TTable->set_first_week('2016-02-19');

See parse_time for examples for specifying time.

set_ColLabel(pattern)

sets strftime pattern for column (day) labels. The default pattern is "%A<br>%Y-%m-%d", which produces labels like:

  Friday
  2003-12-19

In order to have just a weekday name, use "%A".

parse_time(time_specification[,prefix])

Parses time specification and returns the calendar time (see mktime in Perl). The functions dies if the time cannot be completely recognized. If prefix is set to true (1), then only a prefix of the string can be a time specification. If prefix is set to 1, then in an array context it will return a 2-element list: the calendar time and the remainder of the string. Format examples:

  2004-03-17
  now
  Mar 8, 2004
  1-Jul-2005
add_entries_from(file_name)

Adds entries from a file. See method add_entries and add_entry for format explanation.

add_entries(list_of_entries)

Adds more entries. Each entry may contain several entries separated by a new-line, except if the line ends with \. Empty lines and lines that start with \s*# are ignored. See add_entry for further explanation of format.

add_entry(list_of_entries)

Adds more entries. It is different from add_entries because this method does not break entries on new-lines, although it does accept a list of entries as arguments.

Examples:

  $TTable->add_entry('Mon 8-17', 'Labour Day');
  $TTable->add_entry('2003-09-09 Tue 18-20 Some meeting');

More format examples:

  Wed 3-4:30pm meeting
  Mon,Wed,Fri 15:30-16:30 meeting (product team)
  Mon 13-14 seminar :biweekly :start Mar 8, 2004
  Tue,Thu 10-11:30 Class (ECMM 6014) Location: MCCAIN ARTS&SS 2022 :until Apr 8, 2004
  1st,3rd Tue 10-11 meeting
  1st,last Mon,Fri 4-5 meeting (4 meetings every month)

More examples can be found in section "Example entries".

find_next_time(time_spec[,start_time])

Finds next time starting from start_time according to time_spec specification and returns it. If the start_time is not given, the variable StartTime is used.

Examples:

    $t = $schedule->find_next_time("23:59", $t);
generate_table()

Returns a weekly table in HTML. Starts with NextTableTime (or StartTime if NextTableTime does not exist), and updates NextTableTime so that consecutive call produces the table for the following week.

The table column headers can be can be changed by setting the field $obj->{ColLabel} to a format as used by the standard function strftime. The default format is: ColLabel => "%A<>%Y-%m-%d", which looks something like:

   Monday
 2008-09-01

The format "%A" would produce just the weekday name.

Use $obj->{ShowDays} = 'workdays'; to display only work-days; i.e., Monday to Friday.

The table rows include time labeles which are start times and end times of the events that happend to fall in the table time range, with additional labels from the variable $obj->{DefaultRowLabels}. The default value of the variable DefaulRowLabels is defined as:

    $self->{DefaultRowLabels} = [qw( 08:00 12:00 17:00 )];

FUNCTIONS

weekday_to_digits

For example, changes all words "SUNDAY", "Sunday", "SUN", or "Sun" to "00", etc.

CONTRIBUTORS

I would like to thank Stefan Goebel for his report and detailed analysis of a bug and suggestions, Mike Vasiljevs for his suggestions and patches for ISO8601 format, Mohammad S Anwar for correction regarding missing license field, Slaven Rezic from the CPAN testers for useful bug reports, Gabor Szabo for the initial GitHub CI code.

AUTHOR

Copyright 2002-2021 Vlado Keselj (vlado@dnlp.ca http://vlado.ca) and the contributors (section CONTRIBUTORS).

This script is provided "as is" without expressed or implied warranty. This is free software; you can redistribute it, modify it, or both under the same terms as Perl itself.

The latest version can be found at http://vlado.ca/srcperl/Calendar-Schedule/.

SEE ALSO

There are some Perl modules for different types of calendar, and likely may more in other programming languages. I could not find any existing calendars including the particular features that I needed, so this module was created. Below are some modules with similar functionality:

[HTML::CalendarMonthSimple] - Perl Module for Generating HTML Calendars

The module is written as a simplifed version of HTML::CalendarMonth. The intention for this, Calendar::Schedule module, is not to tie it essentially for HTML. The events specification is described in a simple textual format.

[HTML::CalendarMonth] - Generate and manipulate HTML calendar months

The module HTML::CalendarMonth is a subclass of HTML::ElementTable, which makes it a part of larger project--the Date-Time Perl project at http://datetime.perl.org.