···11+# These are supported funding model platforms
22+33+github: kbilkis
+83
CODE_OF_CONDUCT.md
···11+# Contributor Covenant Code of Conduct
22+33+## Our Pledge
44+55+We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
66+77+We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
88+99+## Our Standards
1010+1111+Examples of behavior that contributes to a positive environment for our community include:
1212+1313+- Demonstrating empathy and kindness toward other people
1414+- Being respectful of differing opinions, viewpoints, and experiences
1515+- Giving and gracefully accepting constructive feedback
1616+- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
1717+- Focusing on what is best not just for us as individuals, but for the overall community
1818+1919+Examples of unacceptable behavior include:
2020+2121+- The use of sexualized language or imagery, and sexual attention or advances of any kind
2222+- Trolling, insulting or derogatory comments, and personal or political attacks
2323+- Public or private harassment
2424+- Publishing others' private information, such as a physical or email address, without their explicit permission
2525+- Other conduct which could reasonably be considered inappropriate in a professional setting
2626+2727+## Enforcement Responsibilities
2828+2929+Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
3030+3131+Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
3232+3333+## Scope
3434+3535+This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
3636+3737+## Enforcement
3838+3939+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at kasparas@bilkis.lt. All complaints will be reviewed and investigated promptly and fairly.
4040+4141+All community leaders are obligated to respect the privacy and security of the reporter of any incident.
4242+4343+## Enforcement Guidelines
4444+4545+Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
4646+4747+### 1. Correction
4848+4949+**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
5050+5151+**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
5252+5353+### 2. Warning
5454+5555+**Community Impact**: A violation through a single incident or series of actions.
5656+5757+**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
5858+5959+### 3. Temporary Ban
6060+6161+**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
6262+6363+**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
6464+6565+### 4. Permanent Ban
6666+6767+**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
6868+6969+**Consequence**: A permanent ban from any sort of public interaction within the community.
7070+7171+## Attribution
7272+7373+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
7474+7575+Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
7676+7777+For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
7878+7979+[homepage]: https://www.contributor-covenant.org
8080+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
8181+[Mozilla CoC]: https://github.com/mozilla/diversity
8282+[FAQ]: https://www.contributor-covenant.org/faq
8383+[translations]: https://www.contributor-covenant.org/translations
+143
CONTRIBUTING.md
···11+# Contributing to cron-fast
22+33+Thank you for your interest in contributing to cron-fast! This document provides guidelines and instructions for contributing.
44+55+## Table of Contents
66+77+- [Code of Conduct](#code-of-conduct)
88+- [Development Setup](#development-setup)
99+- [How to Contribute](#how-to-contribute)
1010+- [Development Workflow](#development-workflow)
1111+- [Pull Request Guidelines](#pull-request-guidelines)
1212+- [Coding Standards](#coding-standards)
1313+1414+## Code of Conduct
1515+1616+This project and everyone participating in it is governed by our [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code.
1717+1818+## Development Setup
1919+2020+### Prerequisites
2121+2222+- Node.js >= 20.0.0
2323+- pnpm (recommended) or npm
2424+2525+### Installation
2626+2727+1. Fork the repository
2828+2. Clone your fork:
2929+ ```bash
3030+ git clone https://github.com/YOUR_USERNAME/cron-fast.git
3131+ cd cron-fast
3232+ ```
3333+3. Install dependencies:
3434+ ```bash
3535+ pnpm install
3636+ ```
3737+3838+## How to Contribute
3939+4040+### Reporting Bugs
4141+4242+- Check if the bug has already been reported in [Issues](https://github.com/kbilkis/cron-fast/issues)
4343+- If not, create a new issue with:
4444+ - Clear, descriptive title
4545+ - Steps to reproduce
4646+ - Expected vs actual behavior
4747+ - Node.js/runtime version
4848+ - Code sample if applicable
4949+5050+### Suggesting Features
5151+5252+- Open an issue with the `enhancement` label
5353+- Describe the feature and its use case
5454+- Explain why it would benefit the project
5555+5656+### Submitting Changes
5757+5858+1. Create a feature branch from `main`:
5959+ ```bash
6060+ git checkout -b feature/my-feature
6161+ ```
6262+2. Make your changes
6363+3. Write/update tests
6464+4. Ensure all tests pass
6565+5. Submit a pull request
6666+6767+## Development Workflow
6868+6969+### Available Scripts
7070+7171+```bash
7272+# Run tests
7373+pnpm test
7474+7575+# Run tests in watch mode
7676+pnpm test:watch
7777+7878+# Run tests with coverage
7979+pnpm test:coverage
8080+8181+# Lint code
8282+pnpm lint
8383+8484+# Format code
8585+pnpm fmt
8686+8787+# Type check
8888+pnpm typecheck
8989+9090+# Build
9191+pnpm build
9292+9393+# Run benchmarks
9494+pnpm benchmark
9595+```
9696+9797+### Testing
9898+9999+- Write tests for all new features and bug fixes
100100+- Ensure all existing tests pass
101101+- Aim for high test coverage
102102+- Test across runtimes if making significant changes:
103103+ - Node.js: `pnpm test`
104104+ - Deno: `pnpm benchmark:deno`
105105+ - Bun: `pnpm benchmark:bun`
106106+107107+## Pull Request Guidelines
108108+109109+- Keep PRs focused and small
110110+- Write clear commit messages
111111+- Update documentation if needed
112112+- Add tests for new functionality
113113+- Ensure CI passes
114114+- Reference related issues
115115+116116+### PR Checklist
117117+118118+- [ ] Tests pass locally
119119+- [ ] Linting passes
120120+- [ ] Type checking passes
121121+- [ ] Documentation updated (if needed)
122122+- [ ] Commit messages are clear
123123+124124+## Coding Standards
125125+126126+- **TypeScript**: Strict mode enabled
127127+- **Style**: Formatted with `oxfmt`
128128+- **Linting**: Uses `oxlint`
129129+- **Commits**: Clear, descriptive messages
130130+131131+### Code Style
132132+133133+- Use TypeScript for all source files
134134+- Prefer functional programming patterns
135135+- Keep functions small and focused
136136+- Add JSDoc comments for public APIs
137137+- Follow existing code patterns
138138+139139+## Questions?
140140+141141+Feel free to open an issue for questions or discussions about contributing.
142142+143143+Thank you for contributing! 🎉
+28-19
README.md
···77[](https://github.com/kbilkis/cron-fast/actions/workflows/ci.yml)
88[](https://codecov.io/github/kbilkis/cron-fast)
99[](https://bundlejs.com/?q=cron-fast)
1010+[](https://snyk.io/test/npm/cron-fast)
1011[](https://opensource.org/licenses/MIT)
11121213**Fast and tiny JavaScript/TypeScript cron parser with timezone support.** Works everywhere: Node.js, Deno, Bun, Cloudflare Workers, and browsers. Zero dependencies.
···173174174175## Bundle Size
175176176176-cron-fast is extremely lightweight and fully tree-shakeable. Here are the actual bundle sizes for different import scenarios (tested with v2.0.1):
177177+cron-fast is extremely lightweight and fully tree-shakeable. Here are the actual bundle sizes for different import scenarios (tested with v2.1.0):
177178178179| Import | Raw | Minified | Gzipped |
179180| ------------------------------------------------------ | -------- | -------- | ----------- |
180180-| `Full bundle (all exports) ` | 21.86 KB | 10.12 KB | **3.61 KB** |
181181-| `nextRun only ` | 13.12 KB | 6.03 KB | **2.21 KB** |
182182-| `previousRun only ` | 13.13 KB | 6.03 KB | **2.22 KB** |
183183-| `nextRuns only ` | 13.50 KB | 6.18 KB | **2.28 KB** |
184184-| `isValid only ` | 4.44 KB | 2.23 KB | **980 B** |
185185-| `parse only ` | 4.33 KB | 2.19 KB | **956 B** |
186186-| `describe only ` | 11.55 KB | 5.58 KB | **2.11 KB** |
187187-| `isMatch only ` | 6.35 KB | 3.15 KB | **1.33 KB** |
188188-| `Validation only (isValid + parse) ` | 4.45 KB | 2.24 KB | **981 B** |
189189-| `Scheduling only (nextRun + previousRun + nextRuns) ` | 13.91 KB | 6.36 KB | **2.30 KB** |
181181+| `Full bundle (all exports) ` | 21.84 KB | 10.12 KB | **3.61 KB** |
182182+| `nextRun only ` | 13.10 KB | 6.03 KB | **2.22 KB** |
183183+| `previousRun only ` | 13.11 KB | 6.03 KB | **2.22 KB** |
184184+| `nextRuns only ` | 13.49 KB | 6.18 KB | **2.28 KB** |
185185+| `isValid only ` | 4.42 KB | 2.23 KB | **986 B** |
186186+| `parse only ` | 4.31 KB | 2.18 KB | **963 B** |
187187+| `describe only ` | 11.53 KB | 5.58 KB | **2.11 KB** |
188188+| `isMatch only ` | 6.33 KB | 3.15 KB | **1.33 KB** |
189189+| `Validation only (isValid + parse) ` | 4.43 KB | 2.23 KB | **988 B** |
190190+| `Scheduling only (nextRun + previousRun + nextRuns) ` | 13.89 KB | 6.36 KB | **2.30 KB** |
190191191192Import only what you need:
192193193194```typescript
194194-// Small bundle - only validation (~900 B gzipped)
195195+// Small bundle - only validation
195196import { isValid } from "cron-fast";
196197197197-// Medium bundle - one function + dependencies (~2 KB gzipped)
198198+// Medium bundle - one function + dependencies
198199import { nextRun } from "cron-fast";
199200200200-// Full bundle - everything (~2.3 KB gzipped)
201201+// Full bundle - everything
201202import * as cron from "cron-fast";
202203```
203204···283284284285cron-fast is designed for speed and efficiency. Here's how it compares to popular alternatives:
285286286286-> Tested with cron-fast v2.0.1, croner v10.0.1, cron-parser v5.5.0, cron-schedule v6.0.0 on Node.js v22.18.0
287287+> Tested with cron-fast v2.1.0, croner v10.0.1, cron-parser v5.5.0, cron-schedule v6.0.0 on Node.js v22.18.0
287288288289| Operation | cron-fast | croner | cron-parser | cron-schedule |
289290| ------------ | -------------- | --------- | ----------- | ------------- |
290290-| Next run | **367k ops/s** | 30k ops/s | 33k ops/s | 375k ops/s |
291291-| Previous run | **409k ops/s** | 31k ops/s | 37k ops/s | 386k ops/s |
292292-| Validation | **555k ops/s** | 32k ops/s | 94k ops/s | 436k ops/s |
293293-| Parsing | **543k ops/s** | 32k ops/s | 92k ops/s | 446k ops/s |
291291+| Next run | **459k ops/s** | 31k ops/s | 32k ops/s | 374k ops/s |
292292+| Previous run | **512k ops/s** | 31k ops/s | 37k ops/s | 388k ops/s |
293293+| Validation | **733k ops/s** | 34k ops/s | 92k ops/s | 453k ops/s |
294294+| Parsing | **735k ops/s** | 34k ops/s | 92k ops/s | 458k ops/s |
294295295296See [detailed benchmarks and feature comparison](docs/benchmark-comparison.md) (including Deno and Bun runtimes) for more information.
296297297298Run benchmarks yourself: `pnpm benchmark`
299299+300300+## Contributing
301301+302302+Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
303303+304304+## Contributors
305305+306306+- [Kasparas Bilkis](https://github.com/kbilkis) - Creator and maintainer
298307299308## License
300309
···11{
22 "name": "@kbilkis/cron-fast",
33- "version": "2.0.1",
33+ "version": "2.1.0",
44 "description": "Fast and tiny JavaScript/TypeScript cron parser with timezone support - works in Node.js, Deno, Bun, Cloudflare Workers, and browsers. Zero dependencies.",
55 "keywords": [
66 "javascript",
+5-1
package.json
···11{
22 "name": "cron-fast",
33- "version": "2.0.1",
33+ "version": "2.1.0",
44 "description": "Fast and tiny JavaScript/TypeScript cron parser with timezone support - works in Node.js, Deno, Bun, Cloudflare Workers, and browsers. Zero dependencies.",
55 "keywords": [
66 "browser",
···3030 "repository": {
3131 "type": "git",
3232 "url": "https://github.com/kbilkis/cron-fast.git"
3333+ },
3434+ "funding": {
3535+ "type": "github",
3636+ "url": "https://github.com/sponsors/kbilkis"
3337 },
3438 "files": [
3539 "dist",
+8-8
src/parser.ts
···124124 max: number,
125125 names?: Record<string, number>,
126126): number[] | null {
127127- const values = new Set<number>();
127127+ const values: number[] = [];
128128129129 if (field === "*") {
130130- for (let i = min; i <= max; i++) values.add(i);
131131- return Array.from(values).sort((a, b) => a - b);
130130+ for (let i = min; i <= max; i++) values.push(i);
131131+ return values.slice().sort((a, b) => a - b);
132132 }
133133134134 const parts = field.split(",");
···160160 }
161161162162 for (let i = start; i <= end; i += step) {
163163- if (i >= min && i <= max) values.add(i);
163163+ if (i >= min && i <= max) values.push(i);
164164 }
165165 }
166166 // Handle ranges (e.g., 1-5)
···174174 if (start > end) return null;
175175176176 for (let i = start; i <= end; i++) {
177177- if (i >= min && i <= max) values.add(i);
177177+ if (i >= min && i <= max) values.push(i);
178178 }
179179 }
180180 // Handle single values
···182182 const value = parseValue(part, names);
183183 if (value === null) return null;
184184 if (value < min || value > max) return null;
185185- values.add(value);
185185+ values.push(value);
186186 }
187187 }
188188189189- if (values.size === 0) return null;
190190- return Array.from(values).sort((a, b) => a - b);
189189+ if (values.length === 0) return null;
190190+ return [...new Set(values)].sort((a, b) => a - b);
191191}
192192193193/**