iCalendar「フィールド」リスト (iCalendar 標準に基づくデータベース スキーマ用)
質問
私のアプリケーションはカレンダー情報 (カレンダー情報を含む) を処理する必要があります。単一の発生、再発など)。他のアプリケーションと簡単に連携するために、iCalendar 形式 (フィールド、リレーションシップ、制約) に基づいてデータベース スキーマを直接作成し、ORM 経由で iCalendar 互換のオブジェクトを取得し、いつでも簡単に公開できるようにするのが良いのではないかと考えました。必要です。
RFC が利用可能であることは知っていますが、現時点では使用していない追加情報が含まれているため、少々複雑です。
誰かが iCal 標準に基づいてデータベース スキーマ (iCal エントリのフィールド/フィールド名とそれらの関係のリストを意味します) を作成するためのより簡単なソースを教えてくれませんか?
ありがとう!
解決
私は(TODO項目や雑誌のentiresまたはそのようなものをサポートしていない、だけVEventsのため)これをやりました。私の実装では、このようになります(質問に固有のない列を除去した後):
-- 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)
上記の実装は把握する楽しみをくそです!
他のヒント
はい、一種の。サンバード(オープンソースのMozillaのカレンダーは)sqliteのに基づいており、私はダウンロードして自分のソースコードを解凍しました。それはそれで.SQLファイルを持っています。
ftp://ftp.mozilla.org /pub/mozilla.org/calendar/sunbird/releases/0.9/source/する
Mozillaの\カレンダー\プロバイダー\ストレージ\スキーマ-7.sql - このそれはあまりにも悪いことはできませんので、Sunbirdの用途は、有効なiCalのファイルを作成するスキーマです。
上記の素晴らしいソリューションを提供してくれた Chris Nielsen に心から感謝します。ただし、いくつか問題があったので修正しました。上記の解決策は Python sqlalchemy で行われることに注意してください。すぐに変換します。
Chris の解決策に関する私の主な問題点は次のとおりです (すべての人に当てはまるわけではないかもしれません)。
彼のソリューションには多くの列は必要ありませんでした。イベントと繰り返しに役立つ列だけが必要でした。これは Chris のせいではなく、iCalendar 仕様のせいです。以下の私の解決策では、カレンダーの制限と順序の制限に関してのみ、繰り返しルールを考慮しています。
特定の列 (最も重要なのは dtStart と dtEnd) は RRULE ではなく VEVENT に属しますが、Chris はそれらを RRULE に配置しました。これは私にとって混乱を招くものでした。ヴェヴァント: https://tools.ietf.org/html/rfc5545#section-3.6.1ルール: https://tools.ietf.org/html/rfc5545#section-3.3.10
- また、さまざまなパターンがあるスケジュールをどのように含めるかを考える必要もありました。たとえば、イベントは毎週金曜日の午後 6 時から午後 9 時まで開催されるだけでなく、メーデーには終日開催される場合もあります。これには、dtStart と dtEnd の柔軟性が必要です。このため、EVENTS は RRULES と包含関係を持つのに対し、EVENTS と多対多の関係を維持する包含テーブル "SCHEDULE" を作成しました。
以下は 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 icalendar のこのドキュメントを試してみてください。フィールドをデータベース テーブルに直接複製できます。http://developer.apple.com/library/mac/#DOCUMENTATION/AppleApplications/Reference/SyncServicesSchemaRef/Articles/Calendars.html
Java を使用する場合、ical4j はスキーマとインターフェイスの間の接着剤を提供します。Java を使用しない場合は、ソース コード内のオカレンスと構造を生成するアルゴリズムが実装に役立ちます。