iCal to mySQL database

drug

Новичок
iCal to mySQL database

Всем доброго!

Мне необходимо реолизовать календарь событий на PHP, НО никак не могу сформировать конечное видение представления данных. Может вы поможете..

Заказчик просит использовать базу данных на движке InnoDB, подозреваю что данных будет немало. Насколько я понимаю это напрочь отсекает использование .ics - файлов ибо парситься они будут долго!

.ics - файл стандарта iCal. Этот стандарт очень хорошо может описать любое событие в том числе повторяющееся. Второй плюс .ics - файлов то, что его можно легко обрабатывать взяв существующий алгоритм из того же php iCalendar.

Every four years, the first Tuesday after a Monday in November, forever
стандартом iCal это описывается так:
RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8

Моя проблема в том, что я просто не имею представления какую БД необходимо создать, чтобы описать это рекурсивное событие! Приходит в голову такая структура:

TBL_EVENT

id (DTSTAMP)
organization_id (UID)
summary
description
dtstart
dtend
duration
rrule (reccurence rule)
exdate_id

TBL_EVENT_EX (event exeption dates)

event_id
date


Но она решает проблему только есть dtstart и dtend или dtstart и duration.

Как же быть если это рекурсивное событие и оно описывается полем rrule???

Собственно всё. Заранее Всем огроменное(!!!) спасибо за участие!
 

Necromant

Новичок
И как работает это рекурсивное правило. Т.к. судя по внешним признакам реализует cron в красивом виде.
 

drug

Новичок
Автор оригинала: Necromant
И как работает это рекурсивное правило. Т.к. судя по внешним признакам реализует cron в красивом виде.
cорри, неправильно выразился, не рекурсивное , а повторяющееся .

1. как работает можно посмотреть здесь: Reccurence Rule
2. что есть cron?

Поможите, плз, проект горит!!!
 

alexhemp

Новичок
drug

Делаешь планировщик и не знаешь что такое cron?

Cron - это стандартный планировщик Unix. У него есть стандартный синтаксис, одинаковый для всех реализаций.
 

drug

Новичок
Дело в том, что не все одинаково сильны в Unix. Я почитал по Cron'у, мне это надо реализовать в mySQL'е.

Вопрос в том, какую структуру БД нужно сделать, чтобы она описывала повторяющиеся события?
 

Necromant

Новичок
Тот же формат
Минута Час День Месяц ДеньНедели Год


После чего
SET
http://dev.mysql.com/doc/refman/5.1/en/set.html
FIND_IN_SET
http://dev.mysql.com/doc/refman/5.1/en/string-functions.html
 

drug

Новичок
а как вы такой структурой БД опишете событие:
"Новый год"
(каждыое 1е января)

в БД это будет выглядеть так:
00 00 01 01 null 2000
00 00 01 01 null 2001
00 00 01 01 null 2002
00 00 01 01 null 2003
00 00 01 01 null 2004
..

а если событие повторяется 500 раз в год и его наблюдают в течении 100 лет, то получается 500*100=50000 записей, а если такое событие ниодно?

1. БД не резиновая
2. "2й ПН каждого Августа", при такой структуре описать не возможно!

КАК ЖЕ БЫТЬ?
 

Necromant

Новичок
"Новый год"
(каждыое 1е января)
00 00 01 01 null null


"2й ПН каждого Августа", при такой структуре описать не возможно!
00 00 null 08 01 null | 0 0 0 0 0 2 0


З.Ы. CRON
*/15 */6 1,15,31 * 1-5 В 00:00, 00:15, 00:30, 00:45, 06:00, 06:15, 06:30,
06:45, 12:00, 12:15, 12:30, 12:45, 18:00, 18:15,
18:30, 18:45, если сейчас 1-е, 15-е или 31-е число
любого месяца и только по рабочим дням недели
 

drug

Новичок
вы правы, есть над чем подумать.
допустим есть структура БД именно такая (Минута Час День Месяц ДеньНедели Год), тогда как вывеси (SQL запросом) все события удовлетворяющие условию Текущая_Дата, Текущее_Время, ведь в БД будут записи вида "*/15 и 1-5"?
 

Andreika

"PHP for nubies" reader
RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8

FREQ:UINT = интервал в секундах
BYSEC,BYMIN:UBIGINT = 0..59 биты соответствуют 0..59 секундам/минутам, в которые надо выполнять
BYHOUR:UINT = 0..23 биты...
BYDAY:UNIT = 0..30 - 1..31
BYMONTH:UTINYINT
etc

CREATETIME:UINT - время создания

[sql]
SELECT * FROM at WHERE
/* интервал */
MOD(UNIX_TIMESTAMP()-CREATETIME, FREQ)=0 AND
/* условия */
((BYSEC & (1 << SECOND(CURTIME()))) >0 OR BYSEC=0) AND
((BYMIN & (1 << MINUTE(CURTIME()))) >0 OR BYMIN=0) AND
....
[/sql]
 

drug

Новичок
1. sorry! можете разжевать, что значит
(BY_условиe & ( 1 << SECOND (CURTIME( )))) > 0 OR BY_условиe = 0

2. этот запрос выбирает все события начинающиеся в указанную дату/время, что если текущее время на несколько минут больше, но все же принадлежит промежутку start_date+duration?

3. как быть если число повторений не бесконечно, а лишь COUNT = 5?

Огроменное спасибо за ответ!
 

Andreika

"PHP for nubies" reader
1.
секунды(и остальное) хранятся в 64(или меньше)битном числе - каждый бит равный 1 означает что в эту секунду(минуту,..) надо выполнять действие
т.е. число 5 = в 2ичном виде - 0101 - 0 и 2 секунда включены

