icalendar "Field"목록 (icalendar 표준을 기반으로 한 데이터베이스 스키마 용)

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

  •  20-08-2019
  •  | 
  •  

문제

내 응용 프로그램은 달력 정보 (단일 발생, 재발 등)를 처리해야합니다. 다른 응용 프로그램과 쉽게 인터페이스하기 위해 icalendar 형식 (필드, 관계, 제약 조건)을 기반으로 데이터베이스 스키마를 생성하는 것이 좋습니다. 필요합니다.

RFC를 사용할 수 있다는 것을 알고 있지만 현재 사용하지 않는 모든 추가 정보 때문에 복잡합니다.

누군가가 ICAL 표준 (필드/필드 이름 목록 및 ical 항목과의 관계를 의미 함)을 기반으로 데이터베이스 스키마를 만들기 쉬운 소스를 지적 할 수 있습니까?

감사!

도움이 되었습니까?

해결책

나는 이것을했다 (Vevents의 경우, TODO 항목이나 저널 삽관 또는 그와 비슷한 것을 지원하지 않는 경우). 내 구현은 다음과 같습니다 (질문에 구체적이지 않은 열을 제거한 후) :

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

이것과 함께하기 위해 다양한 이벤트의 날짜를 계산하는 데 사용할 수있는 여러 SQL Server 2005+ CLR 기능이 있습니다. 다음 형식이 매우 유용하다는 것을 알았습니다.

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

위의 구현은 알아내는 것이 재미 있습니다!

다른 팁

예, 일종의. Sunbird (OpenSource Mozilla Calendar)는 SQLITE를 기반으로하며 방금 소스 코드를 다운로드하여 풀었습니다. .sql 파일이 있습니다.

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

Mozilla Calendar Providers Storage Schema-7.sql-Sunbird가 유효한 파일을 만들기 위해 사용하는 스키마이므로 너무 나쁠 수는 없습니다.

위의 위대한 솔루션에 대해 Chris Nielsen에게 감사드립니다. 그러나 나는 그것에 문제가 있었기 때문에 수정했습니다. 위의 솔루션은 Python Sqlalchemy에 있습니다. 곧 변환하겠습니다.

Chris의 솔루션에 대한 나의 주요 어려움은

  1. 그의 솔루션에 많은 열이 필요하지 않았습니다. 이벤트와 재발에 도움이되는 열만 필요했습니다. 이것은 Chris의 것이 아니라 Ialendar 사양의 잘못입니다. 아래의 내 솔루션은 달력 제한 및 시퀀스 제한 측면에서 재발 규칙 만 고려합니다.

  2. 가장 중요한 DTStart 및 DTEND는 특정 열이 rrule이 아닌 Vevent에 속하지만 Chris는 rrule에 배치했습니다. 이것은 나에게 혼란 스러웠다. Vevent : https://tools.ietf.org/html/rfc5545#section-3.6.1rrule : https://tools.ietf.org/html/rfc5545#section-3.3.10

  3. 또한 다양한 패턴을 가질 수있는 일정을 포함하는 방법을 알아 내야했습니다. 예를 들어, 이벤트는 금요일 오후 6 시부 터 오후 9 시까 지 매주 그리고 5 월에 하루 종일 이벤트가 발생할 수 있습니다. 이를 위해서는 DTSTART 및 DTEND의 유연성이 필요합니다. 이러한 이유로, 나는 이벤트와 다수의 관계를 유지하는 포함 테이블 "일정"을 만들었고, 이벤트는 rrules와의 관계를 갖습니다.

아래는 sqlalchemy의 내 솔루션입니다. 이것을 최대한 빨리 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은 현재 ICalendar (이전 VCALENDAR의 후임자)로 알려진 표준을 따르는 Apple 응용 프로그램입니다. 위키 백과를 생각합니다 기입 목적에 필요한 모든 정보와 간단하고 팔로우하기 쉬운 형식으로 필요한 경우 더 많은 지침을 요청하십시오 !!!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top