# Calendar

Calendar data is kept in db8 database storage as JSON data objects. JSON is a lightweight data-interchange text format based on a subset of the JavaScript programming language that is easy for humans to read and write and for machines to parse and generate. Like XML, JSON contains name/value pair collections and ordered list of values (i.e., arrays).

Using the db8 JavaScript wrapper API calls, you can specify the data object fields you want to retrieve using SQL-like queries and then reference them using standard JavaScript notation, i.e., object.field. See the example db8 queries in this document.

For more information on JSON, see the following websites:

- JSON objects, values and format—http://www.json.org/
- JSON schemas—http://tools.ietf.org/html/draft-zyp-json-schema-02

NOTE: A primer on how JSON data objects are formatted is beyond the scope of this document—consult the two links above for more information. However, in brief:

- Curly brackets ('{', '}') are used to enclose objects.
- Angle brackets ('[', ']') are used to enclose arrays.
- Colons (":") are used as delimiters in name/value pairs.
- Quotes (") are used for string values. Numeric values do not require string.

## Calendar Data Object Schemas and Kinds

The schemas below detail the layout of Calendar JSON data objects; 3rd party applications can access this data using the db8 JavaScript wrapper provided with Palm's JavaScript Foundation libraries. See the db8 documentation for detailed information on including and using these calls in your JavaScript code. Examples of db8 JavaScript calls are provided with some of the data type schemas detailed below.

For each stored db8 data object, you need to know the name of its kind. Kind objects in db8 define the indexes and access control for stored JSON data objects. You must specify the kind when accessing data objects of that kind.

NOTES

- The schemas below do not include the "_id", "_rev" and "_kind" fields that are automatically assigned to each stored db8 data object. If you retrieve data objects in their entirety, you will see these fields. See the db8 documentation for information about these special fields and how they are used.

- The example db8 JavaScript calls shown in the documentation below use a Foundation Library construct known as a "future", which is a kind of asynchronous callback.

- Each kind name is appended with a ":#" string indicating its version.

Schema | Description | db8 Kind
--- | --- | ---
Alarm | Parameters for a audio, email or display alarm. |
AlarmTrigger | Parameters for alarm trigger or alarm duration. |
Attendee | Event attendee - role, contact information, emails, language, name, etc. |
Calendar | Calendar data object - name, sync source, color, permissions, etc. | com.palm.calendar:1
Calendar Event | Everything about a Calendar event: attendees, dates, repeating, resources, location, subject, priority, etc. | com.palm.calendarevent:1
Calendar Preferences | User preferences: default calendar, reminder, start of day/week, ringtone, alarm, etc. | com.palm.calendarprefs:1
OrdDay | Defines an ordinal-day pair. Example: ord = 2, day = 4 (second Thursday). |
Recurrence Rule | Parameters for a repeated event. |
Rule | Recurrence rule type and value. |

## Notes on Recurrence Rules and using ordDay

If you do not know what your event's date or day of the week is (i.e.,"3rd weekday," or "2nd weekend day") you can set the Rule object's ruleType field to BYSETPOS. However, Palm does NOT currently support BYSETPOS. In Exchange, you can create most repeating events without BYSETPOS.

Listed below are events you can create — their RFC-formatted RRULE, and what that RRULE looks like as a Recurrence Rule object in our database. Listed below are the two cases where using BYSETPOS is unavoidable. In the future, when BYSETPOS is supported, the examples show how it should be formatted. Listed also, are three cases where the RRULE can be done with or without a BYSETPOS rule, and both alternatives are shown.

To summarize

- Implement the rule without BYSETPOS as it is NOT supported.
- For the two cases where you must use BYSETPOS, in the future, when BYSETPOS is supported, please do it the way indicated to ensure correct data.

### Examples

Two cases where using BYSETPOS is unavoidable:

1. Monthly on the fourth weekday of the month:

       RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=4;WKST=SU

       {freq:"MONTHLY", interval:1, wkst:0, rules:[{ruleType:"BYDAY", ruleValue:[{day:1},{day:2},{day:3},{day:4},{day:5}]}, {ruleType:"BYSETPOS", ruleValue:[{ord:4}]}]}

2. Monthly on the fourth weekend day of the month:

       RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=SU,SA;BYSETPOS=4;WKST=SU

       {freq:"MONTHLY", interval:1, wkst:0, rules:[{ruleType:"BYDAY", ruleValue:[{day:0},{day:6}]}, {ruleType:"BYSETPOS", ruleValue:[{ord:4}]}]}

Three cases where BYSETPOS could be used, but can be avoided:

1. Monthly on the fourth Friday of the month

       RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=FR;BYSETPOS=4;WKST=SU

       {freq:"MONTHLY", interval:1, wkst:0, rules:[{ruleType:"BYDAY", ruleValue:[{day:5}]}, {ruleType:"BYSETPOS", ruleValue:[{ord:4}]}]}

   OR

       RULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=4FR;WKST=SU

       {freq:"MONTHLY", interval:1, wkst:0, rules:[{ruleType:"BYDAY", ruleValue:[{ord:4, day:5}]}]}

2. Monthly on the last Friday of the month

       RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=FR;BYSETPOS=-1;WKST=SU

       {freq:"MONTHLY", interval:1, wkst:0, rules:[{ruleType:"BYDAY", ruleValue:[{day:5}]}, {ruleType:"BYSETPOS", ruleValue:[{ord:-1}]}]}

   OR

       {freq:"MONTHLY", interval:1, wkst:0, rules:[{ruleType:"BYDAY", ruleValue:[{ord:-1, day:5}]}]}

3. Yearly on the fourth Friday of March

       RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=FR;BYMONTH=3;BYSETPOS=4;WKST=SU

       {freq:"YEARLY", interval:1, wkst:0, rules:[{ruleType:"BYDAY", ruleValue:[{day:5}]}, {ruleType:"BYMONTH", ruleValue:[{ord:3}]}, {ruleType:"BYSETPOS", ruleValue:[{ord:4}]}]}

   OR

       RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=4FR;BYMONTH=3;WKST=SU

       {freq:"YEARLY", interval:1, wkst:0, rules:[{ruleType:"BYDAY", ruleValue:[{ord:4, day:5}]},{ruleType:"BYMONTH", ruleValue:[{ord:3}]}]}

These do not need a BYSETPOS rule

- Every day

      RRULE:FREQ=DAILY;INTERVAL=1;WKST=SU

      {freq:"DAILY", interval:1, wkst:0}

- Every week on Friday

      RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=FR;WKST=SU

      {freq:"DAILY", interval:1, wkst:0, rules:[{ruleType:"BYDAY", ruleValue:[{day:5}]}]}

- Every week on Friday and Saturday

      RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=FR,SA;WKST=SU

      {freq:"DAILY", interval:1, wkst:0, rules:[{ruleType:"BYDAY", ruleValue:[{day:5}, {day:6}]}]}

- Every weekday

      RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;WKST=SU

      {freq:"WEEKLY", interval:1, wkst:0, rules:[{ruleType:"BYDAY", ruleValue:[{day:1},{day:2},{day:3},{day:4},{day:5}]}]}

- Monthly on the 26th

      RRULE:FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=26;WKST=SU

      {freq:"MONTHLY", interval:1, wkst:0, rules:[{ruleType:"BYMONTHDAY", ruleValue:[{ord:26}]}]}

- Yearly on March 26

      RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTHDAY=26;BYMONTH=3;WKST=SU

      {freq:"YEARLY", interval:1, wkst:0, rules:[{ruleType:"BYMONTHDAY", ruleValue:[{ord:26}]},{ruleType:"BYMONTH", ruleValue:[{ord:3}]}]}

- Monthly on the fourth day of the month

      RRULE:FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=4;WKST=SU

      {freq:"MONTHLY", interval:1, wkst:0, rules:[{ruleType:"BYMONTHDAY", ruleValue:[{ord:4}]}]}

## Alarm

### Schema

    {
        action       : string,
        alarmTrigger : AlarmTrigger,
        attach       : string,
        description  : string,
        duration     : string,
        repeat       : int,
        summary      : string,
        trigger      : string
    }

### Elements

Element | Required | Type | Description
--- | --- | --- | ---
action | No | string | How the alarm is manifested. One or more of the following: "audio", "display", "email".
alarmTrigger | Yes | AlarmTrigger | Only first one supported. Goes off again at start if not dismissed.
attach | No | string | URL or inline binary also possible.
description | No | string | If action = "email", this is the message body. if action = "display", this is the text to display.
duration | No | string | Amount of time between repeats. If present, "repeat" is also required.
repeat | No | int | Number of times alarm should repeat. If present, "duration" is also required.
trigger | No | string | Original trigger value since we do not support everything - i.e, "TRIGGER;RELATED=END:PT5M". This field is stored on incoming and sent on outgoing, but, otherwise, not used.
summary | No | string | If action = "email", this is the message subject.

## AlarmTrigger

### Schema

    {
       "value"     : string,
       "valueType" : string

    }

### Elements

Element | Required | Type | Description
--- | --- | --- | ---
value | Yes | string | Value to use as string, i.e.: "19981208T000000Z | (+/-) PT15M"
valueType | Yes | string | "DATETIME" | "DURATION"

## Attendee

### Schema

    {
       "calendarUserType"    : string,
       "commonName"          : string,
       "delegatedFrom"       : string,
       "delegatedTo"         : string,
       "dir"                 : string,
       "email"               : string,
       "language"            : string,
       "organizer"           : boolean,
       "member"              : string,
       "participationStatus" : string,
       "role"                : string,
       "rsvp"                : boolean,
       "sentBy"              : string
    }

### Elements

Element | Required | Type | Description
--- | --- | --- | ---
calendarUserType | No | string | Comma-separated list of one or more of the following: "INDIVIDUAL", "GROUP", "RESOURCE", "ROOM", "UNKNOWN", "other".
commonName | Yes | string | Attendee name.
delegatedFrom | No | string | Delegated from person.
delegatedTo | No | string | Delegated to person.
dir | No | string | Possible LDAP reference or Web address. Not checked.
email | Yes | string | Attendee's email.
language | No | string | Attendee language. Can be anything - not validated.
member | No | string | Comma-separated list of mailto:addresses
organizer | No | boolean | Is this attendee the organizer flag.
participationStatus | No | string | Comma-separated list of one or more of the following: "NEEDS-ACTION", "ACCEPTED", "DECLINED", "TENTATIVE", "DELEGATED", "other".
role | No | string | Comma- separated list of one or more of the following: "CHAIR", "REQ-PARTICIPANT", "OPT-PARTICIPANT", "NON-PARTICIPANT", "other".
rsvp | No | boolean | RSVP flag.
sentBy | No | string | Send by person.

Example

    {
       "calendarUserType":"INDIVIDUAL",
       "commonName":"Jenna Flect",
       "email":"Jenna.Flect@palm.com",
       "role":"OPT-PARTICIPANT"
    }

## Calendar

### Schema

    {
       "accountId"     : string,
       "color"         : string,
       "excludeFromAll": boolean,
       "isReadOnly"    : boolean,
       "name"          : string,
       "syncSource"    : string,
       "UID"           : string
    }

### Elements

Element | Required | Type | Description
--- | --- | --- | ---
accountId | Yes | string | ID of db8 account. Foreign key for accounts table.
color | Yes | string | Color for Calendar entries and color picker block : "blue", "green", "yellow", "orange", "pink", "red", "purple", and "teal".
excludeFromAll | Yes | boolean | Flag to not show (true) calendar's events when 'All' is selected in a view's calendar picker.
isReadOnly | Yes | boolean | Is Calendar data read-only? For some providers, you can only download calendar data, not upload it, i.e., Facebook.
name | Yes | string | Calendar name, i.e., "Google", "Exchange", etc.
syncSource | No | string | End-point for sync source. "Local" for Palm.
UID | No | string | External sync source UID.

Example JavaScript db8 find

       var libraries = MojoLoader.require({ name: "foundations", version: "1.0" });
       var Future = libraries["foundations"].Control.Future;
       var DB = libraries["foundations"].Data.DB;

       var fquery = { "from":"com.palm.calendar:1" };

       DB.find(fquery, false, false).then(function(future) { // Get data, no watch, no count
          var result = future.result;

          if (result.returnValue == true)   // Success
          {
             Mojo.Log.info("Success: Calendar Results= "+JSON.stringify(result.results));
          }
          else // Failure
          {
             result = future.exception;
             Mojo.Log.info("find failure: Err code=" + result.errorCode + "Err message=" + result.message);
          }
       });

Example Output

    Success: Calendar Results= [{"_id":"2+3A","_kind":"com.palm.calendar:1","_rev":267, "_sync":true,"accountId":"2+31", "color":"blue", "excludeFromAll":false, "isReadOnly":false,"name":"Palm Profile","syncSource":"Local"}]

## Calendar Event

All references to "RFC" below are to RFC 5545 - Internet Calendaring and Scheduling Core Object Specification.

### Schema

    {
        "alarm"          : Alarm object,
        "allDay"         : boolean,
        "attach"         : array of RFC field,
        "attendees"      : Attendee array,
        "calendarId"     : string,
        "categories"     : string,
        "classification" : string,
        "comment"        : string,
        "contact"        : string,
        "created"        : int,
        "dtend"          : long,
        "dtstart"        : long,
        "dtstamp"        : string,
        "exdates"        : string array,
        "geo"            : string,
        "lastModified"   : int,
        "location"       : string,
        "note"           : string,
        "parentDtstart"  : int,
        "parentId"       : int,
        "priority"       : int,
        "rdates"         : string array,
        "recurrenceId"   : string,
        "relatedTo"      : string,
        "requestStatus"  : string,
        "resources"      : string,       ,
        "rrule"          :RecurrenceRule object,
        "sequence"       : int,
        "subject"        : string,
        "transp"         : string,
        "tzId"           : string,
        "url"            : string
    }

### Elements

Element | Required | Type | Description
--- | --- | --- | ---
alarm | No | Alarm array | Array of Alarm object(s).
allDay | No | boolean | All-day event flag. All-day events have NO time, only a date.
attach | No | string array | RFC field. Attachments to the event. Can be URI or binary.
attendees | No | Attendee array | Array of attendee objects.
calendarId | Yes | string | ID of source calendar - a db8 ID.
categories | No | string | RFC field. Categories associated with the event. No set values, can be anything.
classification | No | string | RFC field. "PUBLIC" "PRIVATE" | "CONFIDENTIAL".
comment | No | string | RFC field. Extra comment info for the calendar user.
contact | No | string | RFC field. A contact person associated with the event.
created | No | long | Creation timestamp, milliseconds since epoch (Midnight, Jan 1, 1970).
dtend | Yes | long | End date and time of the event. Formerly endTimestamp. Calculated in milliseconds since epoch (Midnight, Jan 1, 1970).
dtstamp | No | string | RFC field. Date and time the event was created.
dtstart | Yes | long | Start date and time of the event. Formerly startTimestamp. Calculated in milliseconds since epoch (Midnight, Jan 1, 1970).
exdates | No | string array | Array of RFC date-time strings specifying when this event does NOT repeat.
geo | No | string | lat/long coordinates listed as "float;float".
lastModified | No | long | RFC field. Date-time when this event was last modified.
location | No | string | Event location.
note | No | string | Additional text about the event.
parentDtstart | No | long | For an event that has a parent this is the parent event's dtstart
parentId | No | int | The parent event's db8 ID. See related-to for parent's UID.
priority | No | long | 0-9: 0=undefined, 1=high, 9=low.
rdates | No | string array | RFC field. Array of RFC date-time strings specifying when this event repeats.
recurrenceId | No | string | If this event is an exception to a repeating event, then this is the date-time the event was originally supposed to occur.
relatedTo | No | string | UID of parent. Do NOT confuse with parentID, which is db8 specific.
requestStatus | No | string | RFC field. The status code returned for a scheduling request. Not used.
resources | No | string | RFC field. Resources associated with the event (i.e., chairs, projector). Can be anything.
rrule | No | RecurrenceRule | Recurrence rule object, same name as old schema. Formerly string type.
sequence | No | int | RFC field. Revision number for the calendar event updated when the organizer changes the event
subject | Yes | string | Event subject.
transp | No | string | "OPAQUE" | "TRANSPARENT". Opaque if this event displays as busy on a calendar, transparent if it displays as free.
tzId | No | string | Timezone string such as "America/Los_Angeles". Formerly timeZoneID.
url | No | string | RFC field. URL associated with the event.

Example JavaScript db8 find

       var DB = libraries["foundations"].Data.DB; // Get JS wrapper for DB calls

       //** Construct query, specifying fields to retrieve and kind
       var fquery = { "from":"com.palm.calendarevent:1" };

       DB.find(fquery, false, false).then(function(future) { // Get data, no watch, no count
          var result = future.result;

          if (result.returnValue == true)   // Success
          {
             Mojo.Log.info("Success: Calendar Events= "+JSON.stringify(result.results));
          }
          else // Failure
          {
             result = future.exception;
             Mojo.Log.info("find failure: Err code=" + result.errorCode + "Err message=" + result.message);
          }
       });

Example Output

     Success: Calendar Events= [{"_id":"203n", "_kind":"com.palm.calendarevent:1", "_rev":4409, "_sync":true,"alarm":[{"_id":"203o", "action":"display", "alarmTrigger":{"value":"-PT15M", "valueType":"DURATION"}}], "allDay":false, "calendarColor":"cal-color-blue", "calendarId":"2+3A","dirty":true,"dtend":1280260800000,"dtstart":1280257200000, "height":"48px", "left":"28px","location":"Olive garden\n", "note":"Yadda yadda yadda", "onlyRepeatChanged":false,"rrule":{"freq":"DAILY", "interval":1}, "saved":false,"saving":true,"subject":"Lunch","textFieldWidth":"244px", "top":"577px", "tzId":"America/Los_Angeles","width":"292px"}],

## Calendar Preferences

### Schema

    {
       "alarmSoundOn"               : int,
       "autoDefaultCalendarID"      : int,
       "defaultAllDayEventReminder" : string,
       "defaultCalendarID"          : int,
       "defaultEventDuration"       : int,
       "defaultEventReminder"       : string,
       "endTimeOfDay"               : int,
       "isFirstUse"                 : boolean,
       "ringtoneName"               : string,
       "ringtonePath"               : string,
       "startOfWeek"                : int,
       "startTimeOfDay"             : int,
       "userChangedStartOfWeek"     : boolean
    }

### Elements

Element | Required | Type | Description
--- | --- | --- | ---
alarmSoundOn | Yes | boolean | Alarm sound on flag.
autoDefaultCalendarID | Yes | int | Default calendar ID (0).
defaultAllDayEventReminder | Yes | string | For example: "-P1D" (One day before).
defaultCalendarID | Yes | int | Palm picks calendar to use.
defaultEventDuration | Yes | int | In minutes, i.e., 30, 60.
defaultEventReminder | Yes | string | For example: "-PT15M"
endTimeOfDay | Yes | long | Millisecond timestamp. Daily end time for events, i.e., 5 PM. Calendar is greyed-out past this time. For example, -111599994 equals 05:00:01 PM, 30 Dec 1969 UTC.
isFirstUse | Yes | boolean | Flag to show Calendar's first use screen when Calendar is launched.
ringtoneName | No | string | Ringtone display name.
ringtonePath | No | string | Ringtone file path and location.
startOfWeek | Yes | int | 0 (Sunday) to 6 (Saturday)
startTimeOfDay | Yes | long | Millisecond timestamp. Daily start time for events, i.e., 9 AM. Calendar is greyed-out before this time.
userChangedStartOfWeek | Yes | int | Has user changed default (Monday) start of the week flag.

Example JavaScript db8 find

       var libraries = MojoLoader.require({ name: "foundations", version: "1.0" });
       var Future = libraries["foundations"].Control.Future;
       var DB = libraries["foundations"].Data.DB;

       var fquery = { "from":"com.palm.calendarprefs:1" };

       DB.find(fquery, false, false).then(function(future) { // Get data, no watch, no count
          var result = future.result;

          if (result.returnValue == true)   // Success
          {
             Mojo.Log.info("Success: Calendar Preferences= "+JSON.stringify(result.results));
          }
          else // Failure
          {
             result = future.exception;
             Mojo.Log.info("find failure: Err code=" + result.errorCode + "Err message=" + result.message);
          }
       });

Example Output

    Success: Calendar Preferences= [{"_id":"2+39", "_kind":"com.palm.calendarprefs:1", "_rev":266,"_sync":true, "alarmSoundOn":true, "autoDefaultCalendarID":0, "defaultAllDayEventReminder":"-P1D", "defaultCalendarID":0, "defaultEventDuration":60, "defaultEventReminder":"-PT15M","endTimeOfDay":-111599994, "isFirstUse":true,"startOfWeek":1, "startTimeOfDay":-226799992, "userChangedStartOfWeek":false}]

## ordDay

An ordinal-day pair. Example: ord = 2, day = 4 (second Thursday).

### Schema

    {
       "day" : int,
       "ord" : int
    }

### Elements

Element | Required | Type | Description
--- | --- | --- | ---
ord | Yes | int | Ordinal position of the day. Can be positive or negative.
day | Yes | int | Numeric day code - 0 (Sunday) to 6 (Saturday)

## Recurrence Rule

See Notes on Recurrence Rules and using ordDay.

### Schema

     {
        "count"    : int,
        "freq"     : string,
        "interval" : int,
        "rules"    : Rule array,
        "until"    : long,
        "wkst"     : int
    }

### Elements

Element | Required | Type | Description
--- | --- | --- | ---
count | No | int | Not currently implemented. Number of times the event should repeat. When implemented, an event can have "count" or "until", but not both.
freq | Yes | string | "DAILY" | "WEEKLY" | "MONTHLY" | "YEARLY"
interval | No | int | Frequency modifier. For example: 2 = every other, 3 = every third, etc.
rules | No | Rule array | Rules.
until | No | long | Timestamp representing when the event stops repeating - milliseconds since epoch (Midnight, Jan 1, 1970).
wkst | No | int | Number (0-6) representing starting day of the week. Goes from 0 (Sunday) to 6 (Saturday).

Example

    {freq:"MONTHLY", interval:1, wkst:0, rules:[{ruleType:"BYDAY", ruleValue:[{day:0},{day:6}]}, {ruleType:"BYSETPOS", ruleValue:[{ord:4}]}]}

## Rule

### Schema

    {
           "ruleType"   : string,
           "ruleValue"  : ordDay array
    }

### Elements

Element | Required | Type | Description
--- | --- | --- | ---
ruleType | Yes | string | RFC spec'd: BYSECOND | BYMINUTE | BYHOUR | BYDAY | BYMONTHDAY | BYYEARDAY | BYWEEKNO | BYMONTH Palm supported: BYDAY | BYMONTHDAY | BYYEARDAY | BYWEEKNO | BYMONTH
ruleValue | Yes | ordDay array |

Example

    {ruleType:"BYDAY", ruleValue:[{day:0},{day:6}]}