Forum OpenACS Development: Calendar module and thoughts.

Posted by carl garland on

In my never ending quest to eliminate the db as much as possible, I have some thoughts/comments to those that may be porting the calendar module. It seems to me that the current acs implementation is relying on the database too much for things that could be moved over to the server.

Some Background:

The calendar functionality includes storing data (events) that need to displayed / entered into the system. The tcl module file ad-calendar-widget.tcl includes the procs to display the various calendars. While I grant that it is necessary to recall from the db the events I think that it is overkill to do any database interaction from this tcl module. The module includes 3 basic calls to the db in 2 different procedures.

  • proc_doc calendar_convert_julian_to_ansi { date } "Return an ANSI date for a Julian date" {

    Do we really need to call the DB to convert from an Julian to ANSI .... here is some hijacked GPL code that does same
    proc julian-day-to-calendar-day {jday} {
        if {$jday < 0} {
    	error "cannot convert negative julian days";
        with-global-binding tcl_precision 17 {
    	set Z [expr int($jday+0.5)]
    	set F [expr $jday+0.5-$Z];
    	if {$Z < 2299161} {
    	    set A $Z;
    	} else {
    	    set alpha [expr int(($Z - 1867216.25)/36524.25)];
    	    set A [expr $Z + 1 + $alpha - int($alpha/4)];
    	set B [expr $A + 1524];
    	set C [expr int(($B - 122.1)/365.25)];
    	set D [expr int(365.25 * $C)];
    	set E [expr int(($B - $D)/30.6001)];
    	set day [expr $B - $D - int(30.6001 * $E) + $F];
    	if {$E < 13.5} {
    	    set m [expr $E - 1];
    	} else {
    	    set m [expr $E - 13];
    	if {$m > 2.5} {
    	    set y [expr $C - 4716];
    	} else {
    	    set y [expr $C - 4715];
        return [concat $y $m $day];

  • proc calendar_get_info_from_db { { date "" } } {

    This procedure has the other 2 calls to the db the first is simply:

    set date [database_to_tcl_string $db "select sysdate()::datetime"]

    While I know that there are times to use sysdate in this case it is just used to set the date and compared to:

    set date [ns_fmttime [ns_time] "%Y-%m-%d"]

    The results on my p3 550 are ~35 microseconds for second vs. ~2500 for the 1st approach.

    The last call to the database as well does more julian date/time conversions. While tcl module functions could replace all calls in this file ideally this could be an even more efficient C module for the server. I plan on making this module at some point in future and will post it when done :)

    I think it is important to free up database interaction for where its needed, and no need to hold valuable handles if necessary. For example a simple call to produce a small year calendar took over 2 server seconds just for page processing and incurred 24 queries and much more overhead that I think could be completely eliminated. I also recommend caching the html for current calendar year or 2 and then subst any values where appropo.

    Anyway, sorry to ramble but the functionality is currently separated and before it becomes harder to do away with I think these issues should be kept in mind.

    Best Regards,

Posted by Rafael Calvo on
thanks Carl

I will be looking at this when we start porting Calendar


Posted by Jon Griffin on

I also started writing an ns_date (not the real name yet) module. Lets share the code we each have. This is a perfect use for a good ol' fashioned C module!

Posted by Tom Mizukami on

I work for a pharmaceutical company and need to be able to perform statistical analysis on data sets and have looked into Oracle's ability to call a C function directly from PL/SQL. Does PostgreSQL offer a similar ability? I will be testing the Oracle functionality with the IMSL C numerical library. Is there a way I can achieve similar functionality and remain compatible with PostgreSQL/OpenACS? Thanks for your thoughts.