[asterisk-dev] Calendaring API

John Todd jtodd at digium.com
Wed Oct 8 02:52:21 CDT 2008


To top-summarize:

I don't have any problem with the start/duration method you describe, 
and I agree that it provides a more standard time parsing engine 
method.  I just tried to make it easier with my syntax, but I think 
by trying to make it easier, it became more difficult.  :-)   Your 
method makes more sense.

I was thinking a bit about the caching issue.  Perhaps there is a way 
to temporarily cache and refresh unnamed calendars automatically?  In 
the [general] section of calendars.conf, there might be something 
like this:


[general]
;
; Do we cache un-named calendars that are referenced in the dialplan?
;  This makes subsequent responses faster, which is important during
;  call processing, and also lowers network lag for full calendar
;  imports.
;
cacheunnamed=yes
;
; How long do we maintain state for an un-named calendar?  (seconds)
;  If the calendar is unused, and this timer expires, the calendar
;  is "forgotten" until next requested.  However, if the calendar is
;  queried, the counter is reset to zero and starts again.
;
cacheduration=86400
;
; Un-named calendars are refreshed this often (seconds) for the duration
;  that they live in the cache.  This keeps them "useful" to subsequent
;  queries without having to pause to re-load the entire calendar.
;  If the calendar is unreachable on a refresh, the data is maintained
;  until the cacheduration timer expires.
;
refresh=3600
;


JT



