
Brian Mackey
Top achievements
Rank 1
Brian Mackey
asked on 26 Aug 2009, 06:42 PM
In short, I need to write a regular expression to parse the data from the RuccurenceRule. I've started it with 1 row of sample data:
DTSTART:(?<StartDate>\d{8}).* DTEND:(?<EndDate>\d{8}).* FREQ=(?<Frequency>[A-Z]{0,10});INTERVAL=(?<Interval>\d{1,3});BYDAY=(?<ByDay>[A-Z]{1,3})
Because this is actually handled inside the scheduler control itself, I assume Telerik already has this pattern nice, pretty, and tested. If so, would you mind sharing it?
We have the requirement to color code appointments (recurring and not) according to whether a particular file has been received that has been associated with that appointment. This is extending beyond the functionality a bit, so we need to pretty much duplicate the recurrence handling in order to associate an appointment with a file received via datetime.
DTSTART:(?<StartDate>\d{8}).* DTEND:(?<EndDate>\d{8}).* FREQ=(?<Frequency>[A-Z]{0,10});INTERVAL=(?<Interval>\d{1,3});BYDAY=(?<ByDay>[A-Z]{1,3})
Because this is actually handled inside the scheduler control itself, I assume Telerik already has this pattern nice, pretty, and tested. If so, would you mind sharing it?
We have the requirement to color code appointments (recurring and not) according to whether a particular file has been received that has been associated with that appointment. This is extending beyond the functionality a bit, so we need to pretty much duplicate the recurrence handling in order to associate an appointment with a file received via datetime.
7 Answers, 1 is accepted
0
Accepted
Hi Brian,
Yes, you can parse the recurrence rule using RadScheduler. The following resources show how to do this:
http://www.telerik.com/help/aspnet-ajax/schedule_serversideworkingwithrecurringappointments.html
http://www.telerik.com/support/kb/aspnet-ajax/scheduler/how-to-display-all-radscheduler-appointments-in-gridview.aspx
Let us know if you have further questions.
Greetings,
Peter
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Yes, you can parse the recurrence rule using RadScheduler. The following resources show how to do this:
http://www.telerik.com/help/aspnet-ajax/schedule_serversideworkingwithrecurringappointments.html
http://www.telerik.com/support/kb/aspnet-ajax/scheduler/how-to-display-all-radscheduler-appointments-in-gridview.aspx
Let us know if you have further questions.
Greetings,
Peter
the Telerik team
Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
0

Kevin Price
Top achievements
Rank 1
answered on 12 Apr 2010, 03:26 PM
Peter -
I have gained a similar requirement, and am showing a single appt on a page. Without having to load a scheduler, is there an acceptable way to parse the recurrencerule to show as simple text? Ex. Occurs every Monday until ....
Thanks,
Kevin
I have gained a similar requirement, and am showing a single appt on a page. Without having to load a scheduler, is there an acceptable way to parse the recurrencerule to show as simple text? Ex. Occurs every Monday until ....
Thanks,
Kevin
0
Hello Kevin,
We don't have such function ready, but you can use RecurrenceRule.TryParse to obtain the recurrence object and then format the user-friendly string based on the object type and properties.
I hope this helps.
Best wishes,
Tsvetomir Tsonev
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
We don't have such function ready, but you can use RecurrenceRule.TryParse to obtain the recurrence object and then format the user-friendly string based on the object type and properties.
I hope this helps.
Best wishes,
Tsvetomir Tsonev
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
0

