Skip to content
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

Add support for dtend and floating dates #1

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Prev Previous commit
Remove floating flag, use absense of timezone instead
simonratner committed Sep 25, 2020
commit 78b7d01de003474dfd76efae8e31a074e8aa1196
5 changes: 2 additions & 3 deletions src/optionstostring.ts
Original file line number Diff line number Diff line change
@@ -68,7 +68,6 @@ export function optionsToString (options: Partial<Options>) {
break

case 'DTVALUE':
case 'DTFLOATING':
break

case 'UNTIL':
@@ -87,7 +86,7 @@ export function optionsToString (options: Partial<Options>) {
if (options.dtvalue === DateTimeValue.DATE) {
outValue = dateutil.toRfc5545Date(value)
} else {
outValue = dateutil.toRfc5545DateTime(value, !options.dtfloating)
outValue = dateutil.toRfc5545DateTime(value, !!options.tzid)
}
break

@@ -125,7 +124,7 @@ function formatDateTime (dt?: number, options: Partial<Options> = {}, prop = Dat
if (options.dtvalue) {
prefix += ';VALUE=' + options.dtvalue.toString()
}
if (options.dtfloating) {
if (!options.tzid) {
if (options.dtvalue === DateTimeValue.DATE) {
return prefix + ':' + dateutil.toRfc5545Date(dt)
} else {
20 changes: 5 additions & 15 deletions src/parsestring.ts
Original file line number Diff line number Diff line change
@@ -41,9 +41,6 @@ export function parseString (rfcString: string): Partial<Options> {
} else if (existing && acc.tzid !== cur.tzid) {
// Different timezones.
throw new Error('Invalid rule: DTSTART and DTEND must have the same timezone')
} else if (existing && acc.dtfloating !== cur.dtfloating) {
// Different floating types.
throw new Error('Invalid rule: DTSTART and DTEND must both be floating')
}
return Object.assign(acc, cur)
}, {}) || {}
@@ -78,7 +75,6 @@ export function parseDateTime (line: string, prop = DateTimeProperty.START): Par
options.dtend = dateutil.fromRfc5545Date(dt)
}
options.dtvalue = DateTimeValue.DATE
options.dtfloating = true
if (options.tzid) {
throw new Error(`Invalid date value with timezone: ${line}`)
}
@@ -91,9 +87,6 @@ export function parseDateTime (line: string, prop = DateTimeProperty.START): Par
if (dtvalue) {
options.dtvalue = DateTimeValue.DATE_TIME
}
if (!tzid && !dt.endsWith('Z')) {
options.dtfloating = true
}
}

return options
@@ -159,14 +152,11 @@ function parseRrule (line: string) {
case 'DTSTART':
case 'TZID':
// for backwards compatibility
const dtstart = parseDateTime(line)
options.tzid = dtstart.tzid
options.dtstart = dtstart.dtstart
if (dtstart.dtvalue) {
options.dtvalue = dtstart.dtvalue
}
if (dtstart.dtfloating) {
options.dtfloating = dtstart.dtfloating
const parsed = parseDateTime(line)
options.tzid = parsed.tzid
options.dtstart = parsed.dtstart
if (parsed.dtvalue) {
options.dtvalue = parsed.dtvalue
}
break
case 'UNTIL':
1 change: 0 additions & 1 deletion src/rrule.ts
Original file line number Diff line number Diff line change
@@ -45,7 +45,6 @@ export const DEFAULT_OPTIONS: Options = {
dtstart: null,
dtend: null,
dtvalue: DateTimeValue.DATE_TIME,
dtfloating: false,
interval: 1,
wkst: Days.MO,
count: null,
4 changes: 2 additions & 2 deletions src/rruleset.ts
Original file line number Diff line number Diff line change
@@ -142,10 +142,10 @@ export default class RRuleSet extends RRule {
let result: string[] = []

if (!this._rrule.length && this._dtstart) {
result = result.concat(optionsToString({ dtstart: this._dtstart }))
result = result.concat(optionsToString({ dtstart: this._dtstart, tzid: this._tzid }))
}
if (!this._rrule.length && this._dtend) {
result = result.concat(optionsToString({ dtend: this._dtend }))
result = result.concat(optionsToString({ dtend: this._dtend, tzid: this._tzid }))
}

this._rrule.forEach(function (rrule) {
17 changes: 4 additions & 13 deletions src/rrulestr.ts
Original file line number Diff line number Diff line change
@@ -9,7 +9,6 @@ export interface RRuleStrOptions {
dtstart: Date | null
dtend: Date | null
dtvalue: DateTimeValue | null
dtfloating: boolean | null
cache: boolean
unfold: boolean
forceset: boolean
@@ -25,7 +24,6 @@ const DEFAULT_OPTIONS: RRuleStrOptions = {
dtstart: null,
dtend: null,
dtvalue: null,
dtfloating: false,
cache: false,
unfold: false,
forceset: false,
@@ -39,7 +37,7 @@ export function parseInput (s: string, options: Partial<RRuleStrOptions>) {
let exrulevals: Partial<Options>[] = []
let exdatevals: Date[] = []

let { dtstart, dtfloating, dtvalue, tzid } = parseDateTime(s)
let { dtstart, dtvalue, tzid } = parseDateTime(s)
let dtend: Date | null = null

const lines = splitIntoLines(s, options.unfold)
@@ -95,9 +93,6 @@ export function parseInput (s: string, options: Partial<RRuleStrOptions>) {
} else if (dtstart && tzid !== parsed.tzid) {
// Different timezones.
throw new Error('Invalid rule: DTSTART and DTEND must have the same timezone')
} else if (dtstart && dtfloating !== parsed.dtfloating) {
// Different floating types.
throw new Error('Invalid rule: DTSTART and DTEND must both be floating')
}
dtend = parsed.dtend
}
@@ -112,7 +107,6 @@ export function parseInput (s: string, options: Partial<RRuleStrOptions>) {
dtstart,
dtend,
dtvalue,
dtfloating,
tzid,
rrulevals,
rdatevals,
@@ -130,7 +124,6 @@ function buildRule (s: string, options: Partial<RRuleStrOptions>) {
dtstart,
dtend,
dtvalue,
dtfloating,
tzid
} = parseInput(s, options)

@@ -157,7 +150,7 @@ function buildRule (s: string, options: Partial<RRuleStrOptions>) {
rrulevals.forEach(val => {
rset.rrule(
new RRule(
groomRruleOptions(val, dtstart, dtend, dtvalue, dtfloating, tzid),
groomRruleOptions(val, dtstart, dtend, dtvalue, tzid),
noCache
)
)
@@ -170,7 +163,7 @@ function buildRule (s: string, options: Partial<RRuleStrOptions>) {
exrulevals.forEach(val => {
rset.exrule(
new RRule(
groomRruleOptions(val, dtstart, dtend, dtvalue, dtfloating, tzid),
groomRruleOptions(val, dtstart, dtend, dtvalue, tzid),
noCache
)
)
@@ -190,7 +183,6 @@ function buildRule (s: string, options: Partial<RRuleStrOptions>) {
val.dtstart || options.dtstart || dtstart,
val.dtend || options.dtend || dtend,
val.dtvalue || options.dtvalue || dtvalue,
val.dtfloating || options.dtfloating || dtfloating,
val.tzid || options.tzid || tzid
), noCache)
}
@@ -202,13 +194,12 @@ export function rrulestr (
return buildRule(s, initializeOptions(options))
}

function groomRruleOptions (val: Partial<Options>, dtstart?: Date | null, dtend?: Date | null, dtvalue?: DateTimeValue | null, dtfloating?: boolean | null, tzid?: string | null) {
function groomRruleOptions (val: Partial<Options>, dtstart?: Date | null, dtend?: Date | null, dtvalue?: DateTimeValue | null, tzid?: string | null) {
return {
...val,
dtstart,
dtend,
dtvalue,
dtfloating,
tzid
}
}
1 change: 0 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
@@ -39,7 +39,6 @@ export interface Options {
dtstart: Date | null
dtend: Date | null
dtvalue: DateTimeValue | null
dtfloating: boolean | null
interval: number
wkst: Weekday | number | null
count: number | null
11 changes: 9 additions & 2 deletions test/optionstostring.test.ts
Original file line number Diff line number Diff line change
@@ -6,10 +6,17 @@ import { expect } from "chai";
describe('optionsToString', () => {
it('serializes valid single lines of rrules', function () {
const expectations: ([ Partial<Options>, string ][]) = [
[{ freq: RRule.WEEKLY, until: new Date(Date.UTC(2010, 0, 1, 0, 0, 0)) }, 'RRULE:FREQ=WEEKLY;UNTIL=20100101T000000Z' ],
[{ freq: RRule.WEEKLY, until: new Date(Date.UTC(2010, 0, 1, 0, 0, 0)) }, 'RRULE:FREQ=WEEKLY;UNTIL=20100101T000000' ],
[{ freq: RRule.WEEKLY, until: new Date(Date.UTC(2010, 0, 1, 0, 0, 0)), tzid: 'UTC' }, 'RRULE:FREQ=WEEKLY;UNTIL=20100101T000000Z' ],
[{ dtstart: new Date(Date.UTC(1997, 8, 2, 9, 0, 0)) }, 'DTSTART:19970902T090000' ],
[{ dtstart: new Date(Date.UTC(1997, 8, 2, 9, 0, 0)), tzid: 'America/New_York' }, 'DTSTART;TZID=America/New_York:19970902T090000' ],
[
{ dtstart: new Date(Date.UTC(1997, 8, 2, 9, 0, 0)), freq: RRule.WEEKLY },
'DTSTART:19970902T090000\n' +
'RRULE:FREQ=WEEKLY'
],
[
{ dtstart: new Date(Date.UTC(1997, 8, 2, 9, 0, 0)), tzid: 'UTC', freq: RRule.WEEKLY },
'DTSTART:19970902T090000Z\n' +
'RRULE:FREQ=WEEKLY'
],
@@ -19,7 +26,7 @@ describe('optionsToString', () => {
'RRULE:FREQ=WEEKLY'
],
[
{ dtstart: new Date(Date.UTC(1997, 8, 2, 9, 0, 0)), dtend: new Date(Date.UTC(1997, 8, 3, 9, 0, 0)), freq: RRule.WEEKLY },
{ dtstart: new Date(Date.UTC(1997, 8, 2, 9, 0, 0)), dtend: new Date(Date.UTC(1997, 8, 3, 9, 0, 0)), tzid: 'UTC', freq: RRule.WEEKLY },
'DTSTART:19970902T090000Z\n' +
'DTEND:19970903T090000Z\n' +
'RRULE:FREQ=WEEKLY'
3 changes: 2 additions & 1 deletion test/rrule.test.ts
Original file line number Diff line number Diff line change
@@ -3505,6 +3505,7 @@ describe('RRule', function () {
[6, RRule.SU].forEach(function (wkst) {
const rr = new RRule({
dtstart: new Date(Date.UTC(2017, 9, 17, 0, 30, 0, 0)),
tzid: 'UTC',
until: new Date(Date.UTC(2017, 11, 22, 1, 30, 0, 0)),
freq: RRule.MONTHLY,
interval: 1,
@@ -3643,7 +3644,7 @@ describe('RRule', function () {
const ruleString = rrule.toString()
const rrule2 = RRule.fromString(ruleString)

expect(ruleString).to.equal('DTSTART:09900101T000000Z\nRRULE:COUNT=1')
expect(ruleString).to.equal('DTSTART:09900101T000000\nRRULE:COUNT=1')
expect(rrule2.count()).to.equal(1)
expect(rrule2.all()).to.deep.equal([
new Date(Date.UTC(990, 0, 1, 0, 0, 0))
6 changes: 4 additions & 2 deletions test/rruleset.test.ts
Original file line number Diff line number Diff line change
@@ -366,7 +366,8 @@ describe('RRuleSet', function () {
set.rrule(new RRule({
freq: RRule.YEARLY,
count: 2,
dtstart: parse('19600101T090000')
dtstart: parse('19600101T090000'),
tzid: 'UTC'
}))

expect(set.valueOf()).to.deep.equal([
@@ -381,7 +382,8 @@ describe('RRuleSet', function () {
set.rrule(new RRule({
freq: RRule.YEARLY,
count: 2,
dtstart: parse('19600101T090000')
dtstart: parse('19600101T090000'),
tzid: 'UTC'
}))

set.rrule(new RRule({