(BY_условиe & ( 1 << SECOND (CURTIME( )))) -
математику/битовые функции объяснять не буду :(

SECOND (CURTIME()) - возвращает текущее колво секунд минуты (например, 2)
проверка - включен ли бит нужной секунды(=2) в bysec (=5)
1 << 2 - сдвиг 1(0001) влево на 2 (0100)
5(0101) & 4(0100) = 4(0100) >0

OR by... = 0 или если число = 0, то подходит любой (впринципе мона это условие переделать)

2. MOD( UNIX_TIMESTAMP( ) - CREATETIME, FREQ ) - возвращает кол-во секунд прошедших после времени когда последний раз нужно было выполнять действие ... => вместо =0 можно задать условие например <=60... время начинает считаться от значения поля CREATETIME

3. добавить поле count в таблицу и проверку в запрос ) а значение поля уменьшать при каждом выполнении

-~{}~ 26.04.06 15:50:

всего RFC2445 не читал.. мож всех его возможностей такая система не понятет
 

drug

Новичок
сейчас попробую всё "пережевать" =))

Автор оригинала: Andreika всего RFC2445 не читал.. мож всех его возможностей такая система не понятет
боюсь, что ДА. но это уже что-то!!!

что если всю инфу (различные календари различных пользователей) хранить в БД (правила хранить как есть), а уже при выборе конкретного каледаря конструкцией:
while ($row = mysql_fetch_array($result))
обрабатывать каждое конкретное событие средствами PHP.

Сильно ли это затормозит работу? Или это полная глупость?
 

Andreika

"PHP for nubies" reader
drug
например какие не потянет?
или примеры какие нибудь навороченные покажи
 

drug

Новичок
Автор оригинала: Andreika
drug
например какие не потянет?
или примеры какие нибудь навороченные покажи
хотелось бы, чтобы система поддерживала все это:

PHP:
"FREQ"=freq *(

                ; either UNTIL or COUNT may appear in a 'recur',
                ; but UNTIL and COUNT MUST NOT occur in the same 'recur'

                ( ";" "UNTIL" "=" enddate ) /
                ( ";" "COUNT" "=" 1*DIGIT ) /

                ; the rest of these keywords are optional,
                ; but MUST NOT occur more than once

                ( ";" "INTERVAL" "=" 1*DIGIT )          /
                ( ";" "BYSECOND" "=" byseclist )        /
                ( ";" "BYMINUTE" "=" byminlist )        /
                ( ";" "BYHOUR" "=" byhrlist )           /
                ( ";" "BYDAY" "=" bywdaylist )          /
                ( ";" "BYMONTHDAY" "=" bymodaylist )    /
                ( ";" "BYYEARDAY" "=" byyrdaylist )     /
                ( ";" "BYWEEKNO" "=" bywknolist )       /
                ( ";" "BYMONTH" "=" bymolist )          /
                ( ";" "BYSETPOS" "=" bysplist )         /
                ( ";" "WKST" "=" weekday )              /
если не затруднит подробнее здесь: Recurrence Rule (там не много)

дело в том, что значения BYDAY, BYMONTHDAY, BYYEARDAY, BYWEEKNO, BYSETPOS могут быть отрицательными.
Each BYDAY value can also be preceded by a positive (+n) or negative
(-n) integer. If present, this indicates the nth occurrence of the
specific day within the MONTHLY or YEARLY RRULE. For example, within
a MONTHLY rule, +1MO (or simply 1MO) represents the first Monday
within the month, whereas -1MO represents the last Monday of the
month. If an integer modifier is not present, it means all days of
this type within the specified frequency. For example, within a
MONTHLY rule, MO represents all Mondays within the month.
-~{}~ 26.04.06 09:33:

кстати, нет необходимости в использовании секунд.
точность МИНУТЫ достаточна!
 

Andreika

"PHP for nubies" reader
TABLE at (
id INT AUTO_INC
interval INT sec
create_time INT UNIX_TIMESTAMP()
count INT
until INT UNIX_TIMESTAMP()
r_cnt - колво различных BY* в правиле
)

TABLE at_mf (

id INT
rule ENUM ('BYMINUTE',...,'WKST')
value INT
)

1 BYMINUTE 11
1 BYYEARDAY 22
1 BYYEARDAY -1
1 BYMONTH 3
2 BYWEEKNO 2
.......

[sql]SELECT * FROM at WHERE MOD(UNIX_TIMESTAMP()-create_time,interval)<60 AND count>0 AND until>UNIX_TIMESTAMP()[/sql]

[sql]SELECT COUNT(DISTINCT rule)>=$r_cnt FROM at_mf WHERE
id=$id AND ((rule='BYMINUTE' AND value=MINUTE(CURTIME())) OR (rule='BYMONTHDAY' AND value IN (DAYOFMONTH(CURDATE(),-дней до конца месяца) ) etc[/sql]

смысл такой - кол-во правил(разных BY*) известно заранее (вычисляется как SELECT COUNT(DISTINCT rule) WHERE id=$id ) и хранится в таблице
последним запросом проверяется сколько правил прошли проверку и если оно равно общему кол-ву, то - задание надо выполнить
 

drug

Новичок
AAAAA!!! Уже башка пухнет.. у нас 02.25, так что не особо думается :( но думаю мы на правильном пути!
можно ли связаться с вами как либо помимо форума (e-mail, ICQ, gTalk) если вдруг вопрос возникнет?

И огромное спасибо за такие содержательные ответы!!!
 
Сверху