Repository: bradymholt/cRonstrue
Pull request #288 (2023-07-31 14:18:51)

add tzOffset
a new parameter, tzOffset, which allows you to get the time depending on the transmitted deviation from the UTC

khorevnikita: hi, done,

Patch:
diff --git a/README.md b/README.md
index c420d62..578c854 100644
--- a/README.md
+++ b/README.md
@@ -121,6 +121,7 @@ An options object can be passed as the second parameter to `cronstrue.toString`.
 - **monthStartIndexZero: boolean** - Wether to interpret January as `0` or `1`. (Default: false)
 - **use24HourTimeFormat: boolean** - If true, descriptions will use a [24-hour clock](https://en.wikipedia.org/wiki/24-hour_clock) (Default: false but some translations will default to true)
 - **locale: string** - The locale to use (Default: "en")
+- **tzOffset: number** - Your time offset (in hours) from UTC (Default: 0)
 
 ## i18n
 
diff --git a/src/expressionDescriptor.ts b/src/expressionDescriptor.ts
index ee4ea50..d05b391 100644
--- a/src/expressionDescriptor.ts
+++ b/src/expressionDescriptor.ts
@@ -27,6 +27,7 @@ export class ExpressionDescriptor {
    *         monthStartIndexZero = false,
    *         use24HourTimeFormat = false,
    *         locale = 'en'
+   *         tzOffset = 0
    *     }={}]
    * @returns {string}
    */
@@ -39,6 +40,7 @@ export class ExpressionDescriptor {
       monthStartIndexZero = false,
       use24HourTimeFormat,
       locale = null,
+      tzOffset = 0
     }: Options = {}
   ): string {
     // We take advantage of Destructuring Object Parameters (and defaults) in TS/ES6 and now we will reassemble back to
@@ -51,6 +53,7 @@ export class ExpressionDescriptor {
       monthStartIndexZero: monthStartIndexZero,
       use24HourTimeFormat: use24HourTimeFormat,
       locale: locale,
+      tzOffset: tzOffset
     };
 
     let descripter = new ExpressionDescriptor(expression, options);
@@ -218,8 +221,8 @@ export class ExpressionDescriptor {
         return s == "0"
           ? ""
           : parseInt(s) < 20
-          ? this.i18n.atX0SecondsPastTheMinute(s)
-          : this.i18n.atX0SecondsPastTheMinuteGt20() || this.i18n.atX0SecondsPastTheMinute(s);
+            ? this.i18n.atX0SecondsPastTheMinute(s)
+            : this.i18n.atX0SecondsPastTheMinuteGt20() || this.i18n.atX0SecondsPastTheMinute(s);
       }
     );
 
@@ -246,8 +249,8 @@ export class ExpressionDescriptor {
           return s == "0" && hourExpression.indexOf("/") == -1 && secondsExpression == ""
             ? this.i18n.everyHour()
             : parseInt(s) < 20
-            ? this.i18n.atX0MinutesPastTheHour(s)
-            : this.i18n.atX0MinutesPastTheHourGt20() || this.i18n.atX0MinutesPastTheHour(s);
+              ? this.i18n.atX0MinutesPastTheHour(s)
+              : this.i18n.atX0MinutesPastTheHourGt20() || this.i18n.atX0MinutesPastTheHour(s);
         } catch (e) {
           return this.i18n.atX0MinutesPastTheHour(s);
         }
@@ -450,8 +453,8 @@ export class ExpressionDescriptor {
                 return s == "L"
                   ? this.i18n.lastDay()
                   : this.i18n.dayX0
-                  ? StringUtilities.format(this.i18n.dayX0(), s)
-                  : s;
+                    ? StringUtilities.format(this.i18n.dayX0(), s)
+                    : s;
               },
               (s) => {
                 return s == "1" ? this.i18n.commaEveryDay() : this.i18n.commaEveryX0Days(s);
@@ -630,7 +633,12 @@ export class ExpressionDescriptor {
   }
 
   protected formatTime(hourExpression: string, minuteExpression: string, secondExpression: string) {
-    let hour: number = parseInt(hourExpression);
+    let hour: number = parseInt(hourExpression) + (this.options.tzOffset ? this.options.tzOffset : 0);
+    if (hour >= 24) {
+      hour = hour - 24;
+    } else if (hour < 0) {
+      hour = 24 + hour;
+    }
     let period: string = "";
     let setPeriodBeforeTime: boolean = false;
     if (!this.options.use24HourTimeFormat) {
diff --git a/src/options.ts b/src/options.ts
index 6532732..ba95a9d 100644
--- a/src/options.ts
+++ b/src/options.ts
@@ -5,4 +5,5 @@ export interface Options {
   monthStartIndexZero?: boolean;
   use24HourTimeFormat?: boolean;
   locale?: string | null;
+  tzOffset?: number;
 }


Test patch:
diff --git a/test/cronstrue.ts b/test/cronstrue.ts
index da194f8..7e20248 100644
--- a/test/cronstrue.ts
+++ b/test/cronstrue.ts
@@ -153,6 +153,33 @@ describe("Cronstrue", function () {
   });
 
   describe("at", function () {
+    it("30 11 * * *", function () {
+      assert.equal(cronstrue.toString(this.test?.title as string,{
+        tzOffset:3
+      }), "At 02:30 PM");
+    });
+
+    it("30 11 * * *", function () {
+      assert.equal(cronstrue.toString(this.test?.title as string,{
+        tzOffset:3,
+        use24HourTimeFormat:true
+      }), "At 14:30");
+    });
+
+    it("30 3 * * *", function () {
+      assert.equal(cronstrue.toString(this.test?.title as string,{
+        tzOffset:-5,
+        use24HourTimeFormat:true
+      }), "At 22:30");
+    });
+
+    it("30 22 * * *", function () {
+      assert.equal(cronstrue.toString(this.test?.title as string,{
+        tzOffset:5,
+        use24HourTimeFormat:true
+      }), "At 03:30");
+    });
+
     it("30 11 * * *", function () {
       assert.equal(cronstrue.toString(this.test?.title as string), "At 11:30 AM");
     });