Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

README.md 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827
  1. rrule.js
  2. ========
  3. **Library for working with recurrence rules for calendar dates.**
  4. [![NPM version][npm-image]][npm-url]
  5. [![Build Status][ci-image]][ci-url]
  6. [![js-standard-style][js-standard-image]][js-standard-url]
  7. [![Downloads][downloads-image]][downloads-url]
  8. [![Gitter][gitter-image]][gitter-url]
  9. [![codecov.io](http://codecov.io/github/jakubroztocil/rrule/coverage.svg?branch=master)](http://codecov.io/github/jakubroztocil/rrule?branch=master)
  10. rrule.js supports recurrence rules as defined in the [iCalendar
  11. RFC](https://tools.ietf.org/html/rfc5545), with a few important
  12. [differences](#differences-from-icalendar-rfc). It is a partial port of the
  13. `rrule` module from the excellent
  14. [python-dateutil](http://labix.org/python-dateutil/) library. On top of
  15. that, it supports parsing and serialization of recurrence rules from and
  16. to natural language.
  17. * * * * *
  18. ### Quick Start
  19. - [Demo app](http://jakubroztocil.github.io/rrule/)
  20. #### Client Side
  21. ```bash
  22. $ yarn add rrule
  23. ```
  24. Alternatively, download manually:
  25. * [rrule.min.js](https://jakubroztocil.github.io/rrule/dist/es5/rrule.min.js) (bundled, minified)
  26. * [rrule.js](https://jakubroztocil.github.io/rrule/dist/es5/rrule.js) (bundled, not minified)
  27. * [rrule-tz.min.js](https://jakubroztocil.github.io/rrule/dist/es5/rrule-tz.min.js) (with timezone support, bundled, minified)
  28. * [rrule-tz.js](https://jakubroztocil.github.io/rrule/dist/es5/rrule-tz.js) (with timezone support, bundled, not minified)
  29. ```html
  30. <script src="rrule/dist/es5/rrule.min.js"></script>
  31. ```
  32. #### Server Side
  33. Includes optional TypeScript types
  34. ```bash
  35. $ yarn add rrule
  36. # or
  37. $ npm install rrule
  38. ```
  39. #### Usage
  40. **RRule:**
  41. ```es6
  42. import { RRule, RRuleSet, rrulestr } from 'rrule'
  43. // Create a rule:
  44. const rule = new RRule({
  45. freq: RRule.WEEKLY,
  46. interval: 5,
  47. byweekday: [RRule.MO, RRule.FR],
  48. dtstart: new Date(Date.UTC(2012, 1, 1, 10, 30)),
  49. until: new Date(Date.UTC(2012, 12, 31))
  50. })
  51. // Get all occurrence dates (Date instances):
  52. rule.all()
  53. [ '2012-02-03T10:30:00.000Z',
  54. '2012-03-05T10:30:00.000Z',
  55. '2012-03-09T10:30:00.000Z',
  56. '2012-04-09T10:30:00.000Z',
  57. '2012-04-13T10:30:00.000Z',
  58. '2012-05-14T10:30:00.000Z',
  59. '2012-05-18T10:30:00.000Z',
  60. /* … */]
  61. // Get a slice:
  62. rule.between(new Date(Date.UTC(2012, 7, 1)), new Date(Date.UTC(2012, 8, 1)))
  63. ['2012-08-27T10:30:00.000Z',
  64. '2012-08-31T10:30:00.000Z']
  65. // Get an iCalendar RRULE string representation:
  66. // The output can be used with RRule.fromString().
  67. rule.toString()
  68. "DTSTART:20120201T093000Z\nRRULE:FREQ=WEEKLY;INTERVAL=5;UNTIL=20130130T230000Z;BYDAY=MO,FR"
  69. // Get a human-friendly text representation:
  70. // The output can be used with RRule.fromText().
  71. rule.toText()
  72. "every 5 weeks on Monday, Friday until January 31, 2013"
  73. ```
  74. **RRuleSet:**
  75. ```js
  76. const rruleSet = new RRuleSet()
  77. // Add a rrule to rruleSet
  78. rruleSet.rrule(new RRule({
  79. freq: RRule.MONTHLY,
  80. count: 5,
  81. dtstart: new Date(Date.UTC(2012, 1, 1, 10, 30))
  82. }))
  83. // Add a date to rruleSet
  84. rruleSet.rdate(new Date(Date.UTC(2012, 6, 1, 10, 30)))
  85. // Add another date to rruleSet
  86. rruleSet.rdate(new Date(Date.UTC(2012, 6, 2, 10, 30)))
  87. // Add a exclusion rrule to rruleSet
  88. rruleSet.exrule(new RRule({
  89. freq: RRule.MONTHLY,
  90. count: 2,
  91. dtstart: new Date(Date.UTC(2012, 2, 1, 10, 30))
  92. }))
  93. // Add a exclusion date to rruleSet
  94. rruleSet.exdate(new Date(Date.UTC(2012, 5, 1, 10, 30)))
  95. // Get all occurrence dates (Date instances):
  96. rruleSet.all()
  97. [ '2012-02-01T10:30:00.000Z',
  98. '2012-05-01T10:30:00.000Z',
  99. '2012-07-01T10:30:00.000Z',
  100. '2012-07-02T10:30:00.000Z' ]
  101. // Get a slice:
  102. rruleSet.between(new Date(Date.UTC(2012, 2, 1)), new Date(Date.UTC(2012, 6, 2)))
  103. [ '2012-05-01T10:30:00.000Z', '2012-07-01T10:30:00.000Z' ]
  104. // To string
  105. rruleSet.valueOf()
  106. ['DTSTART:20120201T023000Z',
  107. 'RRULE:FREQ=MONTHLY;COUNT=5',
  108. 'RDATE:20120701T023000Z,20120702T023000Z',
  109. 'EXRULE:FREQ=MONTHLY;COUNT=2',
  110. 'EXDATE:20120601T023000Z']
  111. // To string
  112. rruleSet.toString()
  113. '["DTSTART:20120201T023000Z","RRULE:FREQ=MONTHLY;COUNT=5","RDATE:20120701T023000Z,20120702T023000Z","EXRULE:FREQ=MONTHLY;COUNT=2","EXDATE:20120601T023000Z"]'
  114. ```
  115. **rrulestr:**
  116. ```js
  117. // Parse a RRule string, return a RRule object
  118. rrulestr('DTSTART:20120201T023000Z\nRRULE:FREQ=MONTHLY;COUNT=5')
  119. // Parse a RRule string, return a RRuleSet object
  120. rrulestr('DTSTART:20120201T023000Z\nRRULE:FREQ=MONTHLY;COUNT=5', {forceset: true})
  121. // Parse a RRuleSet string, return a RRuleSet object
  122. rrulestr('DTSTART:20120201T023000Z\nRRULE:FREQ=MONTHLY;COUNT=5\nRDATE:20120701T023000Z,20120702T023000Z\nEXRULE:FREQ=MONTHLY;COUNT=2\nEXDATE:20120601T023000Z')
  123. ```
  124. ### Important: Use UTC dates
  125. Dates in JavaScript are tricky. `RRule` tries to support as much flexibility as possible without adding any large required 3rd party dependencies, but that means we also have some special rules.
  126. By default, `RRule` deals in ["floating" times or UTC timezones](https://tools.ietf.org/html/rfc5545#section-3.2.19). If you want results in a specific timezone, `RRule` also provides [timezone support](#timezone-support). Either way, JavaScript's built-in "timezone" offset tends to just get in the way, so this library simply doesn't use it at all. All times are returned with zero offset, as though it didn't exist in JavaScript.
  127. **The bottom line is the returned "UTC" dates are always meant to be interpreted as dates in your local timezone. This may mean you have to do additional conversion to get the "correct" local time with offset applied.**
  128. For this reason, it is highly recommended to use timestamps in UTC eg. `new Date(Date.UTC(...))`. Returned dates will likewise be in UTC (except on Chrome, which always returns dates with a timezone offset).
  129. For example:
  130. ```ts
  131. // local machine zone is America/Los_Angeles
  132. const rule = RRule.fromString(
  133. "DTSTART;TZID=America/Denver:20181101T190000;\n"
  134. + "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,TH;INTERVAL=1;COUNT=3"
  135. )
  136. rule.all()
  137. [ 2018-11-01T18:00:00.000Z,
  138. 2018-11-05T18:00:00.000Z,
  139. 2018-11-07T18:00:00.000Z ]
  140. // Even though the given offset is `Z` (UTC), these are local times, not UTC times.
  141. // Each of these this is the correct local Pacific time of each recurrence in
  142. // America/Los_Angeles when it is 19:00 in America/Denver, including the DST shift.
  143. // You can get the local components by using the getUTC* methods eg:
  144. date.getUTCDate() // --> 1
  145. date.getUTCHours() // --> 18
  146. ```
  147. If you want to get the same times in true UTC, you may do so eg. using Luxon:
  148. ```ts
  149. rule.all().map(date =>
  150. DateTime.fromJSDate(date)
  151. .toUTC()
  152. .setZone('local', { keepLocalTime: true })
  153. .toJSDate()
  154. )
  155. [ 2018-11-02T01:00:00.000Z,
  156. 2018-11-06T02:00:00.000Z,
  157. 2018-11-08T02:00:00.000Z ]
  158. // These times are in true UTC; you can see the hours shift
  159. ```
  160. For more examples see
  161. [python-dateutil](http://labix.org/python-dateutil/) documentation.
  162. * * * * *
  163. ### Timezone Support
  164. Optionally, it also supports use of the `TZID` parameter in the
  165. [RFC](https://tools.ietf.org/html/rfc5545#section-3.2.19)
  166. when the [Luxon](https://github.com/moment/luxon) library is provided. The
  167. [specification](https://moment.github.io/luxon/docs/manual/zones.html#specifying-a-zone)
  168. and [support matrix](https://moment.github.io/luxon/docs/manual/matrix.html) for Luxon apply.
  169. Example with `TZID`:
  170. ```js
  171. new RRule({
  172. dtstart: new Date(Date.UTC(2018, 1, 1, 10, 30)),
  173. count: 1,
  174. tzid: 'Asia/Tokyo'
  175. }).all()
  176. // assuming the system timezone is set to America/Los_Angeles, you get:
  177. [ '2018-01-31T17:30:00.000Z' ]
  178. // which is the time in Los Angeles when it's 2018-02-01T10:30:00 in Tokyo.
  179. ```
  180. Whether or not you use the `TZID` param, make sure to only use JS `Date` objects that are
  181. represented in UTC to avoid unexpected timezone offsets being applied, for example:
  182. ```js
  183. // WRONG: Will produce dates with TZ offsets added
  184. new RRule({
  185. freq: RRule.MONTHLY,
  186. dtstart: new Date(2018, 1, 1, 10, 30),
  187. until: new Date(2018, 2, 31)
  188. }).all()
  189. [ '2018-02-01T18:30:00.000Z', '2018-03-01T18:30:00.000Z' ]
  190. // RIGHT: Will produce dates with recurrences at the correct time
  191. new RRule({
  192. freq: RRule.MONTHLY,
  193. dtstart: new Date(Date.UTC(2018, 1, 1, 10, 30)),
  194. until: new Date(Date.UTC(2018, 2, 31))
  195. }).all()
  196. [ '2018-02-01T10:30:00.000Z', '2018-03-01T10:30:00.000Z' ]
  197. ```
  198. ### API
  199. #### `RRule` Constructor
  200. ```javascript
  201. new RRule(options[, noCache=false])
  202. ```
  203. The `options` argument mostly corresponds to the properties defined for `RRULE` in the
  204. iCalendar RFC. Only `freq` is required.
  205. <table>
  206. <!-- why, markdown... -->
  207. <thead>
  208. <tr>
  209. <th>Option</th>
  210. <th>Description</th>
  211. </tr>
  212. <thead>
  213. <tbody>
  214. <tr>
  215. <td><code>freq</code></td>
  216. <td>
  217. <p>(required) One of the following constants:</p>
  218. <ul>
  219. <li><code>RRule.YEARLY</code></li>
  220. <li><code>RRule.MONTHLY</code></li>
  221. <li><code>RRule.WEEKLY</code></li>
  222. <li><code>RRule.DAILY</code></li>
  223. <li><code>RRule.HOURLY</code></li>
  224. <li><code>RRule.MINUTELY</code></li>
  225. <li><code>RRule.SECONDLY</code></li>
  226. </ul>
  227. </td>
  228. </tr>
  229. <tr>
  230. <td><code>dtstart</code></td>
  231. <td>The recurrence start. Besides being the base for the
  232. recurrence, missing parameters in the final recurrence
  233. instances will also be extracted from this date. If not
  234. given, <code>new Date</code> will be used instead.
  235. **IMPORTANT:** See the discussion under <a href="#timezone-support">timezone support</a>
  236. </td>
  237. </tr>
  238. <tr>
  239. <td><code>interval</code></td>
  240. <td>The interval between each freq iteration. For example,
  241. when using <code>RRule.YEARLY</code>, an interval of <code>2</code> means
  242. once every
  243. two years, but with <code>RRule.HOURLY</code>, it means once every two
  244. hours.
  245. The default interval is <code>1</code>.
  246. </td>
  247. </tr>
  248. <tr>
  249. <td><code>wkst</code></td>
  250. <td>The week start day. Must be one of the <code>RRule.MO</code>,
  251. <code>RRule.TU</code>, <code>RRule.WE</code> constants, or an integer,
  252. specifying
  253. the first day of the week. This will affect recurrences based
  254. on weekly periods. The default week start is <code>RRule.MO</code>.
  255. </td>
  256. </tr>
  257. <tr>
  258. <td><code>count</code></td>
  259. <td>How many occurrences will be generated.</td>
  260. </tr>
  261. <tr>
  262. <td><code>until</code></td>
  263. <td>If given, this must be a <code>Date</code> instance, that will specify
  264. the limit of the recurrence. If a recurrence instance happens
  265. to be the same as the <code>Date</code> instance given in the
  266. <code>until</code>
  267. argument, this will be the last occurrence.
  268. </td>
  269. </tr>
  270. <tr>
  271. <td><code>tzid</code></td>
  272. <td>If given, this must be a string <a href="https://moment.github.io/luxon/docs/manual/zones.html#specifying-a-zone">supported</a>
  273. by Luxon, and the <a href="https://moment.github.io/luxon/">Luxon</a> library must be provided. See
  274. discussion under <a href="#timezone-support">Timezone support</a>.
  275. </td>
  276. </tr>
  277. <tr>
  278. <td><code>bysetpos</code></td>
  279. <td>If given, it must be either an integer, or an array of
  280. integers, positive or negative. Each given integer will specify
  281. an occurrence number, corresponding to the nth occurrence of
  282. the rule inside the frequency period. For example, a
  283. <code>bysetpos</code> of <code>-1</code> if combined with a <code>RRule.MONTHLY</code>
  284. frequency, and a byweekday of (<code>RRule.MO</code>, <code>RRule.TU</code>,
  285. <code>RRule.WE</code>, <code>RRule.TH</code>, <code>RRule.FR</code>), will result in
  286. the last
  287. work day of every month.
  288. </td>
  289. </tr>
  290. <tr>
  291. <td><code>bymonth</code></td>
  292. <td>If given, it must be either an integer, or an array of
  293. integers, meaning the months to apply the recurrence to.
  294. </td>
  295. </tr>
  296. <tr>
  297. <td><code>bymonthday</code></td>
  298. <td>If given, it must be either an integer, or an array of
  299. integers, meaning the month days to apply the recurrence to.
  300. </td>
  301. </tr>
  302. <tr>
  303. <td><code>byyearday</code></td>
  304. <td>If given, it must be either an integer, or an array of
  305. integers, meaning the year days to apply the recurrence to.
  306. </td>
  307. </tr>
  308. <tr>
  309. <td><code>byweekno</code></td>
  310. <td>If given, it must be either an integer, or an array of
  311. integers, meaning the week numbers to apply the recurrence to.
  312. Week numbers have the meaning described in ISO8601, that is,
  313. the first week of the year is that containing at least four
  314. days of the new year.
  315. </td>
  316. </tr>
  317. <tr>
  318. <td><code>byweekday</code></td>
  319. <td>If given, it must be either an integer (<code>0 == RRule.MO</code>), an
  320. array of integers, one of the weekday constants
  321. (<code>RRule.MO</code>,
  322. <code>RRule.TU</code>, etc), or an array of these constants. When
  323. given,
  324. these variables will define the weekdays where the recurrence
  325. will be applied. It's also possible to use an argument n for
  326. the weekday instances, which will mean the nth occurrence of
  327. this weekday in the period. For example, with
  328. <code>RRule.MONTHLY</code>,
  329. or with <code>RRule.YEARLY</code> and <code>BYMONTH</code>, using
  330. <code>RRule.FR.nth(+1)</code> or <code>RRule.FR.nth(-1)</code> in <code>byweekday</code>
  331. will specify the first or last friday of the month where the
  332. recurrence happens.
  333. Notice
  334. that the RFC documentation, this is specified as <code>BYDAY</code>,
  335. but was renamed to avoid the ambiguity of that argument.
  336. </td>
  337. </tr>
  338. <tr>
  339. <td><code>byhour</code></td>
  340. <td>If given, it must be either an integer, or an array of
  341. integers, meaning the hours to apply the recurrence to.
  342. </td>
  343. </tr>
  344. <tr>
  345. <td><code>byminute</code></td>
  346. <td>If given, it must be either an integer, or an array of
  347. integers, meaning the minutes to apply the recurrence to.
  348. </td>
  349. </tr>
  350. <tr>
  351. <td><code>bysecond</code></td>
  352. <td>If given, it must be either an integer, or an array of
  353. integers, meaning the seconds to apply the recurrence to.
  354. </td>
  355. </tr>
  356. <tr>
  357. <td><code>byeaster</code></td>
  358. <td>This is an extension to the RFC specification which the Python
  359. implementation provides.
  360. <strong>Not implemented in the JavaScript version.</strong>
  361. </td>
  362. </tr>
  363. </tbody>
  364. </table>
  365. `noCache`: Set to `true` to disable caching of results. If you will use the
  366. same rrule instance multiple times, enabling caching will improve the
  367. performance considerably. Enabled by default.
  368. See also [python-dateutil](http://labix.org/python-dateutil/)
  369. documentation.
  370. * * * * *
  371. #### Instance properties
  372. <dl>
  373. <dt><code>rule.options</code></dt>
  374. <dd>Processed options applied to the rule. Includes default options
  375. (such us <code>wkstart</code>). Currently,
  376. <code>rule.options.byweekday</code> isn't equal
  377. to <code>rule.origOptions.byweekday</code> (which is an inconsistency).
  378. </dd>
  379. <dt><code>rule.origOptions</code></dt>
  380. <dd>The original <code>options</code> argument passed to
  381. the constructor.</dd>
  382. </dl>
  383. * * * * *
  384. #### Occurrence Retrieval Methods
  385. ##### `RRule.prototype.all([iterator])`
  386. Returns all dates matching the rule. It is a replacement for the
  387. iterator protocol this class implements in the Python version.
  388. As rules without `until` or `count` represent infinite date series, you
  389. can optionally pass `iterator`, which is a function that is called for
  390. each date matched by the rule. It gets two parameters `date` (the `Date`
  391. instance being added), and `i` (zero-indexed position of `date` in the
  392. result). Dates are being added to the result as long as the iterator
  393. returns `true`. If a `false`-y value is returned, `date` isn't added to
  394. the result and the iteration is interrupted (possibly prematurely).
  395. ```javascript
  396. rule.all()
  397. [ '2012-02-01T10:30:00.000Z',
  398. '2012-05-01T10:30:00.000Z',
  399. '2012-07-01T10:30:00.000Z',
  400. '2012-07-02T10:30:00.000Z' ]
  401. rule.all(function (date, i){return i < 2})
  402. [ '2012-02-01T10:30:00.000Z',
  403. '2012-05-01T10:30:00.000Z' ]
  404. ```
  405. ##### `RRule.prototype.between(after, before, inc=false [, iterator])`
  406. Returns all the occurrences of the rrule between `after` and `before`.
  407. The inc keyword defines what happens if `after` and/or `before` are
  408. themselves occurrences. With `inc == true`, they will be included in the
  409. list, if they are found in the recurrence set.
  410. Optional `iterator` has the same function as it has with
  411. `RRule.prototype.all()`.
  412. ```javascript
  413. rule.between(new Date(Date.UTC(2012, 7, 1)), new Date(Date.UTC(2012, 8, 1)))
  414. ['2012-08-27T10:30:00.000Z',
  415. '2012-08-31T10:30:00.000Z']
  416. ```
  417. ##### `RRule.prototype.before(dt, inc=false)`
  418. Returns the last recurrence before the given `Date` instance. The `inc`
  419. argument defines what happens if `dt` is an occurrence. With
  420. `inc == true`, if `dt` itself is an occurrence, it will be returned.
  421. ##### `RRule.prototype.after(dt, inc=false)`
  422. Returns the first recurrence
  423. after the given `Date` instance. The `inc` argument defines what happens
  424. if `dt` is an occurrence. With `inc == true`, if `dt` itself is an
  425. occurrence, it will be returned.
  426. See also [python-dateutil](http://labix.org/python-dateutil/)
  427. documentation.
  428. * * * * *
  429. #### iCalendar RFC String Methods
  430. ##### `RRule.prototype.toString()`
  431. Returns a string representation of the rule as per the iCalendar RFC.
  432. Only properties explicitly specified in `options` are included:
  433. ```javascript
  434. rule.toString()
  435. "DTSTART:20120201T093000Z\nRRULE:FREQ=WEEKLY;INTERVAL=5;UNTIL=20130130T230000Z;BYDAY=MO,FR"
  436. rule.toString() == RRule.optionsToString(rule.origOptions)
  437. true
  438. ```
  439. ##### `RRule.optionsToString(options)`
  440. Converts `options` to iCalendar RFC `RRULE` string:
  441. ```javascript
  442. // Get full a string representation of all options,
  443. // including the default and inferred ones.
  444. RRule.optionsToString(rule.options)
  445. "DTSTART:20120201T093000Z\nRRULE:FREQ=WEEKLY;INTERVAL=5;WKST=0;UNTIL=20130130T230000Z;BYDAY=MO,FR;BYHOUR=10;BYMINUTE=30;BYSECOND=0"
  446. // Cherry-pick only some options from an rrule:
  447. RRule.optionsToString({
  448. freq: rule.options.freq,
  449. dtstart: rule.options.dtstart
  450. })
  451. "DTSTART:20120201T093000Z\nRRULE:FREQ=WEEKLY;"
  452. ```
  453. ##### `RRule.fromString(rfcString)`
  454. Constructs an `RRule` instance from a complete `rfcString`:
  455. ```javascript
  456. var rule = RRule.fromString("DTSTART:20120201T093000Z\nRRULE:FREQ=WEEKLY;")
  457. // This is equivalent
  458. var rule = new RRule(RRule.parseString("DTSTART:20120201T093000Z\nRRULE:FREQ=WEEKLY"))
  459. ```
  460. ##### `RRule.parseString(rfcString)`
  461. Only parse RFC string and return `options`.
  462. ```javascript
  463. var options = RRule.parseString('FREQ=DAILY;INTERVAL=6')
  464. options.dtstart = new Date(Date.UTC(2000, 1, 1))
  465. var rule = new RRule(options)
  466. ```
  467. * * * * *
  468. #### Natural Language Text Methods
  469. These methods provide an incomplete support for text–`RRule` and
  470. `RRule`–text conversion. You should test them with your input to see
  471. whether the result is acceptable.
  472. ##### `RRule.prototype.toText([gettext, [language]])`
  473. Returns a textual representation of `rule`. The `gettext` callback, if
  474. provided, will be called for each text token and its return value used
  475. instead. The optional `language` argument is a language definition to be
  476. used (defaults to `rrule/nlp.js:ENGLISH`).
  477. ```javascript
  478. var rule = new RRule({
  479. freq: RRule.WEEKLY,
  480. count: 23
  481. })
  482. rule.toText()
  483. "every week for 23 times"
  484. ```
  485. ##### `RRule.prototype.isFullyConvertibleToText()`
  486. Provides a hint on whether all the options the rule has are convertible
  487. to text.
  488. ##### `RRule.fromText(text[, language])`
  489. Constructs an `RRule` instance from `text`.
  490. ```javascript
  491. rule = RRule.fromText('every day for 3 times')
  492. ```
  493. ##### `RRule.parseText(text[, language])`
  494. Parse `text` into `options`:
  495. ```javascript
  496. options = RRule.parseText('every day for 3 times')
  497. // {freq: 3, count: "3"}
  498. options.dtstart = new Date(Date.UTC(2000, 1, 1))
  499. var rule = new RRule(options)
  500. ```
  501. * * * * *
  502. #### `RRuleSet` Constructor
  503. ```javascript
  504. new RRuleSet([noCache=false])
  505. ```
  506. The RRuleSet instance allows more complex recurrence setups, mixing multiple
  507. rules, dates, exclusion rules, and exclusion dates.
  508. Default `noCache` argument is `false`, caching of results will be enabled,
  509. improving performance of multiple queries considerably.
  510. ##### `RRuleSet.prototype.rrule(rrule)`
  511. Include the given rrule instance in the recurrence set generation.
  512. ##### `RRuleSet.prototype.rdate(dt)`
  513. Include the given datetime instance in the recurrence set generation.
  514. ##### `RRuleSet.prototype.exrule(rrule)`
  515. Include the given rrule instance in the recurrence set exclusion list. Dates
  516. which are part of the given recurrence rules will not be generated, even if
  517. some inclusive rrule or rdate matches them. NOTE: EXRULE has been (deprecated
  518. in RFC 5545)[https://icalendar.org/iCalendar-RFC-5545/a-3-deprecated-features.html]
  519. and does not support a DTSTART property.
  520. ##### `RRuleSet.prototype.exdate(dt)`
  521. Include the given datetime instance in the recurrence set exclusion list. Dates
  522. included that way will not be generated, even if some inclusive rrule or
  523. rdate matches them.
  524. ##### `RRuleSet.prototype.tzid(tz?)`
  525. Sets or overrides the timezone identifier. Useful if there are no rrules in this
  526. RRuleSet and thus no DTSTART.
  527. ##### `RRuleSet.prototype.all([iterator])`
  528. Same as `RRule.prototype.all`.
  529. ##### `RRuleSet.prototype.between(after, before, inc=false [, iterator])`
  530. Same as `RRule.prototype.between`.
  531. ##### `RRuleSet.prototype.before(dt, inc=false)`
  532. Same as `RRule.prototype.before`.
  533. ##### `RRuleSet.prototype.after(dt, inc=false)`
  534. Same as `RRule.prototype.after`.
  535. ##### `RRuleSet.prototype.rrules()`
  536. Get list of included rrules in this recurrence set.
  537. ##### `RRuleSet.prototype.exrules()`
  538. Get list of excluded rrules in this recurrence set.
  539. ##### `RRuleSet.prototype.rdates()`
  540. Get list of included datetimes in this recurrence set.
  541. ##### `RRuleSet.prototype.exdates()`
  542. Get list of excluded datetimes in this recurrence set.
  543. * * * * *
  544. #### `rrulestr` Function
  545. ```js
  546. rrulestr(rruleStr[, options])
  547. ```
  548. The `rrulestr` function is a parser for RFC-like syntaxes. The string passed
  549. as parameter may be a multiple line string, a single line string, or just the
  550. RRULE property value.
  551. Additionally, it accepts the following keyword arguments:
  552. `cache`
  553. If True, the rruleset or rrule created instance will cache its results.
  554. Default is not to cache.
  555. `dtstart`
  556. If given, it must be a datetime instance that will be used when no DTSTART
  557. property is found in the parsed string. If it is not given, and the property
  558. is not found, datetime.now() will be used instead.
  559. `unfold`
  560. If set to True, lines will be unfolded following the RFC specification. It
  561. defaults to False, meaning that spaces before every line will be stripped.
  562. `forceset`
  563. If set to True a rruleset instance will be returned, even if only a single rule
  564. is found. The default is to return an rrule if possible, and an rruleset if necessary.
  565. `compatible`
  566. If set to True, the parser will operate in RFC-compatible mode. Right now it
  567. means that unfold will be turned on, and if a DTSTART is found, it will be
  568. considered the first recurrence instance, as documented in the RFC.
  569. `tzid`
  570. If given, it must be a string that will be used when no `TZID` property is found
  571. in the parsed string. If it is not given, and the property is not found, `'UTC'`
  572. will be used by default.
  573. * * * * *
  574. ### Differences From iCalendar RFC
  575. * `RRule` has no `byday` keyword. The equivalent keyword has been replaced by
  576. the `byweekday` keyword, to remove the ambiguity present in the original
  577. keyword.
  578. * Unlike documented in the RFC, the starting datetime, `dtstart`, is
  579. not the first recurrence instance, unless it does fit in the specified rules.
  580. This is in part due to this project being a port of
  581. [python-dateutil](https://labix.org/python-dateutil#head-a65103993a21b717f6702063f3717e6e75b4ba66),
  582. which has the same non-compliant functionality. Note that you can get the
  583. original behavior by using a `RRuleSet` and adding the `dtstart` as an `rdate`.
  584. ```javascript
  585. var rruleSet = new RRuleSet()
  586. var start = new Date(Date.UTC(2012, 1, 1, 10, 30))
  587. // Add a rrule to rruleSet
  588. rruleSet.rrule(new RRule({
  589. freq: RRule.MONTHLY,
  590. count: 5,
  591. dtstart: start
  592. }))
  593. // Add a date to rruleSet
  594. rruleSet.rdate(start)
  595. ```
  596. * Unlike documented in the RFC, every keyword is valid on every frequency (the
  597. RFC documents that `byweekno` is only valid on yearly frequencies, for example).
  598. ### Development
  599. rrule.js is implemented in Typescript. It uses [JavaScript Standard Style](https://github.com/feross/standard) coding style.
  600. To run the code, checkout this repository and run:
  601. ```
  602. $ yarn
  603. ```
  604. To run the tests, run:
  605. ```
  606. $ yarn test
  607. ```
  608. To build files for distribution, run:
  609. ```
  610. $ yarn build
  611. ```
  612. #### Authors
  613. * [Jakub Roztocil](http://roztocil.co/)
  614. ([@jakubroztocil](http://twitter.com/jakubroztocil))
  615. * Lars Schöning ([@lyschoening](http://twitter.com/lyschoening))
  616. * David Golightly ([@davigoli](http://twitter.com/davigoli))
  617. Python `dateutil` is written by [Gustavo
  618. Niemeyer](http://niemeyer.net/).
  619. See [LICENCE](https://github.com/jakubroztocil/rrule/blob/master/LICENCE) for
  620. more details.
  621. [npm-url]: https://npmjs.org/package/rrule
  622. [npm-image]: http://img.shields.io/npm/v/rrule.svg
  623. [ci-url]: https://github.com/jakubroztocil/rrule/actions
  624. [ci-image]: https://github.com/jakubroztocil/rrule/workflows/Node%20CI/badge.svg
  625. [downloads-url]: https://npmjs.org/package/rrule
  626. [downloads-image]: http://img.shields.io/npm/dm/rrule.svg?style=flat-square
  627. [js-standard-url]: https://github.com/feross/standard
  628. [js-standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat
  629. [gitter-url]: https://gitter.im/rrule-js/Lobby
  630. [gitter-image]: https://img.shields.io/gitter/room/nwjs/nw.js.svg
  631. #### Related projects
  632. * https://rrules.com/ — RESTful API to get back occurrences of RRULEs that conform to RFC 5545.