Liste iCalendar « Champ » (pour le schéma de base de données basé sur le standard iCalendar)

StackOverflow https://stackoverflow.com/questions/1054201

  •  20-08-2019
  •  | 
  •  

Question

ma demande doit traiter des informations de calendrier (y compris. Occurrence unique, récidive, etc.). Afin d'interfacer facilement avec d'autres applications que je pensais que ce serait une bonne idée de créer mon schéma de base de données basé sur le format iCalendar (champs, relations, contraintes) directement afin que je reçois des objets compatibles iCalendar via ORM que je peux facilement exposer quand nécessaire.

Je sais que le RFC est disponible, mais il est un peu compliqué à cause de toutes les informations complémentaires dans ce que je ne l'utilise pour le moment.

Quelqu'un pourrait-il me pointer vers une source plus facile de créer un schéma de base de données basé sur le standard iCal (ce qui signifie une liste de champs / fieldnames et leur relation pour les entrées iCal)?

Merci!

Était-ce utile?

La solution

Je l'ai fait (pour vevents, et non à l'appui des éléments TODO ou entires ou quoi que ce soit de journal comme ça). Ma mise en œuvre ressemble à ceci (après la suppression des colonnes qui ne sont pas spécifiques à la question):

-- One table for each event.  An event may have multiple rRules.
Create Table [vEvent]
    (vEventID Integer Identity(1, 1) Not Null
     Constraint [vEvent.pk]
     Primary Key
     Clustered
    ,title nVarChar(200) Not Null);

-- One table for rRules.
-- My application does NOT support the "bySetPos" rule, so that is not included.
Create Table [rRule]
    (rRuleID Integer Identity(1, 1) Not Null
     Constraint [rRule.pk]
     Primary Key
     Clustered
    ,vEventID Integer Not Null
     Constraint [fk.vEvent.rRules]
     Foreign Key
     References [vEvent] (vEventID)
     On Update Cascade
     On Delete Cascade
    ,[class]            varChar(  12) Not Null Default('public')
    ,[created]         DateTime       Not Null Default(getUTCDate())
    ,[description]     nVarChar(max)      Null
    ,[dtStart]         DateTime       Not Null
    ,[dtEnd]           DateTime           Null
    ,[duration]         varChar(  20)     Null
    ,[geoLat]          Float              Null
    ,[geoLng]          Float              Null
    ,[lastModified]    DateTime       Not Null Default(getUTCDate())
    ,[location]        nVarChar(max)      Null
    ,[organizerCN]     nVarChar(  50)     Null
    ,[organizerMailTo] nVarChar( 100)     Null
    ,[seq]             Integer        Not Null Default(0)
    ,[status]           varChar(   9) Not Null Default('confirmed')
    ,[summary]         nVarChar(  75)     Null
    ,[transparent]     Bit            Not Null Default(0)
    ,[freq]             varChar(   8) Not Null Default('daily')
    ,[until]           DateTime           Null
    ,[count]           Integer            Null
    ,[interval]        Integer        Not Null Default(1)
    ,[bySecond]         varChar( 170)     Null
    ,[byMinute]         varChar( 170)     Null
    ,[byHour]           varChar(  61)     Null
    ,[byDay]            varChar(  35)     Null
    ,[byMonthDay]       varChar( 200)     Null
    ,[byYearDay]        varChar(3078)     Null
    ,[byWeekNo]         varChar( 353)     Null
    ,[byMonth]          varChar(  29)     Null
    ,[wkSt]             Char   (   2)     Null Default('mo'));

-- Class must be one of "Confidential", "Private", or "Public"
Alter Table [rRule]
Add Constraint [rRule.ck.Class]
Check ([class] In ('confidential', 'private', 'public'));

-- Start date must come before End date
Alter Table [rRule]
Add Constraint [rRule.ck.dtStart]
Check ([dtEnd] Is Null Or [dtStart] <= [dtEnd]);

-- dtEnd and duration may not both be present
Alter Table [rRule]
Add Constraint [rRule.ck.duration]
Check (Not ([dtEnd] Is Not Null And [duration] Is Not Null));

