aboutsummaryrefslogtreecommitdiff
path: root/vcalendar/recur.scm
blob: 474d228d9bfde5dc28dbadcb6e46cb3186443310 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
(define-module (vcalendar recur)
  #:use-module (srfi srfi-1)
  #:use-module (srfi srfi-9)
  #:use-module (srfi srfi-9 gnu)
  #:use-module (srfi srfi-26)
  #:use-module (srfi srfi-41)

  #:use-module (vcalendar)
  )

(define s "FREQ=WEEKLY;UNTIL=20191130")

(define (generate-kv-pairs str)
  (map (cut string-split <> #\=)
       (string-split str #\;)))

(define upstring->symbol (compose string->symbol string-upcase))

(define-syntax-rule (ensure key val test)
  ((key)
   (let ((v val))
     (if (test v)
         v
         (throw 'bad-value key val))
     )))

#;
(let ((key 'FREQ)
      (val-base 'HOURLY))
  (case key
    (FREQ (upstring->symbol val-base)
          (memv <> '(SECONDLY MINUTELY HOURLY DAILY
                           WEEKLY MONTHLY YEARLY)))))

(define-immutable-record-type <recur-rule>
  (make-recur-rules freq until count interval)
  recur-rule?
  (freq get-freq set-freq)
  (until get-until set-until)
  (count get-count set-count)
  (interval get-interval set-interval)))

(let ((s->n string->number))
 (reduce (lambda (kv rule)
        (let ((key (upstring->symbol (car kv)))
              (val-base (cadr kv)))
          (case key
            ((FREQ)
             (set-freq rule
                       (ensure (upstring->symbol val-base)
                               (cut memv <>
                                    '(SECONDLY MINUTELY HOURLY DAILY
                                               WEEKLY MONTHLY YEARLY)))))
            

            ((UNTIL)
             (set-until rule (parse-datetime val-base)))

            ((COUNT) (set-count rule (s->n val-base)))

            ((INTERVAL) (set-internal rule (s->n val-base)))

            ((BYSECOND) (let ((s (s->n val-base)))
                          (<= 0 s 60)))

            ((BYMINUTE) (let ((m (s->n val-base)))
                          (<= 0 m 59)))

            ((BYHOUR) (let ((h (s->n val-base)))
                        (<= 0 h 23)))
            
            #|
            ((BYDAY) #; TODO )

            ((BYMONTHDAY) #; TODO)
            ((BYYEARDAY)  )
            ((BYWEEKNO)  )
            ((BYMONTH)  )
            ((BYSETPOS) )
            ((WKST)  )
            |#
            (else 'err))))

      (generate-kv-pairs s)))



#|
Each recuring event should be expanded to a stream of all it's occurances.

The first instance of the event is at DTSTART,
times for following instances are calculating according to the DSL below. 
     
3.3.10. Recurrence Rule
     Value Name: RECUR
|#


#|
       byseclist   = ( seconds *("," seconds) )

       seconds     = 1*2DIGIT       ;0 to 60

       byminlist   = ( minutes *("," minutes) )

       minutes     = 1*2DIGIT       ;0 to 59

       byhrlist    = ( hour *("," hour) )

       hour        = 1*2DIGIT       ;0 to 23

       bywdaylist  = ( weekdaynum *("," weekdaynum) )

       weekdaynum  = [[±] ordwk] weekday

       ordwk       = 1*2DIGIT       ;1 to 53

       weekday     = "SU" / "MO" / "TU" / "WE" / "TH" / "FR" / "SA"
       ;Corresponding to SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY,
       ;FRIDAY, and SATURDAY days of the week.



Desruisseaux                Standards Track                    [Page 39]

RFC 5545                       iCalendar                  September 2009


       bymodaylist = ( monthdaynum *("," monthdaynum) )

       monthdaynum = [±] ordmoday

       ordmoday    = 1*2DIGIT       ;1 to 31

       byyrdaylist = ( yeardaynum *("," yeardaynum) )

       yeardaynum  = [±] ordyrday

       ordyrday    = 1*3DIGIT      ;1 to 366

       bywknolist  = ( weeknum *("," weeknum) )

       weeknum     = [±] ordwk

       bymolist    = ( monthnum *("," monthnum) )

       monthnum    = 1*2DIGIT       ;1 to 12

       bysplist    = ( setposday *("," setposday) )

       setposday   = yeardaynum



|#