This repository contains a flexible, composable, and extensible TypeScript library for representing, evaluating, and describing complex conditions on time ranges. The support for time ranges is what makes it different from many other popular time scheduling libraries that focus on events (points in time).
Try it online: You can view and use the interactive test/demo app at https://knz.github.io/timecond/
The main library is located in packages/timecond, and a test/demo UI is available in examples/react.
A reusable TypeScript library for advanced scheduling, filtering, and rule-based logic involving time intervals, recurring patterns, and human-friendly time expressions.
- Composable Time Conditions: Express rules like "every Monday", "between 9am and 5pm", "the third Friday of each month", or "between December 15 and January 10".
- Logical Combinators: Combine conditions using AND, OR, Nth, and FirstAfter constructs for arbitrarily complex rules.
- Rich Query API:
- Check if a date/time satisfies a condition
- Find the next or last occurrence
- Generate human-readable descriptions
- Extensible: Add new condition types by subclassing the base
Condclass. - Efficient: Uses sorted, non-overlapping date ranges and binary search for fast queries.
- Localization: Day parts and season hemispheres are configurable via a
TimeConfigobject. - DSL Parser: Supports a human-friendly domain-specific language for defining time conditions (see below).
import { CondFactory, AndCond, parse, defaultTimeConfig } from '@knz/timecond';
// --- Classic API (composable objects) ---
const factory = new CondFactory(defaultTimeConfig);
const weekdayCond = factory.makeWeekDay('monday');
const morningCond = factory.dayPart('morning');
const workdayMorning = new AndCond([weekdayCond, morningCond]);
const now = new Date();
console.log('Is now a workday morning?', workdayMorning.inRange(now));
console.log('Next workday morning starts at:', workdayMorning.nextStart(now));
// --- DSL Parser API ---
// You can also use the built-in human-friendly DSL parser:
const expr = 'both monday and morning';
const cond = parse(expr, defaultTimeConfig); // cond is a Cond instance
console.log('Is now a workday morning (via DSL)?', cond.inRange(now));
console.log('Next workday morning (via DSL) starts at:', cond.nextStart(now));- Time of day, day of week, day of month, month, date ranges
- Named day parts (e.g., "morning"), seasons, custom ranges
- Lunar phases (new moon, full moon)
- Logical AND/OR/Nth/FirstAfter combinators
- Relative and recurring patterns (e.g., "after 2 hours", "nth 3 Monday after...", etc.)
either monday or fridayboth workday and morningfirst tuesday after start of january exclusiventh 2 fridaydaily from 9:00 to 17:00 inclusiveyearly from december 15 to january 10both full moon and nightnew moon within 6 hours
See the library README for full details.
A React-based demo and test UI for the TimeCond library. This UI allows you to:
- Enter and parse time condition expressions (using the DSL)
- Select reference and evaluation dates
- Visualize the evaluation results, including next/last occurrences and active ranges
- See human-readable descriptions of parsed conditions
- Experiment interactively with all features of the library
Try it online: You can view and use the interactive test/demo app at https://knz.github.io/timecond/
To run the test UI locally, see the instructions in examples/react.
Here are some popular time condition libraries. Note that they are all event-oriented: they provide conditions on points in time not entire time ranges. They do not support conditions like "the first night after the start of monday".
- rSchedule: Powerful, date-library agnostic, supports iCal, custom rules, and occurrence stream operators. API is inspired by iCal and is very flexible.
- rrulejs: Implements the iCal RRULE spec, widely used, mature, but less extensible and not as composable for custom logic.
- laterjs: Simpler API, supports cron-like schedules, not iCal compatible, less flexible for complex rules, currently unmaintained.
- dayspan: Full-featured for recurring dates, but with a unique API and less focus on composability/extensibility.