-- Check valid values for [freq]. Note that 'single' is NOT in the RFC;
-- it is an optimization for my particular iCalendar calculation engine.
-- I use it as a clue that this pattern has only a single date (dtStart),
-- and there is no need to perform extra calculations on it.
Alter Table [rRule]
Add Constraint [rRule.ck.freq]
Check ([freq] In
    ('yearly'
    ,'monthly'
    ,'weekly'
    ,'daily'
    ,'hourly'
    ,'minutely'
    ,'secondly'
    ,'single')); -- Single is NOT part of the spec!

-- If there is a latitude, there must be a longitude, and vice versa.
Alter Table [rRule]
Add Constraint [rRule.ck.geo]
Check (([geoLat] Is Null And [geoLng] Is Null)
       Or ([geoLat] Is Not Null And [geoLng] Is Not Null));

-- Interval must be positive.
Alter Table [rRule]
Add Constraint [rRule.ck.interval]
Check ([interval] > 0);

-- Status has a set of defined values.
Alter Table [rRule]
Add Constraint [rRule.ck.status]
Check ([status] In ('cancelled', 'confirmed', 'tentative'));

-- Until and Count may not coexist in the same rule.
Alter Table [rRule]
Add Constraint [rRule.ck.until and count]
Check (Not ([until] Is Not Null And [count] Is Not Null));