Kevin Price
Top achievements
Rank 1
answered on 15 Sep 2010, 03:24 AM
Peter,
To avoid duplicating efforts (again :) ) I'll keep my posts on this thread. Please check the below code (RecRuleParser.cs).
It does a pretty good job of converting the RecurrenceRule values from the database to a plain-text English statement.
Ex:
DTSTART:20100526T040000Z DTEND:20100527T040000Z RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=WE EXDATE:20100526T040000Z,20100812T040000Z
Returns:
Occurs weekly every Wednesday starting on 5/26/2010 at 12:00 AM except on 5/26/2010 12:00:00 AM and 8/12/2010 12:00:00 AM (as it converts to local time) I included code as well to try and spell out the exceptions - source is quite easily modified and full of comments (and commentary)
DTSTART:20100622T160000Z DTEND:20100622T170000Z RRULE:FREQ=WEEKLY;COUNT=3;INTERVAL=1;BYDAY=TU EXDATE:20100622T160000Z,20100706T160000Z
Returns:
Occurs weekly every Tuesday starting on 6/22/2010 at 12:00 PM for the next 3 weeks ending on 7/13/2010 at 1:00 PM except on 6/22/2010 12:00:00 PM and 7/6/2010 12:00:00 PM
usage: myOutputString = RecRuleParser.ParseRule(string <RecurrenceRuleText>, bool <showExceptions>);
With a little work, and a resource file, probably wouldn't be too hard to support additional language. Hope this helps. It may not
Thanks,
Kevin
To avoid duplicating efforts (again :) ) I'll keep my posts on this thread. Please check the below code (RecRuleParser.cs).
It does a pretty good job of converting the RecurrenceRule values from the database to a plain-text English statement.
Ex:
DTSTART:20100526T040000Z DTEND:20100527T040000Z RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=WE EXDATE:20100526T040000Z,20100812T040000Z
Returns:
Occurs weekly every Wednesday starting on 5/26/2010 at 12:00 AM except on 5/26/2010 12:00:00 AM and 8/12/2010 12:00:00 AM (as it converts to local time) I included code as well to try and spell out the exceptions - source is quite easily modified and full of comments (and commentary)
DTSTART:20100622T160000Z DTEND:20100622T170000Z RRULE:FREQ=WEEKLY;COUNT=3;INTERVAL=1;BYDAY=TU EXDATE:20100622T160000Z,20100706T160000Z
Returns:
Occurs weekly every Tuesday starting on 6/22/2010 at 12:00 PM for the next 3 weeks ending on 7/13/2010 at 1:00 PM except on 6/22/2010 12:00:00 PM and 7/6/2010 12:00:00 PM
usage: myOutputString = RecRuleParser.ParseRule(string <RecurrenceRuleText>, bool <showExceptions>);
With a little work, and a resource file, probably wouldn't be too hard to support additional language. Hope this helps. It may not
Thanks,
Kevin
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Globalization;
//You might want to change this
namespace
RRuleParser
{
public
static
class
RecRuleParser
{
public
static
string
ParseRRule(
string
rRule,
bool
showExceptions)
{
string
parsed =
string
.Empty;
//set up the return string
StringBuilder englishStatement =
new
StringBuilder();
//Break it into basic parts
string
[] elements = rRule.Split(
' '
);
//it's double spaced in the db, so deal with it accordingly
string
startDate = elements[0];
string
endDate = elements[2];
string
recRule = elements[4];
string
recExcs =
string
.Empty;
//check for exceptions
if
(elements.Length > 5)
{
recExcs = elements[6];
}
//Attempt to parse the zulu dates into something else
DateTime dtStart = DateTime.ParseExact(getElemValue(startDate),
"yyyyMMddTHHmmssZ"
, System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
DateTime dtEnd = DateTime.ParseExact(getElemValue(endDate),
"yyyyMMddTHHmmssZ"
, System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
TimeSpan tsEnd = dtEnd.Subtract(dtStart);
//Now work with the recurrence rule
Dictionary<
string
,
string
> rruleElems =
new
Dictionary<
string
,
string
>();
//Convert the string to a dictionary so we can find things easy
parsed = getElemValue(recRule);
//no need having unnecessarily declared strings
elements = parsed.Split(
';'
);
for
(
int
i = 0; i < elements.Length; i++)
{
string
[] tmp = elements[i].Split(
'='
);
rruleElems.Add(tmp[0], tmp[1]);
}
englishStatement.Append(
"Occurs "
+ rruleElems[
"FREQ"
].ToLower());
string
calType =
string
.Empty;
//need a scratchpad
//start translating into English
int
timeToAdd = 0;
try
{
timeToAdd = Convert.ToInt32(rruleElems[
"COUNT"
]);
}
catch
{
timeToAdd = 0;
}
switch
(rruleElems[
"FREQ"
].ToLower())
{
case
"daily"
:
string
[] days = rruleElems[
"BYDAY"
].Split(
','
);
englishStatement.Append(parseDayNames(days));
dtEnd = dtEnd.AddDays(timeToAdd);
calType =
"days"
;
break
;
case
"weekly"
:
calType =
"weeks"
;
dtEnd = dtEnd.AddDays(timeToAdd * 7);
try
{
days = rruleElems[
"BYDAY"
].Split(
','
);
englishStatement.Append(parseDayNames(days));
}
catch
{
//just in case we missed something on this one
throw
new
Exception(
"Error while processing Recurrence Rule"
);
}
break
;
case
"monthly"
:
calType =
"months"
;
dtEnd = dtEnd.AddMonths(timeToAdd);
//see if it's positional
try
{
string
bsp = getDayEnding(rruleElems[
"BYSETPOS"
]);
englishStatement.Append(
" on the "
+ bsp +
" "
+ parseDayNames(rruleElems[
"BYDAY"
].Split(
','
)).Replace(
" every "
,
""
));
}
catch
{
//Ok, no BYSETPOS, let's go for BYMONTHDAY
string
bsp = getDayEnding(rruleElems[
"BYMONTHDAY"
]);
englishStatement.Append(
" on the "
+ bsp +
" day of each month"
);
}
break
;
case
"yearly"
:
calType =
"years"
;
dtEnd = dtEnd.AddYears(timeToAdd);
//looks a lot like monthly....
string
mName = CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(Convert.ToInt32(rruleElems[
"BYMONTH"
]));
//see if it's positional
try
{
string
bsp = getDayEnding(rruleElems[
"BYSETPOS"
]);
englishStatement.Append(
" on the "
+ bsp +
" "
+ parseDayNames(rruleElems[
"BYDAY"
].Split(
','
)).Replace(
" every "
,
""
) +
" of "
+ mName);
}
catch
{
//Ok, no BYSETPOS, let's go for BYMONTHDAY
string
bsp = getDayEnding(rruleElems[
"BYMONTHDAY"
]);
englishStatement.Append(
" on the "
+ bsp +
" day of "
+ mName);
}
break
;
case
"hourly"
:
calType =
"hours"
;
dtEnd = dtEnd.AddHours(timeToAdd);
break
;
default
:
break
;
}
englishStatement.Append(
" starting on "
+ dtStart.ToLocalTime().ToShortDateString() +
" at "
+ dtStart.ToLocalTime().ToShortTimeString());
if
(timeToAdd > 0)
{
englishStatement.Append(
" for the next "
+ rruleElems[
"COUNT"
] +
" "
+ calType);
englishStatement.Append(
" ending on "
+ dtEnd.ToLocalTime().ToShortDateString() +
" at "
+ dtStart.AddHours(tsEnd.Hours).ToLocalTime().ToShortTimeString());
}
if
(recExcs.Length > 0 && showExceptions)
{
string
[] excs = recExcs.Split(
':'
)[1].Split(
','
);
string
retString =
string
.Empty;
englishStatement.Append(
" except on "
);
for
(
int
r = 0; r < excs.Length; r++)
{
//we'll use dtEnd, it's not doing anything now
dtEnd = DateTime.ParseExact(excs[r],
"yyyyMMddTHHmmssZ"
, System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal).ToLocalTime();
if
(r < excs.Length && excs.Length > 2)
{
retString += dtEnd +
","
;
}
else
{
if
(r < excs.Length - 1 && excs.Length == 2)
{
retString += dtEnd +
" and "
;
}
else
{
retString += dtEnd;
}
}
}
englishStatement.Append(retString);
}
return
englishStatement.ToString();
}
private
static
string
getElemValue(
string
elem)
{
//just easier than writing split all over the place
string
[] elems = elem.Split(
':'
);
return
elems[1].Trim();
}
private
static
string
getDayName(
string
day)
{
//pretty self explanatory
switch
(day)
{
case
"MO"
:
return
"Monday"
;
case
"TU"
:
return
"Tuesday"
;
case
"WE"
:
return
"Wednesday"
;
case
"TH"
:
return
"Thursday"
;
case
"FR"
:
return
"Friday"
;
case
"SA"
:
return
"Saturday"
;
case
"SU"
:
return
"Sunday"
;
default
:
return
""
;
}
}
private
static
string
parseDayNames(
string
[] days)
{
string
retString =
string
.Empty;
{
if
(days.Length < 7)
{
retString +=
" every"
;
for
(
int
d = 0; d < days.Length; d++)
{
days[d] = getDayName(days[d]);
if
(d == days.Length - 1 && days.Length > 1)
{
days[d] =
" and "
+ days[d];
}
else
{
if
(days.Length > 2)
{
days[d] +=
","
;
}
}
retString +=
" "
+ days[d];
}
}
return
retString;
}
}
private
static
string
getDayEnding(
string
d)
{
//tried to avoid a big ugly if statement
//handle the events on the "n"th day of the month
if
(d.EndsWith(
"1"
) && d !=
"11"
)
{
d +=
"st"
;
}
if
(d.EndsWith(
"2"
) && d !=
"12"
)
{
d +=
"nd"
;
}
if
(d.EndsWith(
"3"
) && d !=
"13"
)
{
d +=
"rd"
;
}
if
(d.Length < 3)
//hasn't been appended yet
{
d +=
"th"
;
}
return
d;
}
}
}
0
Hi Kevin,
Thank you for posting the code here. I'm sure someone will find it helpful.
As a token of gratitude for your involvement your Telerik points have been updated.
Best wishes,
Tsvetomir Tsonev
the Telerik team
Thank you for posting the code here. I'm sure someone will find it helpful.
As a token of gratitude for your involvement your Telerik points have been updated.
Best wishes,
Tsvetomir Tsonev
the Telerik team
Do you want to have your say when we set our development plans?
Do you want to know when a feature you care about is added or when a bug fixed?
Explore the
Telerik Public Issue Tracking
system and vote to affect the priority of the items
0

Gustavo
Top achievements
Rank 1
answered on 05 Feb 2013, 07:37 PM
Hello,
I'm new using asp.net and i want to know how I can implement this code into the my web apps. right now, I'm using RadScheduler for one of my applications and I have a small problem is that each follows: My application is a work order system which uses a calendar to place recurring orders, these orders are shipped one day before processing in order that they can be addressed. however I am trying to do that every time you mount a recurring type this command is saved in the database independently ie. If an order is placed to run for example every Friday for a month, I need to know how I can send a work order for each Friday of the month that was scheduled.
Thanks you
Gustavo
I'm new using asp.net and i want to know how I can implement this code into the my web apps. right now, I'm using RadScheduler for one of my applications and I have a small problem is that each follows: My application is a work order system which uses a calendar to place recurring orders, these orders are shipped one day before processing in order that they can be addressed. however I am trying to do that every time you mount a recurring type this command is saved in the database independently ie. If an order is placed to run for example every Friday for a month, I need to know how I can send a work order for each Friday of the month that was scheduled.
Thanks you
Gustavo
0
Hello Gustavo,
I would recommend using the the RadScheduler AppointmentInsert server-side event to parse the current appointment recurrence rule. This way you could extract the information that would be helpful in order to calculate all appointment occurrences in the future and execute your custom logic to send those orders.
Here you may find more information about AppointmentInsert server-side event.
Regards,
Boyan Dimitrov
the Telerik team
I would recommend using the the RadScheduler AppointmentInsert server-side event to parse the current appointment recurrence rule. This way you could extract the information that would be helpful in order to calculate all appointment occurrences in the future and execute your custom logic to send those orders.
Here you may find more information about AppointmentInsert server-side event.
Regards,
Boyan Dimitrov
the Telerik team
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to their blog feed now.