What distinguishes /calendar from /news is that items may be categorized and the display at a large site might be personalized to a user's country, state, or zip code. Also, if there are too many items to display comfortably, the non-expired events coming up soonest get displayed.
See www.harpcolumn.com for a good running example that distinguishes /news from /calendar.
Comments are handled by the general comments facility.create sequence calendar_category_id_sequence start with 1 ; create table calendar_categories ( category_id integer primary key, -- if scope=public, this is the address book the whole system -- if scope=group, this is the address book for a particular group scope varchar(20) not null, group_id references user_groups, category varchar(100) not null, enabled_p char(1) default 't' check(enabled_p in ('t','f')), constraint calendar_category_scope_check check ((scope='group' and group_id is not null) or (scope='public')), constraint calendar_category_unique_check unique(scope, category, group_id) ); create index calendar_categories_group_idx on calendar_categories ( group_id ); create sequence calendar_id_sequence start with 1; create table calendar ( calendar_id integer primary key, category_id not null references calendar_categories, title varchar(100) not null, body varchar(4000) not null, -- is the body in HTML or plain text (the default) html_p char(1) default 'f' check(html_p in ('t','f')), start_date date not null, -- first day of the event end_date date not null, -- last day of the event (same as start_date for single-day events) expiration_date date not null, -- day to stop including the event in calendars, typically end_date event_url varchar(200), -- URL to the event event_email varchar(100), -- email address for the event -- for events that have a geographical location country_code references country_codes(iso), -- within the US usps_abbrev references states, -- we only want five digits zip_code varchar(10), approved_p char(1) default 'f' check(approved_p in ('t','f')), creation_date date not null, creation_user not null references users(user_id), creation_ip_address varchar(50) not null );
The /bboard system is better if you want to support lively discussion and archive the exchanges.