cron-converter-u2q 1.0.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,14 +1,23 @@
1
1
  # cron-converter-u2q
2
2
 
3
- Easily convert cron expressions between Unix and Quartz formats with the `cron-converter-u2q` package
3
+ Easily work with cron expressions using the `cron-converter-u2q` package. Effortlessly convert between Unix and Quartz formats and describe cron schedules in plain language for better understanding and usability.
4
4
 
5
5
  ![example event parameter](https://github.com/rahu619/cron-converter-u2q/actions/workflows/integration.yml/badge.svg?branch=main)
6
- ![example event parameter](https://github.com/rahu619/cron-converter-u2q/actions/workflows/release.yml/badge.svg?branch=main)
6
+ ![example event parameter](https://github.com/rahu619/cron-converter-u2q/actions/workflows/release.yml/badge.svg?event=workflow_dispatch)
7
7
  [![NPM version](https://badge.fury.io/js/cron-converter-u2q.svg)](https://www.npmjs.com/package/cron-converter-u2q)
8
8
 
9
9
  ### Features
10
10
 
11
- :arrows_counterclockwise: Two-way conversion: from Unix to Quartz and Quartz to Unix.
11
+ :arrows_counterclockwise: **Two-way conversion**
12
+
13
+ Effortlessly convert cron expressions:
14
+ - From Unix to Quartz
15
+ - From Quartz to Unix
16
+
17
+ :memo: **Human-readable Descriptions**
18
+
19
+ Translate cron schedules into plain, understandable text:
20
+ - Example: `*/5 * * * *` -> "Every 5 minutes"
12
21
 
13
22
  ### Installation
14
23
 
@@ -40,21 +49,51 @@ If you're using ES6 Modules
40
49
  import { CronConverterU2QModule as c2q } from "cron-converter-u2q";
41
50
  ```
42
51
 
43
- Convert from Unix to Quartz
52
+ ### Conversion Methods
53
+
54
+ #### Convert from Unix to Quartz:
44
55
 
45
56
  ```javascript
46
57
  const quartzExpression = c2q.unixToQuartz("5 * * * *");
47
58
  ```
48
59
 
49
- Convert from Quartz to Unix
60
+ #### Convert from Quartz to Unix:
50
61
 
51
62
  ```javascript
52
63
  const unixExpression = c2q.quartzToUnix("* */5 * ? * * *");
53
64
  ```
54
65
 
66
+ ### Description Methods
67
+
68
+ You can now generate human-readable descriptions for Unix and Quartz cron expressions.
69
+
70
+ #### Describe Unix Cron Expressions:
71
+
72
+ ```javascript
73
+ const description = c2q.describeUnix("5 * * * *");
74
+ console.log(description); // Outputs: "Every 5 minutes"
75
+ ```
76
+
77
+ #### Describe Quartz Cron Expressions:
78
+
79
+ ```javascript
80
+ const description = c2q.describeQuartz("0 0 8 * * ?");
81
+ console.log(description); // Outputs: "At 8 o'clock"
82
+ ```
83
+
84
+ ### Contribution Guide
85
+ 1. **Fork the repository.**
86
+ 2. **Create a feature branch:**
87
+ ```bash
88
+ git checkout -b feature/xxxx
89
+ ```
90
+ 3. **Commit changes:**
91
+ 4. **Push the branch:**
92
+ 5. **Open a Pull Request.**
93
+
55
94
  ### Development Notice
56
95
 
57
- This package is still under active development. Some methods and features might not be stable yet. We're working diligently to improve and stabilize the package. Any feedback, suggestions, or contributions are highly appreciated!
96
+ Any feedback, suggestions, or contributions are highly appreciated!
58
97
 
59
98
  ## License
60
99
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cron-converter-u2q",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Converts cron expressions between unix and quartz formats",
5
5
  "main": "lib/index.js",
6
6
  "types": "types/index.d.ts",
@@ -1,131 +1,142 @@
1
- import { CronConverterU2Q as converter, CronDescriberU2Q as describer } from '../index';
1
+ import {
2
+ CronConverterU2Q as converter,
3
+ CronDescriberU2Q as describer,
4
+ } from "../index";
2
5
 
3
6
  //Basic suite of tests
4
- describe('Unix2Quartz Conversion', () => {
5
-
6
- test('Every minute', () => {
7
- const result = converter.unixToQuartz('* * * * *');
8
- expect(result).toBe("0 * * ? * *");
9
- });
10
-
11
- test('Every 5 minutes', () => {
12
- const result = converter.unixToQuartz('*/5 * * * *');
13
- expect(result).toBe("0 */5 * ? * *");
14
- });
15
-
16
- test('Every hour at minute 30', () => {
17
- const result = converter.unixToQuartz('30 * * * *');
18
- expect(result).toBe("0 30 * ? * *");
19
- });
20
-
21
- test('Everyday at 12pm', () => {
22
- const result = converter.unixToQuartz('0 12 * * *');
23
- expect(result).toBe("0 0 12 ? * *");
24
- });
25
-
26
- test('Every Monday at 12pm', () => {
27
- const result = converter.unixToQuartz('0 12 * * 1');
28
- expect(result).toBe("0 0 12 ? * 1");
29
- });
30
-
31
- test('Every 10th day of the month', () => {
32
- const result = converter.unixToQuartz('0 0 10 * *');
33
- expect(result).toBe("0 0 0 10 * ?");
34
- });
35
-
36
- test('Every January 1st at 12am', () => {
37
- const result = converter.unixToQuartz('0 0 1 1 *');
38
- expect(result).toBe("0 0 0 1 1 ?");
39
- });
40
-
41
- test('Every last day of the month', () => {
42
- const result = converter.unixToQuartz('59 23 L * *');
43
- expect(result).toBe("0 59 23 L * ?");
44
- });
45
-
46
- test('Every day at 2:30 AM', () => {
47
- const result = converter.unixToQuartz('30 2 * * *');
48
- expect(result).toBe('0 30 2 ? * *');
49
- });
50
-
51
- test('Every Monday at 2:30 AM', () => {
52
- const result = converter.unixToQuartz('30 2 * * 1');
53
- expect(result).toBe('0 30 2 ? * 1');
54
- });
55
-
56
- test('Every day at 1:00 AM and 1:00 PM', () => {
57
- const result = converter.unixToQuartz('0 1,13 * * *');
58
- expect(result).toBe('0 0 1,13 ? * *');
59
- });
60
-
61
- test('Every 15 minutes', () => {
62
- const result = converter.unixToQuartz('*/15 * * * *');
63
- expect(result).toBe('0 */15 * ? * *');
64
- });
65
-
66
- //Include
67
- // test('Last day of every month at 4:45 PM conversion', () => {
68
- // const result = converter.unixToQuartz('45 16 28-31 * *');
69
- // expect(result).toBe('45 16 L * ?');
70
- // });
71
-
72
- // test('Last Sunday of every month at 4:45 PM conversion', () => {
73
- // const result = converter.unixToQuartz('45 16 22-31 * 0');
74
- // expect(result).toBe('45 16 ? * 7L');
75
- // });
76
-
77
- // test('Second Wednesday of every month at 1:00 AM conversion', () => {
78
- // const result = converter.quartzToUnix('0 1 ? * 3#2');
79
- // expect(result).toBe('Not directly possible without additional logic');
80
- // });
81
-
82
- // test('Every last Friday of the month conversion', () => {
83
- // const result = converter.unixToQuartz('0 0 * * 5'); //Find equivalent unix expression
84
- // expect(result).toBe("0 0 0 ? * 5L");
85
- // });
86
-
7
+ describe("Unix2Quartz Conversion", () => {
8
+ test("Every minute", () => {
9
+ const result = converter.unixToQuartz("* * * * *");
10
+ expect(result).toBe("0 * * ? * *");
11
+ });
12
+
13
+ test("Every 5 minutes", () => {
14
+ const result = converter.unixToQuartz("*/5 * * * *");
15
+ expect(result).toBe("0 */5 * ? * *");
16
+ });
17
+
18
+ test("Every hour at minute 30", () => {
19
+ const result = converter.unixToQuartz("30 * * * *");
20
+ expect(result).toBe("0 30 * ? * *");
21
+ });
22
+
23
+ test("Everyday at 12pm", () => {
24
+ const result = converter.unixToQuartz("0 12 * * *");
25
+ expect(result).toBe("0 0 12 ? * *");
26
+ });
27
+
28
+ test("Every Monday at 12pm", () => {
29
+ const result = converter.unixToQuartz("0 12 * * 1");
30
+ expect(result).toBe("0 0 12 ? * 1");
31
+ });
32
+
33
+ test("Every 10th day of the month", () => {
34
+ const result = converter.unixToQuartz("0 0 10 * *");
35
+ expect(result).toBe("0 0 0 10 * ?");
36
+ });
37
+
38
+ test("Every January 1st at 12am", () => {
39
+ const result = converter.unixToQuartz("0 0 1 1 *");
40
+ expect(result).toBe("0 0 0 1 1 ?");
41
+ });
42
+
43
+ test("Every last day of the month", () => {
44
+ const result = converter.unixToQuartz("59 23 L * *");
45
+ expect(result).toBe("0 59 23 L * ?");
46
+ });
47
+
48
+ test("Every day at 2:30 AM", () => {
49
+ const result = converter.unixToQuartz("30 2 * * *");
50
+ expect(result).toBe("0 30 2 ? * *");
51
+ });
52
+
53
+ test("Every Monday at 2:30 AM", () => {
54
+ const result = converter.unixToQuartz("30 2 * * 1");
55
+ expect(result).toBe("0 30 2 ? * 1");
56
+ });
57
+
58
+ test("Every day at 1:00 AM and 1:00 PM", () => {
59
+ const result = converter.unixToQuartz("0 1,13 * * *");
60
+ expect(result).toBe("0 0 1,13 ? * *");
61
+ });
62
+
63
+ test("Every 15 minutes", () => {
64
+ const result = converter.unixToQuartz("*/15 * * * *");
65
+ expect(result).toBe("0 */15 * ? * *");
66
+ });
67
+
68
+ //Include
69
+ // test('Last day of every month at 4:45 PM conversion', () => {
70
+ // const result = converter.unixToQuartz('45 16 28-31 * *');
71
+ // expect(result).toBe('45 16 L * ?');
72
+ // });
73
+
74
+ // test('Last Sunday of every month at 4:45 PM conversion', () => {
75
+ // const result = converter.unixToQuartz('45 16 22-31 * 0');
76
+ // expect(result).toBe('45 16 ? * 7L');
77
+ // });
78
+
79
+ // test('Second Wednesday of every month at 1:00 AM conversion', () => {
80
+ // const result = converter.quartzToUnix('0 1 ? * 3#2');
81
+ // expect(result).toBe('Not directly possible without additional logic');
82
+ // });
83
+
84
+ // test('Every last Friday of the month conversion', () => {
85
+ // const result = converter.unixToQuartz('0 0 * * 5'); //Find equivalent unix expression
86
+ // expect(result).toBe("0 0 0 ? * 5L");
87
+ // });
87
88
  });
88
89
 
89
-
90
- describe('Quartz2Unix Conversion', () => {
91
-
92
- test('Every 5 minutes conversion', () => {
93
- const result = converter.quartzToUnix('0 */5 * ? * *');
94
- expect(result).toBe("*/5 * * * *");
95
- });
96
-
97
- test('Everyday at 12pm conversion', () => {
98
- const result = converter.quartzToUnix('0 0 12 ? * *');
99
- expect(result).toBe("0 12 * * *");
100
- });
101
-
102
- test('Every Monday at 12pm conversion', () => {
103
- const result = converter.quartzToUnix('0 0 12 ? * 1');
104
- expect(result).toBe("0 12 * * 1");
105
- });
106
-
107
- test('Every 10th day of the month conversion', () => {
108
- const result = converter.quartzToUnix('0 0 0 10 * ?');
109
- expect(result).toBe("0 0 10 * *");
110
- });
111
-
112
- test('Every January 1st at 12am conversion', () => {
113
- const result = converter.quartzToUnix('0 0 0 1 1 ?');
114
- expect(result).toBe("0 0 1 1 *");
115
- });
116
-
117
- test('Every last day of the month conversion', () => {
118
- const result = converter.quartzToUnix('0 59 23 L * ?');
119
- expect(result).toBe("59 23 L * *");
120
- });
90
+ describe("Quartz2Unix Conversion", () => {
91
+ test("Every 5 minutes conversion", () => {
92
+ const result = converter.quartzToUnix("0 */5 * ? * *");
93
+ expect(result).toBe("*/5 * * * *");
94
+ });
95
+
96
+ test("Everyday at 12pm conversion", () => {
97
+ const result = converter.quartzToUnix("0 0 12 ? * *");
98
+ expect(result).toBe("0 12 * * *");
99
+ });
100
+
101
+ test("Every Monday at 12pm conversion", () => {
102
+ const result = converter.quartzToUnix("0 0 12 ? * 1");
103
+ expect(result).toBe("0 12 * * 1");
104
+ });
105
+
106
+ test("Every 10th day of the month conversion", () => {
107
+ const result = converter.quartzToUnix("0 0 0 10 * ?");
108
+ expect(result).toBe("0 0 10 * *");
109
+ });
110
+
111
+ test("Every January 1st at 12am conversion", () => {
112
+ const result = converter.quartzToUnix("0 0 0 1 1 ?");
113
+ expect(result).toBe("0 0 1 1 *");
114
+ });
115
+
116
+ test("Every last day of the month conversion", () => {
117
+ const result = converter.quartzToUnix("0 59 23 L * ?");
118
+ expect(result).toBe("59 23 L * *");
119
+ });
121
120
  });
122
121
 
123
-
124
-
125
- // describe('Unix Description', () => {
126
-
127
- // test('Describe every 5 minutes', () => {
128
- // const result = describer.describe('*/5 * * * *');
129
- // expect(result).toBe("Every 5 minutes");
130
- // });
131
- // });
122
+ describe("Description", () => {
123
+ test("Describe every 5 minutes (Unix)", () => {
124
+ const result = describer.describeUnix("*/5 * * * *");
125
+ expect(result).toBe("Every 5 minutes");
126
+ });
127
+
128
+ test("Describe every 5 minutes (Quartz)", () => {
129
+ const result = describer.describeQuartz("0 */5 * * * *");
130
+ expect(result).toBe("Every 5 minutes");
131
+ });
132
+
133
+ test("Describe daily at 8:00 AM (Unix)", () => {
134
+ const result = describer.describeUnix("0 8 * * *");
135
+ expect(result).toBe("At 8 o'clock");
136
+ });
137
+
138
+ test("Describe daily at 8:00 AM (Quartz)", () => {
139
+ const result = describer.describeQuartz("0 0 8 * * *");
140
+ expect(result).toBe("At 8 o'clock");
141
+ });
142
+ });
package/src/describer.ts CHANGED
@@ -1,58 +1,156 @@
1
- import { ExpressionHelper as helper } from './helper';
1
+ import { ExpressionHelper as helper } from "./helper";
2
2
 
3
3
  export class CronDescriberU2Q {
4
+ /**
5
+ * Generates a human-readable description for a Unix-style cron expression.
6
+ *
7
+ * Unix-style cron expressions consist of 5 parts:
8
+ * - Minute (0-59)
9
+ * - Hour (0-23)
10
+ * - Day of Month (1-31)
11
+ * - Month (1-12)
12
+ * - Day of Week (0-6, where 0 = Sunday)
13
+ * @param unixExpression - A string containing the Unix-style cron expression.
14
+ * @returns A human-readable description or an error message if invalid.
15
+ */
16
+ public static describeUnix(unixExpression: string): string {
17
+ try {
18
+ const parts = helper.GetExpressionParts(unixExpression);
19
+ if (parts.length !== 5) {
20
+ return "Invalid Unix cron expression";
21
+ }
4
22
 
5
- public static describe(expression: string): string {
6
- const [second, min, hour, dom, month, dow] = helper.GetExpressionParts(expression);
7
- return `${this.describeSecond(second)} ${this.describeMinute(min)} ${this.describeHour(hour)} ${this.describeDayOfMonth(dom)} ${this.describeMonth(month)} ${this.describeDayOfWeek(dow)}`.trim();
8
- }
23
+ const [min, hour, dom, month, dow] = parts;
9
24
 
10
- // #region Standard cron description logic
25
+ const descriptions = [
26
+ this.describeMinute(min, true),
27
+ this.describeHour(hour),
28
+ this.describeDayOfMonth(dom),
29
+ this.describeMonth(month),
30
+ this.describeDayOfWeek(dow),
31
+ ];
11
32
 
12
- private static describeSecond(second: string): string {
13
- if (second === '*') return 'Every second';
14
- if (second.startsWith('*/')) return `Every ${second.split('/')[1]} seconds`;
15
- return `At second ${second}`;
33
+ return this.combineDescriptions(descriptions);
34
+ } catch (error) {
35
+ return "Invalid Unix cron expression";
16
36
  }
37
+ }
17
38
 
18
- private static describeMinute(min: string): string {
19
- if (min === '*') return 'Every minute';
20
- if (min.startsWith('*/')) return `Every ${min.split('/')[1]} minutes`;
21
- return `At minute ${min}`;
22
- }
39
+ /**
40
+ * Generates a human-readable description for a Quartz-style cron expression.
41
+ *
42
+ * Quartz-style cron expressions consist of 6 parts:
43
+ * - Second (0-59)
44
+ * - Minute (0-59)
45
+ * - Hour (0-23)
46
+ * - Day of Month (1-31)
47
+ * - Month (1-12)
48
+ * - Day of Week (0-6, where 0 = Sunday)
49
+ * @param quartzExpression - A string containing the Quartz-style cron expression.
50
+ * @returns A human-readable description or an error message if invalid.
51
+ */
52
+ public static describeQuartz(quartzExpression: string): string {
53
+ try {
54
+ const parts = helper.GetExpressionParts(quartzExpression);
55
+ if (parts.length !== 6) {
56
+ return "Invalid Quartz cron expression";
57
+ }
23
58
 
24
- private static describeHour(hour: string): string {
25
- if (hour === '*') return 'of every hour';
26
- if (hour.startsWith('*/')) return `Every ${hour.split('/')[1]} hours`;
27
- return `At ${hour} o'clock`;
28
- }
59
+ const [second, min, hour, dom, month, dow] = parts;
29
60
 
30
- private static describeDayOfMonth(dom: string): string {
31
- if (dom === '*') return 'on every day';
32
- return `on the ${this.ordinalSuffix(Number(dom))} of the month`;
33
- }
61
+ const descriptions = [
62
+ this.describeSecond(second, true),
63
+ this.describeMinute(min, true),
64
+ this.describeHour(hour),
65
+ this.describeDayOfMonth(dom),
66
+ this.describeMonth(month),
67
+ this.describeDayOfWeek(dow),
68
+ ];
34
69
 
35
- private static describeMonth(month: string): string {
36
- if (month === '*') return 'of every month';
37
- const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
38
- return `in ${months[Number(month) - 1]}`;
70
+ return this.combineDescriptions(descriptions);
71
+ } catch (error) {
72
+ return "Invalid Quartz cron expression";
39
73
  }
74
+ }
40
75
 
41
- private static describeDayOfWeek(dow: string): string {
42
- if (dow === '*') return '';
43
- const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
44
- return `on ${days[Number(dow)]}`;
45
- }
76
+ private static describeSecond(second: string, suppressZero = false): string {
77
+ if (second === "*" || (suppressZero && second === "0")) return ""; // Suppress default
78
+ if (second.startsWith("*/")) return `Every ${second.split("/")[1]} seconds`;
79
+ return `At second ${second}`;
80
+ }
46
81
 
47
- private static ordinalSuffix(i: number): string {
48
- const j = i % 10;
49
- const k = i % 100;
50
- if (j == 1 && k != 11) return i + "st";
51
- if (j == 2 && k != 12) return i + "nd";
52
- if (j == 3 && k != 13) return i + "rd";
53
- return i + "th";
54
- }
82
+ private static describeMinute(min: string, suppressZero = false): string {
83
+ if (min === "*" || (suppressZero && min === "0")) return ""; // Suppress default
84
+ if (min.startsWith("*/")) return `Every ${min.split("/")[1]} minutes`;
85
+ return `At minute ${min}`;
86
+ }
87
+
88
+ private static describeHour(hour: string): string {
89
+ if (hour === "*") return ""; // Default behavior
90
+ if (hour.startsWith("*/")) return `Every ${hour.split("/")[1]} hours`;
91
+ return `At ${hour} o'clock`;
92
+ }
93
+
94
+ private static describeDayOfMonth(dom: string): string {
95
+ if (dom === "*") return ""; // Default behavior
96
+ return `on the ${this.ordinalSuffix(Number(dom))} of the month`;
97
+ }
98
+
99
+ private static describeMonth(month: string): string {
100
+ if (month === "*") return ""; // Default behavior
101
+ const months = [
102
+ "January",
103
+ "February",
104
+ "March",
105
+ "April",
106
+ "May",
107
+ "June",
108
+ "July",
109
+ "August",
110
+ "September",
111
+ "October",
112
+ "November",
113
+ "December",
114
+ ];
115
+ const monthIndex = Number(month) - 1;
116
+ return months[monthIndex]
117
+ ? `in ${months[monthIndex]}`
118
+ : "Invalid month value";
119
+ }
120
+
121
+ private static describeDayOfWeek(dow: string): string {
122
+ if (dow === "*") return ""; // Default behavior
123
+ const days = [
124
+ "Sunday",
125
+ "Monday",
126
+ "Tuesday",
127
+ "Wednesday",
128
+ "Thursday",
129
+ "Friday",
130
+ "Saturday",
131
+ ];
132
+ const dayIndex = Number(dow);
133
+ return days[dayIndex]
134
+ ? `on ${days[dayIndex]}`
135
+ : "Invalid day of week value";
136
+ }
55
137
 
56
- //#endregion
138
+ private static ordinalSuffix(i: number): string {
139
+ if (i <= 0) return "Invalid day";
140
+ const j = i % 10;
141
+ const k = i % 100;
142
+ if (j === 1 && k !== 11) return i + "st";
143
+ if (j === 2 && k !== 12) return i + "nd";
144
+ if (j === 3 && k !== 13) return i + "rd";
145
+ return i + "th";
146
+ }
57
147
 
58
- }
148
+ private static combineDescriptions(descriptions: string[]): string {
149
+ const filteredDescriptions = descriptions.filter(
150
+ (part) => part && part !== ""
151
+ );
152
+ return filteredDescriptions.length > 0
153
+ ? filteredDescriptions.join(" ").trim()
154
+ : "Every moment"; // Default if all parts are wildcards
155
+ }
156
+ }
package/types/index.d.ts CHANGED
@@ -2,5 +2,7 @@ declare module 'cron-converter-u2q' {
2
2
  export const CronConverterU2QModule: {
3
3
  unixToQuartz(unixExpression: string): string;
4
4
  quartzToUnix(quartzExpression: string): string;
5
+ describeUnix(unixExpression: string): string;
6
+ describeQuartz(quartzExpression: string): string
5
7
  }
6
8
  }