@heinlein-video/rrule
Version:
rrule fork. Includes the src/ folder for typescript sourceMaps
108 lines (90 loc) • 2.97 kB
text/typescript
import { Options } from './types'
import { RRule, DEFAULT_OPTIONS } from './rrule'
import { includes, isPresent, isArray, isNumber, toArray } from './helpers'
import { Weekday } from './weekday'
import { timeToUntilString } from './dateutil'
import { DateWithZone } from './datewithzone'
export function optionsToString(options: Partial<Options>) {
const rrule: string[][] = []
let dtstart = ''
const keys: (keyof Options)[] = Object.keys(options) as (keyof Options)[]
const defaultKeys = Object.keys(DEFAULT_OPTIONS)
for (let i = 0; i < keys.length; i++) {
if (keys[i] === 'tzid') continue
if (!includes(defaultKeys, keys[i])) continue
let key = keys[i].toUpperCase()
const value = options[keys[i]]
let outValue = ''
if (!isPresent(value) || (isArray(value) && !value.length)) continue
switch (key) {
case 'FREQ':
outValue = RRule.FREQUENCIES[options.freq]
break
case 'WKST':
if (isNumber(value)) {
outValue = new Weekday(value).toString()
} else {
outValue = value.toString()
}
break
case 'BYWEEKDAY':
/*
NOTE: BYWEEKDAY is a special case.
RRule() deconstructs the rule.options.byweekday array
into an array of Weekday arguments.
On the other hand, rule.origOptions is an array of Weekdays.
We need to handle both cases here.
It might be worth change RRule to keep the Weekdays.
Also, BYWEEKDAY (used by RRule) vs. BYDAY (RFC)
*/
key = 'BYDAY'
outValue = toArray<Weekday | number[] | number>(
value as Weekday | number[] | number
)
.map((wday) => {
if (wday instanceof Weekday) {
return wday
}
if (isArray(wday)) {
return new Weekday(wday[0], wday[1])
}
return new Weekday(wday)
})
.toString()
break
case 'DTSTART':
dtstart = buildDtstart(value as number, options.tzid)
break
case 'UNTIL':
outValue = timeToUntilString(value as number, !options.tzid)
break
default:
if (isArray(value)) {
const strValues: string[] = []
for (let j = 0; j < value.length; j++) {
strValues[j] = String(value[j])
}
outValue = strValues.toString()
} else {
outValue = String(value)
}
}
if (outValue) {
rrule.push([key, outValue])
}
}
const rules = rrule
.map(([key, value]) => `${key}=${value.toString()}`)
.join(';')
let ruleString = ''
if (rules !== '') {
ruleString = `RRULE:${rules}`
}
return [dtstart, ruleString].filter((x) => !!x).join('\n')
}
function buildDtstart(dtstart?: number, tzid?: string | null) {
if (!dtstart) {
return ''
}
return 'DTSTART' + new DateWithZone(new Date(dtstart), tzid).toString()
}