At 1:54 AM -0500 2008/10/8, Terry Wilson wrote:
>
>>  [note to future archive surfers: this syntax does not exist; it is 
>>  currently
>>  a figment of my imagination - please keep searching for what you 
>>  want, or
>>  feel free to bring this thread back from the depths.]
>>
>>
>>  core1*CLI> core show function CALENDAR_STATUS
>>   -= Info about function 'CALENDAR_STATUS' =-
>>
>>  [Syntax]
>>  CALENDAR_STATUS(<calendar_name>,<value>[,<time range>][,<event-
>>  number>])
>
>After a cursory glance I think I like the above format, but with some 
>changes to the time range functionality.  Perhaps:
>CALENDAR_STATUS(<calendar_name>,<value>[,<start-time>][,<duration>]
>[,<event-number>])
>
>>     time range = a time range for the query, in the format of:
>>
>>  YYYYMMDDHHMM["-<tzone-name>","-HH:MM"][&[YYYYMMDDHHMM["-<tzone-
>>  name>","-HH:MM"]]
>>
>>             Special name "now" can replace time and timezone.
>>             Special indicators "+" and "-" can be used to add or
>>             subtract minutes from a given time.  If no timezone is
>>             specified, Asterisk uses the timezone of the system as
>>             set locally.  Any references in timezone-names to numeric
>>             hour/minute offsets are assumed to be from GMT, and any
>>             use of "-" and "+" characters in the timezone names are
>>             considered part of the timezone name and not as modifiers.
>>             If time range is omitted, assumption is that the time
>>             is "now".
>
>My initial inclination is to prefer the times just be in seconds since 
>epoch.  We already have the EPOCH variable, so we wouldn't need the 
>"now" keyword.  Then ranges from that are easily determined by adding 
>seconds.  Time zones and date conversions could be handled with the 
>STRFTIME and STRPTIME dialplan functions.  Since the dialplan already 
>has these methods for handling time functions, it seems more Asterisk-
>y and interoperable to use them.  Let me see if I can translate all of 
>the examples...
>
>>            examples:
>>
>>             now+5
>>               Looks up any events 5 minutes from this moment.
>
>${EPOCH}, 300
>
>>             200810061440
>>               Looks up any events (using system timezone) that are
>>                occuring on Oct 6, 2008 at 14:40.
>
>${STRPTIME(200810061440,,%Y%m%d%H%M%S)}
>
>>             now&now+30
>>              Looks up any events from this moment until one half
>>               hour in the future.
>
>${EPOCH}, 1800
>
>>             now-30&now+30
>>              Looks up any events from half an hour ago to half
>  >              an hour in the future.
>
>$[${EPOCH} - 1800], 3600
>This and following queries involves a bit of calculation if using a 
>duration field, so maybe having a start and end would be easier for 
>it, but having to specify a start and endtime for querying just "right
>now" is kind of annoying.  Right now I'm envisioning not providing a
>duration as "just intersecting the start time", and maybe if 0 or a
>negative number maybe being specified meaning an open end time--all 
>events after start time (not that I'm sure that is a useful query).  
>Otherwise we could do the start and end time and and have an empty 
>start or end make the query open (+/- infinity) on that bound.  So 
>this query would be:
>$[${EPOCH} - 1800], $[${EPOCH} + 1800]
>
>>             200810061450&200810061550
>>              Looks up any events for 2:50 PM until 3:50 PM, and uses 
>>  the
>>               timezone of the local machine as the timezone modifier.
>
>${STRPTIME(20810061450,,%Y%m%d%H%M%S)}, 3600
>or
>${STRPTIME(20810061450,,%Y%m%d%H%M%S)}, ${STRPTIME(200810061550,,%Y%m%d
>%H%M%S)}
>>              200810061450-PDT&200810061550-PDT
>>              Looks up any events for 2:50 PM Pacific Daylight Time
>>               until 3:50 PM Pacific.
>
>${STRPTIME(200810061450,America/Los_Angeles,%Y%m%d%H%M%S)}, 3600
>or
>${STRPTIME(200810061450,America/Los_Angeles,%Y%m%d%H%M%S)}, $
>{STRPTIME(200810061550,America/Los_Angeles,%Y%m%d%H%M%S)}
>
>>             200810061450-08:00&200810061550-08:00
>>              Looks up any events for October 6, 2008 2:50 PM Pacific
>>               until October 6, 2008 3:50 PM Pacific, but doesn't 
>>  consider
>>               daylight savings time - just uses 8 hour offset.
>
>${STRPTIME(200810061450,GMT-8,%Y%m%d%H%M%S)}, 3600
>or
>${STRPTIME(200810061450,GMT-8,%Y%m%d%H%M%S)},$
>{STRPTIME(200810061550,GMT-8,%Y%m%d%H%M%S)}
>
>>              now-30&200810061450-08:00-120
>>              Looks up any events from half an hour in the past until
>>               two hours before October 6, 2008 2:50 Pacific
>>               (otherwise known as 12:50 PM Pacific)
>
>$[${EPOCH} - 1800], $[1800 + ${STRPTIME(200810061450,GMT-8,%Y%m%d%H%M
>%S)} - 7200 - ${EPOCH}]
>or
>$[${EPOCH} - 1800], $[${STRPTIME(200810061450,GMT-8,%Y%m%d%H%M%S)} - 
>7200]
>
>Now, I understand that most of those look relatively ugly, but there 
>are several benefits: 1) We aren't inventing yet another way to 
>represent datetimes and ranges in Asterisk.  2) With STRPTIME you can 
>pass in the time in any format you choose and then work with epoch 
>times that are easily manipulatable via simple arithmetic.  3) Using $
>{EPOCH} and offsets lets you completely ignore timezones and 
>conversions.  4) The calendaring API internallhy does everything in 
>GMT, so no more timezone processing has to be done inside the module.
>
>Most of the above is mostly academic, one is probably never going to 
>do queries in the dialplan based on specific datetimes that aren't 
>actually tied to some offset from "now".  I agree with the sentiment 
>of making queries flexible for people who might find a need for them 
>(people are really good at using things in ways you don't anticipate), 
>but implementing a new way to parse dates just inside the calendar 
>module seems to me to be a lot of work for what amounts to a semantic 
>difference which would need to be converted with STRPTIME anyway to be 
>used with other time-related dialplan functions.
>
>>  Examples:
>>
>>   These examples use a calendar which has two (poorly scheduled) 
>>  events:
>>         Oct 6, 2008 1:00 - 1:30 PM Pacific: "Get Lunch with Penny 
>>  Preddy"
>>         Oct 6, 2008 1:15 - 1:45 PM Pacific: "Mrs. Johnson conference 
>>  call"
>>   The calendar exists in calendar.conf as "calendar1".
>>   The realtime clock at the moment of this example is 1:20 PM
>>  Pacific, October 6 2008.
>>
>>    ${CALENDAR_STATUS(calendar1,busystate)}
>>      Returns "2", since there is at least one event at this moment.
>
>Assuming that 2 is the greatest value of busystate for the two events.
>
>>    ${CALENDAR_STATUS(calendar1,getnum)}
>>      Returns "2", since there are two events active at this moment.
>>
>>    ${CALENDAR_STATUS(calendar1,summary)}
>  >     Returns "Get Lunch with Penny Preddy" as the first ordered result.
>>       (see "Sorting Order..." in calendar.README)
>>
>>    ${CALENDAR_STATUS(calendar1,summary,,2)}
>>      Returns "Mrs. Johnson conference call"
>>        (see "Sorting Order..." in calendar.README)
>>
>>    ${CALENDAR_STATUS(calendar1,summary,now+20)}
>>      Returns "Mrs. Johnson conference call" since at 1:40 we only 
>>  have that one
>>        active event.
>
>${CALENDAR_STATUS(calendar1,summary,$[${EPOCH} + 1200])}
>
>>    ${CALENDAR_STATUS(calendar1,summary,now+60&now+120)}
>>      Returns a null string, since there are no entries on the calendar
>>        that match that time span.
>
>${CALENDAR_STATUS(calendar1,summary,$[${EPOCH} + 3600],3600)}
>
>>  ${CALENDAR_STATUS(calendar1,busystate,now+60&now+120)}
>>      Returns a null string, since there are no entries on the calendar
>>        that match that time span.  Note that this is different than
>>        replying with "0", which means there is an event but it is not
>>        a "busy" event.
>
>${CALENDAR_STATUS(calendar1,busystate,$[${EPOCH} + 3600, 3600)}
>
>After going through this I think I might prefer the start/end time 
>with leaving them empty for open ended queries instead of start and 
>duration.  Also, one problem is that if these queries are on an 
>unnamed calendar, each query would most likely be pulling back the 
>information for the calendar each time, which would really suck.  It 
>would be nice to come up with a way to query the range that you are 
>going to be working with, then be able to access the data with 
>successive calls w/o having to make separate http requests for each.  
>With named calendars, we would just be querying data from within the 
>timerange that is set in calendar.conf and is already cached.
>
>On a side note, unnamed calendars would not be accessible via the 
>hints interface and each call that hit them in the dialplan would most 
>likely result in a new http request.  So users would need to be aware 
>of how bad that would be on a busy system--from both a delay 
>standpoint and a hammering your calendar server standpoint.
>
>>  From a snippet of a hypothetical calendar.README file:
>>
>>  SORTING ORDER MULTIPLE EVENTS
>>
>>  If there are multiple events resulting from a query that is not a
>>  time range and is a specific moment im time, the system will create
>>  an ordered list, with the events being stacked by the nearest start
>>  time to the given query time, nearest times to the query moment
>>  ordered lowest in the list.  If one or more events have the same
>>  start time, then those events will be sub-ordered by nearest end
>>  time, nearest times to the query moment ordered lowest in the list.
>>  If one or more of those events have the same end time, then they will
>>  be further sub-ordered by their UIDs, alphabetically/numerically,
>>  with the highest ranking members appearing lowest in the resulting
>>  list.
>>
>>  If there are multiple events resulting from a query that consists of
>>  a time start/end range, the system will create an ordered list.
>>  Events that span or are equal to the starting edge of the query range
>>  will be ordered by their start time, earliest start times lowest on
>>  the list.  If one or more are equal, then sort by duration, with
>>  longer durations being lower on the list.  If one or more of those
>>  are equal, then sort alphabetically/numerically by UID, with highest
>>  ranking members appearing lowest in the resulting list.  The
>>  remaining events are sorted by earliest start time, with earlier
>>  start times being lower on the list.  If one or more of these are the
>>  same, then sort by duration, with longer durations being lower on the
>>  list.  If one or more of those are equal, then sort
>>  alphabetically/numerically by UID, with highest ranking members
>>  appearing lowest in the resulting list.
>>
>>  For example, if a calendar event ("Management Retreat Meeting") spans
>>  from 8:00A to 8:00P, and then another event ("Lunch") spans from
>>  12:00P to 1:00P, and yet another event ("Get a Soda") spans from
>>  12:00P to 12:05P, then a query about 12:03P would give an ordered
>>  list of:
>>   1: Get a Soda
>  >  2: Lunch
>>   3: Management Retreat Meeting
>>
>>  and a query about 12:00P-1:00P time span would give an ordered list 
>>  of:
>>   1: Management Retreat Meeting
>>   2: Lunch
>>   3: Get a Soda
>>
>>  Maximum number of stacked events is 255.
>>
>>  If the query is a "busystate" query without a specific event-number
>>  provided, and there is more than 1 concurrent event, then the highest
>>  busystate of all of the events will be returned.
>
>After a cursory read of the ordering stuff, it seems reasonable.
>
>Terry

-- 
John Todd
jtodd at digium.com        +1-256-428-6083
Asterisk Open Source Community Director



More information about the asterisk-dev mailing list