-
-
Notifications
You must be signed in to change notification settings - Fork 516
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RuleSet and rrulestr doesn't work as intended #332
Comments
I've encountered something similar too, and I think it's the Z at the ISO date end. Weird |
From what I can tell, it's a bug in @davidgoli If you're interested I can open a new PR for this once my current one is merged |
Until this gets fixed I implemented an alternative to rrulestr that should handle DTSTART as expected: import { RRule, RRuleSet, rrulestr } from 'rrule';
/**
* Parse a rrule string as a RRuleSet.
*
* This also fixes a bug in {@link rrulestr} where the dtstart of the rrules following the first one are lost.
* {@link https://github.com/jakubroztocil/rrule/issues/332}
*
* Does not support EXRULE, RDATE, or EXDATE
*
* @throws Error if the rrule cannot be parsed into a rruleset.
* @param {string} rruleStr
* @returns {RRuleSet}
*/
export function parseRRuleSet(rruleStr: string): RRuleSet {
const set = new RRuleSet();
rruleStr = rruleStr.trim();
let dtStart = '';
for (let line of rruleStr.split('\n')) {
line = line.trim();
const { name, value, parms } = breakDownLine(line);
if (name !== 'RRULE' && dtStart) {
throw new Error('Incorrectly placed DTSTART found. Must be placed one line before RRULE');
}
switch (name) {
case 'RDATE': {
const dates = parseRDate(value, parms);
for (const date of dates) {
set.rdate(date);
}
break;
}
case 'DTSTART':
dtStart = line;
continue;
case 'RRULE': {
const rrule = parseRrule(`${dtStart}\n${line}`);
set.rrule(rrule);
dtStart = '';
break;
}
default:
throw new Error('parseRRuleSet only supports DTSTART, RDATE & RRULE for now');
}
}
return set;
}
export function parseRrule(rruleStr: string): RRule {
const rrule = rrulestr(rruleStr);
if (!(rrule instanceof RRule)) {
throw new Error('Cannot parse input as RRule. Is it an RRuleSet?');
}
return rrule;
}
function parseRDate(rdateval, parms): Date[] {
validateDateParm(parms);
return rdateval
.split(',')
.map(datestr => {
return parseRRuleDate(datestr);
});
}
function parseRRuleDate(until: string): Date {
const re = /^(\d{4})(\d{2})(\d{2})(T(\d{2})(\d{2})(\d{2})Z?)?$/;
const bits = re.exec(until);
if (!bits) {
throw new Error(`Invalid RRule Date value: ${until}`);
}
const parseInt = Number.parseInt;
return new Date(Date.UTC(
parseInt(bits[1], 10),
parseInt(bits[2], 10) - 1,
parseInt(bits[3], 10),
parseInt(bits[5], 10) || 0,
parseInt(bits[6], 10) || 0,
parseInt(bits[7], 10) || 0,
));
}
function validateDateParm(parms) {
parms.forEach(parm => {
if (!/(VALUE=DATE(-TIME)?)|(TZID=)/.test(parm)) {
throw new Error(`unsupported RDATE/EXDATE parm: ${parm}`);
}
});
}
function breakDownLine(line) {
const { name, value } = extractName(line);
const parms = name.split(';');
if (!parms) {
throw new Error('empty property name');
}
return {
name: parms[0].toUpperCase(),
parms: parms.slice(1),
value,
};
}
function extractName(line) {
if (line.indexOf(':') === -1) {
return {
name: 'RRULE',
value: line,
};
}
const [name, value] = pythonSplit(line, ':', 1);
return {
name,
value,
};
}
function pythonSplit(str: string, sep: string, splitCount?: number) {
const splits = str.split(sep);
return splitCount
? splits.slice(0, splitCount).concat([splits.slice(splitCount).join(sep)])
: splits;
} |
Thank you so mutch this works for me. |
Reporting an issue
Thank you for taking an interest in
rrule
! Please include the following inyour report:
creating a new one
are using such as the exact RRule string and dates.
rrule
you are using$ date
from the command lineof the machine showing the bug)
rrule version : ^2.6.0
on MacOS
date: Lun 18 mar 2019 16:47:35 CET
Hi,
I'm trying to create a
rruleset
from a string passed in the DB, and I have a different behavior when using tworruleset.rrule
or just one.I'm not really clear, so here is the code sample :
And here is the
console.log
associated, with the difference of the toString() of the two methods highlighted with a + and - :Obviously, the second result acts weirdly. I don't know if it's a bug, but it feels like one.
The text was updated successfully, but these errors were encountered: