iCalendar Liste „Feld“ (für Datenbankschema basiert auf iCalendar-Standard)

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

  •  20-08-2019
  •  | 
  •  

Frage

meine Anwendung hat mit Kalenderinformationen (inkl. Einzel Auftreten, Wiederholung, etc.) zu behandeln. Um mit anderen Anwendungen leicht Schnittstelle Ich dachte, dass es eine gute Idee, mein Datenbankschema zu erstellen, basierend auf das iCalendar-Format (Felder, Beziehungen, Einschränkungen) würde direkt, so dass ich iCalendar kompatible Objekte über ORM bekommen, dass ich einfach aussetzen kann, wenn benötigt werden.

Ich weiß, dass die RFC verfügbar ist, aber es ist ein bisschen kompliziert, weil alle die zusätzlichen Informationen darin, dass ich nicht im Moment nicht benutzen.

Könnte mich jemand zu einer einfacheren Quelle zeigt ein Datenbankschema auf dem iCal-Standard (dh eine Liste der Felder / Feldnamen und ihre Beziehung für iCal-Einträge) auf der Grundlage zu erstellen?

Danke!

War es hilfreich?

Lösung

Ich habe dies getan (für VEvents nur, nicht TODO Artikel oder Journal entires oder so etwas unterstützen). Meine Implementierung sieht wie folgt aus (nach Spalten zu entfernen, die auf die Frage nicht spezifisch sind):

-- 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.

mit diesem gehen zusammen, ich mehrere SQL Server 2005+ CLR-Funktionen haben, die verwendet werden können, die Daten für verschiedene Veranstaltungen zu berechnen. Ich habe die folgenden Formen gefunden sehr nützlich zu sein:

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

Die Umsetzung der oben ist darn Spaß herauszufinden!

Andere Tipps

Ja, irgendwie. Sunbird (der Open-Source-mozilla Kalender) basiert auf SQLite und ich gerade heruntergeladen und entpackt den Quellcode. Es hat SQL-Dateien in ihm.

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

mozilla \ Kalender \ Provider \ storage \ schema-7.sql --dieses ist das Schema, das sunbird Anwendungen gültig iCal-Dateien zu machen, so kann es nicht so schlimm sein.

Vielen Dank Chris Nielsen für seine große Lösung oben. Allerdings hatte ich mit ihm einige Probleme, damit ich es geändert. Bitte beachten Sie, dass die Lösung oben in Python sqlalchemy ist. Ich konvertiert es sehr bald.

Meine Hauptschwierigkeiten mit Chris-Lösung (und sie könnten nicht für alle gelten) sind

  1. Ich brauche nicht viele der Spalten in seiner Lösung. Ich brauchte nur Spalten, die mich mit Events und Rezidive helfen würde. Dies ist die Schuld der iCalendar-Spezifikation, nicht Chris. Meine Lösung unten betrachtet nur Wiederholungsregeln in Bezug auf ihre Kalender Einschränkungen und die Reihenfolge Einschränkungen.

  2. Bestimmte Spalten - was am wichtigsten ist dtstart und DTEND - gehören zu VEVENT, nicht RRULE, aber Chris legte sie in RRULE. Das war verwirrend für mich. VEVENT: https://tools.ietf.org/html/rfc5545#section- 3.6.1 RRULE: https://tools.ietf.org/html/rfc5545#section- 3.3.10

  3. Ich auch, um herauszufinden, wie benötigt einen Zeitplan enthalten, die eine Vielzahl von Mustern haben könnte. Zum Beispiel könnte ein Ereignis jede Woche am Freitag von 06.00 bis 21.00 passieren, aber auch die ganzen Tag am Maifeiertag. Dies erfordert Flexibilität mit dtstart und DTEND. Aus diesem Grund habe ich eine Tabelle enthält „ZEITPLAN“, die mit EVENTS eine many-to-many-Beziehung unterhält, während EVENTS eine Einschließungsbeziehung mit RRULES haben.

Im Folgenden finden Sie meine Lösung in sqlalchemy. Ich werde dies so schnell wie möglich konvertieren SQL.

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 ist eine Apple-Anwendung, die den Standard derzeit bekannt als iCalendar (der Nachfolger des bisherigen VCALENDAR) folgt. Ich denke, die Wikipedia Eintrag hat alle Informationen, die Sie für Ihre Zwecke benötigen, und in einem einfachen und einfach zu verstehenden Format, aber fühlen Sie sich frei, um weitere Führung zu bitten, wenn nötig !!!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top