-- One table for exceptions to rRules.  In my application, this covers both
-- exDate and rDate.  I do NOT support extended rule logic here;  The RFC says
-- you should support the same sort of date calculations here as are supported
-- in rRules: exceptions can recur, etc.  I don't do that; mine is simply a
-- set of dates that are either "exceptions" (dates which don't appear, even
-- if the rule otherwise says they should) or "extras" (dates which do appear,
-- even if the rule otherwise wouldn't include them).  This has proved
-- sufficient for my application, and something that can be exported into a
-- valid iCalendar file--even if I can't import an iCalendar file that makes
-- use of recurring rules for exceptions to recurring rules.
Create Table [exDate]
    (exDateID Integer Identity(1, 1) Not Null
     Constraint [exDate.pk]
     Primary Key
     Clustered
    ,rRuleID Integer Not Null
     Constraint [fk.rRule.exDates]
     Foreign Key
     References [rRule] (rRuleID)
     On Update Cascade
     On Delete Cascade
    ,[date] DateTime Not Null
    ,[type] varChar(6) Not Null);  -- Type = "exDate" or "rDate" for me; YMMV.

Pour aller de pair avec cela, j'ai plusieurs SQL Server 2005+ fonctions CLR qui peuvent être utilisés pour calculer les dates pour divers événements. J'ai trouvé les formes suivantes pour être très utile:

Select * From dbo.getDatesByVEventID(@id, @startDate, @endDate)
Select * From dbo.getEventsByDateRange(@startDate, @endDate, @maxCount)

La mise en œuvre du plaisir est sacrément ci-dessus pour comprendre!

Autres conseils

Oui, en quelque sorte. Sunbird (le calendrier mozilla opensource) est basé sur SQLite et je viens de télécharger et décompressé leur code source. Il a des fichiers .sql en elle.

ftp://ftp.mozilla.org /pub/mozilla.org/calendar/sunbird/releases/0.9/source/

mozilla \ fournisseurs calendrier de \ \ storage \ schéma 7.sql --Ce est le schéma que les usages Sunbird pour rendre les fichiers iCal valides, donc il ne peut pas être trop mauvais.

Merci beaucoup Chris Nielsen pour sa grande solution ci-dessus. Cependant, j'ai eu quelques problèmes avec elle si je l'ai modifié. S'il vous plaît noter que la solution ci-dessus est en sqlalchemy python. Je le convertir très bientôt.

Mes principales difficultés avec la solution de Chris (et ils pourraient ne pas appliquer à tout le monde) sont

  1. Je n'ai pas besoin de beaucoup de colonnes dans sa solution. Je ne avais besoin des colonnes qui me aider des événements et des récurrences. C'est la faute de la spécification iCalendar, pas de Chris. Ma solution ci-dessous ne considère règles de récurrence en termes de restrictions de calendrier et leurs restrictions de séquence.

  2. Certaines colonnes - le plus important dtstart et dtEnd - appartiennent à VEVENT, pas RRULE, mais Chris les a placés dans RRULE. Ce fut déroutant pour moi. VEVENT: https://tools.ietf.org/html/rfc5545#section- 3.6.1 RRULE: https://tools.ietf.org/html/rfc5545#section- 3.3.10

  3. J'ai aussi besoin de savoir comment contenir un calendrier qui pourrait avoir une variété de modèles. Par exemple, un événement peut se produire chaque semaine le vendredi de 18 heures-21 heures, mais aussi toute la journée le jour de mai. Cela exige de la souplesse avec dtstart et dtEnd. Pour cette raison, j'ai créé un tableau contenant « ANNEXE » qui maintient un grand nombre à plusieurs relations avec des événements, alors que les événements ont une relation de confinement avec RRULES.

Voici ma solution dans sqlalchemy. Je vais convertir en SQL dès que possible.

from app import db
from sqlalchemy import CheckConstraint
from sqlalchemy.ext.associationproxy import association_proxy


class Schedule(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    subtypes_relation = db.relationship('Event', secondary=schedule_event_association,
                                        backref=db.backref('Schedule', lazy='dynamic'))

schedule_event_association = db.Table(
    'schedule_event_association',
    db.Column('schedule_id', db.Integer, db.ForeignKey('schedule.id')),
    db.Column('event_id', db.Integer, db.ForeignKey('event.id')))

class Event(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    dt_start = db.Column(db.DateTime)  # start time
    dt_end = db.Column(db.DateTime) # end time
    tz_id = db.Column(db.String) # Time Zone

    recurrence_rule = db.Column('RecurrenceRule_id',  db.Integer, db.ForeignKey('RecurrenceRule.id'))

# Start date must come before End date
    CheckConstraint('dtEnd is NULL OR dtStart <= dtEnd', name='Valid: Time Period')

class RecurrenceRule(db.Model):
    id = db.Column(db.Integer, primary_key=True)

    # Frequency Type
    freq = db.Column(db.String(8), nullable=False, default='weekly') # type of recurrence

    # Calendar-Based Rules
    byDay = db.Column(db.String(35))   # List of Day of the Week
                                        # "mo,tu,we" for weekly
                                        # "+2MO, -1MO" = second monday, last monday for yearly or monthly
    byMonthDay = db.Column(db.String(200)) # List of Day of the Month
                                            # +1,-1"
                                            # Only for Monthly or Yearly
    byYearDay = db.Column(db.String(3078)) # List Day of the Year
                                            #"+1, -1"
                                            # Only for yearly
                                            # Take care with leap years
    byWeekNo = db.Column(db.String(353)) # Which week of Mon`enter code here`th
                                            # "+5, -3" for fifth and third-to-last
                                            # Only for yearly
    byMonth = db.Column(db.String(29))   # Month of year.

    # Sequence-Based Rules
    until = db.Column(db.DateTime)   # last day of occurence
    count = db.Column(db.Integer)    # number of occurences
    interval = db.Column(db.Integer, nullable=False, default=1) # interval between recurrences
    bysetpos = db.Column(db.String()) # Specifies specific instances of recurrence


# Valid Values
    CheckConstraint(freq in ('yearly', 'monthly', 'weekly', 'daily', 'single'),
                    name='Valid: Frequency Value')
    CheckConstraint(interval > 0, name='Valid: Positive Interval')
    CheckConstraint(byDay is not None and freq in ('daily', 'yearly', 'monthly'))
    CheckConstraint(byWeekNo is not None and freq in ('yearly', 'monthly'))
    CheckConstraint(byYearDay is not None and freq == 'yearly')

# Until and Count may not coexist in the same rule.
    CheckConstraint(not (until is not None and count is not None),
                    name='Valid: Not Both Until and Count')

iCal est une application Apple qui suit la norme actuellement connue sous le nom iCalendar (le successeur du Vcalendar précédent). Je pense que le wikipedia entrée a toutes les informations dont vous avez besoin pour vos besoins, et dans un simple et facile à suivre le format, mais ne hésitez pas à demander plus de conseils si nécessaire !!!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top