{"id":13527175,"url":"https://github.com/harrisiirak/cron-parser","last_synced_at":"2026-10-19T12:43:26.492Z","repository":{"id":6103791,"uuid":"7331247","full_name":"harrisiirak/cron-parser","owner":"harrisiirak","description":"Typescript library for parsing crontab instructions","archived":false,"fork":false,"pushed_at":"2026-10-11T15:14:17.000Z","size":1844,"stargazers_count":1501,"open_issues_count":13,"forks_count":176,"subscribers_count":13,"default_branch":"master","last_synced_at":"2026-10-17T15:07:52.600Z","etag":null,"topics":["cron","cron-expression","cron-parser","cronjob","crontab","crontab-format","typescript","typescript-library"],"latest_commit_sha":null,"homepage":"http://harrisiirak.github.io/cron-parser/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/harrisiirak.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"claude":null,"gemini":null,"cursor":null,"copilot":null,"dco":null,"cla":null,"disclosure":null},"funding":{"github":"harrisiirak","patreon":"harrisiirak","ko_fi":"harrisiirak"}},"created_at":"2012-12-26T19:52:17.000Z","updated_at":"2026-10-15T05:35:59.000Z","dependencies_parsed_at":"2026-09-18T02:50:21.507Z","dependency_job_id":null,"html_url":"https://github.com/harrisiirak/cron-parser","commit_stats":{"total_commits":296,"total_committers":52,"mean_commits":"5.6923076923076925","dds":0.6283783783783784,"last_synced_commit":"fa94e7f67870db1a36f09a526129d986ae966f47"},"previous_names":[],"tags_count":95,"template":false,"template_full_name":null,"purl":"pkg:github/harrisiirak/cron-parser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harrisiirak%2Fcron-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harrisiirak%2Fcron-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harrisiirak%2Fcron-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harrisiirak%2Fcron-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/harrisiirak","download_url":"https://codeload.github.com/harrisiirak/cron-parser/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harrisiirak%2Fcron-parser/sbom","scorecard":{"id":456103,"data":{"date":"2025-08-11","repo":{"name":"github.com/harrisiirak/cron-parser","commit":"4b16aa93ca387fa0efff8a22b35a33470744b755"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.2,"checks":[{"name":"Code-Review","score":1,"reason":"Found 5/30 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":10,"reason":"4 commit(s) and 8 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: topLevel 'contents' permission set to 'read': .github/workflows/documentation.yml:9","Warn: no topLevel permission defined: .github/workflows/push.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":2,"reason":"dependency not pinned by hash detected -- score normalized to 2","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/documentation.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/harrisiirak/cron-parser/documentation.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/documentation.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/harrisiirak/cron-parser/documentation.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/documentation.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/harrisiirak/cron-parser/documentation.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/documentation.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/harrisiirak/cron-parser/documentation.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/documentation.yml:43: update your workflow using https://app.stepsecurity.io/secureworkflow/harrisiirak/cron-parser/documentation.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/push.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/harrisiirak/cron-parser/push.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/push.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/harrisiirak/cron-parser/push.yml/master?enable=pin","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned","Info:   2 out of   2 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 9 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":6,"reason":"4 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-xffm-g5w8-qvg7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T09:43:39.465Z","repository_id":6103791,"created_at":"2025-08-19T09:43:39.465Z","updated_at":"2025-08-19T09:43:39.465Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":344872684,"owners_count":38334940,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-10-03T21:59:58.778Z","status":"online","status_checked_at":"2026-10-17T02:00:06.547Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cron","cron-expression","cron-parser","cronjob","crontab","crontab-format","typescript","typescript-library"],"created_at":"2024-08-01T06:01:42.550Z","updated_at":"2026-10-19T12:43:26.486Z","avatar_url":"https://github.com/harrisiirak.png","language":"TypeScript","funding_links":["https://github.com/sponsors/harrisiirak","https://patreon.com/harrisiirak","https://ko-fi.com/harrisiirak"],"categories":["Repository","TypeScript"],"sub_categories":["Job Scheduling"],"readme":"# cron-parser\n\n[![Build Status](https://github.com/harrisiirak/cron-parser/actions/workflows/push.yml/badge.svg?branch=master)](https://github.com/harrisiirak/cron-parser/actions/workflows/push.yml)\n[![NPM version](https://badge.fury.io/js/cron-parser.png)](http://badge.fury.io/js/cron-parser)\n![Statements](https://harrisiirak.github.io/cron-parser/badge-statements.svg)\n\nA JavaScript library for parsing and manipulating cron expressions. Features timezone support, DST handling, and iterator capabilities.\n\n[API documentation](https://harrisiirak.github.io/cron-parser/)\n\n## Requirements\n\n- Node.js \u003e= 18\n- TypeScript \u003e= 5\n\n## Installation\n\n```bash\nnpm install cron-parser\n```\n\n## Cron Format\n\n```\n*    *    *    *    *    *\n┬    ┬    ┬    ┬    ┬    ┬\n│    │    │    │    │    │\n│    │    │    │    │    └─ day of week (0-7, 1L-7L) (0 or 7 is Sun)\n│    │    │    │    └────── month (1-12, JAN-DEC)\n│    │    │    └─────────── day of month (1-31, L)\n│    │    └──────────────── hour (0-23)\n│    └───────────────────── minute (0-59)\n└────────────────────────── second (0-59, optional)\n```\n\n### Special Characters\n\n| Character | Description               | Example                                                                |\n| --------- | ------------------------- | ---------------------------------------------------------------------- |\n| `*`       | Any value                 | `* * * * *` (every minute)                                             |\n| `?`       | Any value (alias for `*`) | `? * * * *` (every minute)                                             |\n| `,`       | Value list separator      | `1,2,3 * * * *` (1st, 2nd, and 3rd minute)                             |\n| `-`       | Range of values           | `1-5 * * * *` (every minute from 1 through 5)                          |\n| `/`       | Step values               | `*/5 * * * *` (every 5th minute)                                       |\n| `L`       | Last day of month/week    | `0 0 L * *` (midnight on last day of month)                            |\n| `#`       | Nth day of month          | `0 0 * * 1#1` (first Monday of month)                                  |\n| `H`       | Randomized value          | `H * * * *` (every n minute where n is randomly picked within [0, 59]) |\n\n### Predefined Expressions\n\n| Expression  | Description                               | Equivalent      |\n| ----------- | ----------------------------------------- | --------------- |\n| `@yearly`   | Once a year at midnight of January 1      | `0 0 0 1 1 *`   |\n| `@monthly`  | Once a month at midnight of first day     | `0 0 0 1 * *`   |\n| `@weekly`   | Once a week at midnight on Sunday         | `0 0 0 * * 0`   |\n| `@daily`    | Once a day at midnight                    | `0 0 0 * * *`   |\n| `@hourly`   | Once an hour at the beginning of the hour | `0 0 * * * *`   |\n| `@minutely` | Once a minute                             | `0 * * * * *`   |\n| `@secondly` | Once a second                             | `* * * * * *`   |\n| `@weekdays` | Every weekday at midnight                 | `0 0 0 * * 1-5` |\n| `@weekends` | Every weekend at midnight                 | `0 0 0 * * 0,6` |\n\n### Field Values\n\n| Field        | Values | Special Characters              | Aliases                        |\n| ------------ | ------ | ------------------------------- | ------------------------------ |\n| second       | 0-59   | `*` `?` `,` `-` `/` `H`         |                                |\n| minute       | 0-59   | `*` `?` `,` `-` `/` `H`         |                                |\n| hour         | 0-23   | `*` `?` `,` `-` `/` `H`         |                                |\n| day of month | 1-31   | `*` `?` `,` `-` `/` `H` `L`     |                                |\n| month        | 1-12   | `*` `?` `,` `-` `/` `H`         | `JAN`-`DEC`                    |\n| day of week  | 0-7    | `*` `?` `,` `-` `/` `H` `L` `#` | `SUN`-`SAT` (0 or 7 is Sunday) |\n\n## Options\n\n| Option      | Type                     | Description                                                                                                                 |\n| ----------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------- |\n| currentDate | Date \\| string \\| number | Current date. Defaults to current local time in UTC. If not provided but startDate is set, startDate is used as currentDate |\n| endDate     | Date \\| string \\| number | End date of iteration range. Sets iteration range end point                                                                 |\n| startDate   | Date \\| string \\| number | Start date of iteration range. Set iteration range start point                                                              |\n| tz          | string                   | Timezone (e.g., 'Europe/London')                                                                                            |\n| hashSeed    | string                   | A seed to be used in conjunction with the `H` special character                                                             |\n| strict      | boolean                  | Enable strict mode validation                                                                                               |\n\nWhen using string dates, the following formats are supported:\n\n- ISO8601\n- HTTP and RFC2822\n- SQL\n\n## Basic Usage\n\n### Expression Parsing\n\n```typescript\nimport { CronExpressionParser } from 'cron-parser';\n\ntry {\n  const interval = CronExpressionParser.parse('*/2 * * * *');\n\n  // Get next date\n  console.log('Next:', interval.next().toString());\n  // Get next 3 dates\n  console.log(\n    'Next 3:',\n    interval.take(3).map((date) =\u003e date.toString()),\n  );\n\n  // Get previous date\n  console.log('Previous:', interval.prev().toString());\n} catch (err) {\n  console.log('Error:', err.message);\n}\n```\n\n### With Options\n\n```typescript\nimport { CronExpressionParser } from 'cron-parser';\n\nconst options = {\n  currentDate: '2023-01-01T00:00:00Z',\n  endDate: '2024-01-01T00:00:00Z',\n  tz: 'Europe/London',\n};\n\ntry {\n  const interval = CronExpressionParser.parse('0 0 * * *', options);\n  console.log('Next:', interval.next().toString());\n} catch (err) {\n  console.log('Error:', err.message);\n}\n```\n\n### Date Range Handling\n\nThe library provides handling of date ranges with automatic adjustment of the `currentDate`:\n\n**startDate as fallback**: If `currentDate` is not provided but `startDate` is, the `startDate` will be used as the `currentDate`.\n\n```typescript\nconst options = {\n  startDate: '2023-01-01T00:00:00Z', // No currentDate provided\n};\n// currentDate will be set to 2023-01-01T00:00:00Z automatically\nconst interval = CronExpressionParser.parse('0 0 * * *', options);\n```\n\n**Automatic clamping**: If `currentDate` is outside the bounds defined by `startDate` and `endDate`, it will be automatically adjusted:\n\n```typescript\nconst options = {\n  currentDate: '2022-01-01T00:00:00Z', // Before startDate\n  startDate: '2023-01-01T00:00:00Z',\n  endDate: '2024-01-01T00:00:00Z',\n};\n// currentDate will be clamped to startDate (2023-01-01T00:00:00Z)\nconst interval = CronExpressionParser.parse('0 0 * * *', options);\n```\n\n**Validation during iteration**: While the initial `currentDate` is automatically adjusted, the library still validates date bounds during iteration:\n\n```typescript\nconst options = {\n  currentDate: '2023-12-31T00:00:00Z',\n  endDate: '2024-01-01T00:00:00Z', // Very close end date\n};\n\nconst interval = CronExpressionParser.parse('0 0 * * *', options);\nconsole.log('Next:', interval.next().toString()); // Works fine\n\n// This will throw an error because it would exceed endDate\ntry {\n  console.log('Next:', interval.next().toString());\n} catch (err) {\n  console.log('Error:', err.message); // \"Out of the time span range\"\n}\n```\n\nThis behavior simplifies working with date ranges by removing the need to manually ensure that `currentDate` is within bounds, reducing confusion and making the API more intuitive.\n\n### Crontab File Operations\n\nFor working with crontab files, use the CronFileParser:\n\n```typescript\nimport { CronFileParser } from 'cron-parser';\n\n// Async file parsing\ntry {\n  const result = await CronFileParser.parseFile('/path/to/crontab');\n  console.log('Variables:', result.variables);\n  console.log('Expressions:', result.expressions);\n  console.log('Errors:', result.errors);\n} catch (err) {\n  console.log('Error:', err.message);\n}\n\n// Sync file parsing\ntry {\n  const result = CronFileParser.parseFileSync('/path/to/crontab');\n  console.log('Variables:', result.variables);\n  console.log('Expressions:', result.expressions);\n  console.log('Errors:', result.errors);\n} catch (err) {\n  console.log('Error:', err.message);\n}\n```\n\n## Advanced Features\n\n### Strict Mode\n\nIn several implementations of CRON, it's ambiguous to specify both the Day Of Month and Day Of Week parameters simultaneously, as it's unclear which one should take precedence. Despite this ambiguity, this library allows both parameters to be set by default, although the resultant behavior might not align with your expectations.\n\nTo resolve this ambiguity, you can activate the strict mode of the library. When strict mode is enabled, the library enforces several validation rules:\n\n1. **Day Of Month and Day Of Week**: Prevents the simultaneous setting of both Day Of Month and Day Of Week fields\n2. **Complete Expression**: Requires all 6 fields to be present in the expression (second, minute, hour, day of month, month, day of week)\n3. **Non-empty Expression**: Rejects empty expressions that would otherwise default to '0 \\* \\* \\* \\* \\*'\n4. **Usable Hashed Range and Step**: Rejects a hash the field cannot satisfy - a range reaching outside the field, such as `H(0-5)` in day of month, or a step wider than the range it applies to, such as `H(1-5)/10` (see [Hash support](#hash-support))\n\nThese validations help ensure that your cron expressions are unambiguous and correctly formatted.\n\n```typescript\nimport { CronExpressionParser } from 'cron-parser';\n\n// This will throw an error in strict mode because it uses both dayOfMonth and dayOfWeek\nconst options = {\n  currentDate: new Date('Mon, 12 Sep 2022 14:00:00'),\n  strict: true,\n};\n\ntry {\n  // This will throw an error in strict mode\n  CronExpressionParser.parse('0 0 12 1-31 * 1', options);\n} catch (err) {\n  console.log('Error:', err.message);\n  // Error: Cannot use both dayOfMonth and dayOfWeek together in strict mode!\n}\n\n// This will also throw an error in strict mode because it has fewer than 6 fields\ntry {\n  CronExpressionParser.parse('0 20 15 * *', { strict: true });\n} catch (err) {\n  console.log('Error:', err.message);\n  // Error: Invalid cron expression, expected 6 fields\n}\n\n// This will also throw an error in strict mode because a step of 10 cannot fit the range 1-5\ntry {\n  CronExpressionParser.parse('0 H(1-5)/10 * * * *', { strict: true });\n} catch (err) {\n  console.log('Error:', err.message);\n  // Error: Invalid step: 10, wider than the 1-5 range of the minute field\n}\n```\n\n### Last Day of Month/Week Support\n\nThe library supports parsing the range `0L - 7L` in the `weekday` position of the cron expression, where the `L` means \"last occurrence of this weekday for the month in progress\".\n\nFor example, the following expression will run on the last Monday of the month at midnight:\n\n```typescript\nimport { CronExpressionParser } from 'cron-parser';\n\n// Last Monday of every month at midnight\nconst lastMonday = CronExpressionParser.parse('0 0 0 * * 1L');\n\n// You can also combine L expressions with other weekday expressions\n// This will run every Monday and the last Wednesday of the month\nconst mixedWeekdays = CronExpressionParser.parse('0 0 0 * * 1,3L');\n\n// Last day of every month\nconst lastDay = CronExpressionParser.parse('0 0 L * *');\n```\n\n### Using Iterator\n\n```typescript\nimport { CronExpressionParser } from 'cron-parser';\n\nconst interval = CronExpressionParser.parse('0 */2 * * *');\n\n// Using for...of\nfor (const date of interval) {\n  console.log('Iterator value:', date.toString());\n  if (someCondition) break;\n}\n\n// Using take() for a specific number of iterations\nconst nextFiveDates = interval.take(5);\nconsole.log(\n  'Next 5 dates:',\n  nextFiveDates.map((date) =\u003e date.toString()),\n);\n```\n\n### Timezone Support\n\nThe library provides robust timezone support using Luxon, handling DST transitions correctly:\n\n```typescript\nimport { CronExpressionParser } from 'cron-parser';\n\nconst options = {\n  currentDate: '2023-03-26T01:00:00',\n  tz: 'Europe/London',\n};\n\nconst interval = CronExpressionParser.parse('0 * * * *', options);\n\n// Will correctly handle DST transition\nconsole.log('Next dates during DST transition:');\nconsole.log(interval.next().toString());\nconsole.log(interval.next().toString());\nconsole.log(interval.next().toString());\n```\n\n### Field Manipulation\n\nYou can modify cron fields programmatically using `CronFieldCollection.from` and construct a new expression:\n\n```typescript\nimport { CronExpressionParser, CronFieldCollection, CronHour, CronMinute } from 'cron-parser';\n\n// Parse original expression\nconst interval = CronExpressionParser.parse('0 7 * * 1-5');\n\n// Create new collection with modified fields using raw values\nconst modified = CronFieldCollection.from(interval.fields, {\n  hour: [8],\n  minute: [30],\n  dayOfWeek: [1, 3, 5],\n});\n\nconsole.log(modified.stringify()); // \"30 8 * * 1,3,5\"\n\n// You can also use CronField instances\nconst modified2 = CronFieldCollection.from(interval.fields, {\n  hour: new CronHour([15]),\n  minute: new CronMinute([30]),\n});\n\nconsole.log(modified2.stringify()); // \"30 15 * * 1-5\"\n```\n\nThe `CronFieldCollection.from` method accepts either CronField instances or raw values that would be valid for creating new CronField instances. This is particularly useful when you need to modify only specific fields while keeping others unchanged.\n\n### Hash support\n\nThe library supports adding [jitter](https://en.wikipedia.org/wiki/Jitter) to the returned intervals using the `H` special character in a field. When `H` is specified instead of `*`, a random value is used (`H` is replaced by `23`, where 23 is picked randomly, within the valid range of the field).\n\nThis jitter allows to spread the load when it comes to job scheduling. This feature is inspired by Jenkins's cron syntax.\n\n```typescript\nimport { CronExpressionParser } from 'cron-parser';\n\n// At 23:\u003crandomized\u003e on every day-of-week from Monday through Friday.\nconst interval = CronExpressionParser.parse('H 23 * * 1-5');\n\n// At \u003crandomized\u003e:30 everyday.\nconst interval = CronExpressionParser.parse('30 H * * *');\n\n// At every minutes of \u003crandomized\u003e hour at \u003crandomized\u003e second everyday.\nconst interval = CronExpressionParser.parse('H * H * * *');\n\n// At every 5th minute starting from a random offset.\n// For example, if the random offset is 3, it will run at minutes 3, 8, 13, 18, etc.\nconst interval = CronExpressionParser.parse('H/5 * * * *');\n\n// At a random minute within the range 0-10 everyday.\nconst interval = CronExpressionParser.parse('H(0-10) * * * *');\n\n// At every 5th minute starting from a random offset within the range 0-4.\n// For example, if the random offset is 2, it will run at minutes 2, 7, 12, 17, etc.\n// The random offset is constrained to be less than the step value.\nconst interval = CronExpressionParser.parse('H(0-29)/5 * * * *');\n\n// At every minute of the third \u003crandomized\u003e day of the month\nconst interval = CronExpressionParser.parse('* * * * H#3');\n```\n\nA step only produces several occurrences while it is narrow enough to fit the range more than once. When the step is wider than the range - as in `H(1-5)/10`, or `H/60` in a field whose constraints are narrower than 60 - no step-aligned value is guaranteed to land inside the range, so the field falls back to a single random occurrence within it, exactly as `H(1-5)` would give:\n\n```typescript\nimport { CronExpressionParser } from 'cron-parser';\n\n// A step of 10 cannot fit the range 1-5, so this behaves like 'H(1-5)':\n// one random minute between 1 and 5.\nconst interval = CronExpressionParser.parse('H(1-5)/10 * * * *');\n```\n\nA range is first narrowed to what the field can hold, so `H(0-5)` in day of month picks a day between 1 and 5, and `H(50-100)/60` in the minute field steps across 50-59 rather than the 50-100 that was written. A range with nothing left after narrowing, such as `H(0-0)/40` in day of month, is rejected.\n\nWhether such an expression is a mistake is up to you: enable [strict mode](#strict-mode) to have it rejected instead of falling back.\n\nThe randomness is seed-able using the `hashSeed` option of `CronExpressionOptions`:\n\n```typescript\nimport { CronExpressionParser } from 'cron-parser';\n\nconst options = {\n  currentDate: '2023-03-26T01:00:00',\n  hashSeed: 'main-backup', // Generally, hashSeed would be a job name for example\n};\n\nconst interval = CronExpressionParser.parse('H * * * H', options);\n\nconsole.log(interval.stringify()); // \"12 * * * 4\"\n\nconst otherInterval = CronExpressionParser.parse('H * * * H', options);\n\n// Using the same seed will always return the same jitter\nconsole.log(otherInterval.stringify()); // \"12 * * * 4\"\n```\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details on:\n\n- Setting up the development environment\n- Code style and standards\n- Testing requirements\n- Pull request process\n- Reporting bugs and requesting features\n\nParticipation is governed by the [Code of Conduct](CODE_OF_CONDUCT.md).\n\n## Security\n\nTo report a security vulnerability, please follow the [Security Policy](SECURITY.md) rather than opening a public issue.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharrisiirak%2Fcron-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fharrisiirak%2Fcron-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharrisiirak%2Fcron-parser/lists"}