DEV Community

Cover image for You Are Scheduling Your Node Cron Jobs Wrong. Fix It Now!
Sohail Jafri
Sohail Jafri

Posted on • Updated on

You Are Scheduling Your Node Cron Jobs Wrong. Fix It Now!

So, I had a cron server running multiple tasks. I had a task lets call to it x-task that was supposed to run every day 5.00 PM and few others that supposed to run at different times. I had scheduled them using node-cron package.

But the problem was that x-task was running multiple times in a day instead of one time in a at @5.00 PM. I was confused as I had took cron time syntax from cron guru it was 0 17 * * * link1, link2. Lets see what was the problem and how we can prevent it.

Also I have attached a cool cronjob code snippet for you to use for all your cron jobs. And here is the guide to setup cron in node.js

Prerequisites

  • Basic knowledge of JavaScript and Node.js
  • Basic knowledge of npm
  • Basic knowledge of Node.js and Express.js
  • Basic knowledge of cronjob schedule

So If you dont know about cronjob schedule you can learn about it here

Lets break down the task into smaller steps.

  1. Identify the problem
  2. Fixing the problem
  3. Optimizing the code
  4. Conclusion

Step 1: Identify the problem

So the problem was node-cron uses uses 6 parameters to define the schedule but in general cronjob uses 5 parameters. Please see below for the explanation of the parameters.

Node-cron parameters

  1. Seconds
  2. Minutes
  3. Hours
  4. Day of the month
  5. Month
  6. Day of the week

General cronjob parameters

  1. Minutes
  2. Hours
  3. Day of the month
  4. Month
  5. Day of the week

You can see that node-cron uses extra parameter in starting which is seconds. So when you define a cronjob schedule in node-cron you have to provide 6 parameters.

Step 2: Fixing the problem

So the problem was that I was using 0 17 * * * as a cronjob schedule which was wrong. The correct schedule should be 0 0 17 * * *. So the correct schedule for the task to run at 5.00 PM should be 0 0 17 * * *. So I changed the schedule and the task was running only once in a day.

Cool cronjob code snippet

Copy the below code snippet and paste it in any file in your project. You can use this code snippet to generate cron expressions for different time intervals with 6 fields for node-cron without scheduling the task wrong ever again 😄. Also If your not fimilar with typescript I have attached JavaScript version.

TypeScript Version

/**
 * @description Generate cron expressions for different time intervals with 6 fields for node-cron
 */
export class CronTime {
  // Generate a cron expression for every month on a specified day
  // Example: everyMonthOn(15) -> "0 0 0 15 * *"
  static everyMonthOn(day: number = 1, hour: number = 0): string {
    if (day < 1 || day > 31) {
      throw new Error('Day must be between 1 and 31')
    }
    if (hour < 0 || hour > 23) {
      throw new Error('Hour must be between 0 and 23')
    }
    return `0 0 ${hour} ${day} * *`
  }

  // Generate a cron expression for every day of the week at a specified hour
  // Example: everyDay(3) -> "0 0 3 * * *"
  static everyDay(hour: number = 0): string {
    if (hour < 0 || hour > 23) {
      throw new Error('Hour must be between 0 and 23')
    }
    return `0 0 ${hour} * * *`
  }

  // Generate a cron expression for every Monday at a specified hour
  // Example: everyMonday(2) -> "0 0 2 * * 1"
  static everyMonday(hour: number = 0): string {
    return CronTime.everyWeekday(1, hour)
  }

  // Generate a cron expression for every Tuesday at a specified hour
    // Example: everyTuesday(3) -> "0 0 3 * * 2"
  static everyTuesday(hour: number = 0): string {
    return CronTime.everyWeekday(2, hour)
  }

  // Generate a cron expression for every Wednesday at a specified hour
    // Example: everyWednesday(4) -> "0 0 4 * * 3"
  static everyWednesday(hour: number = 0): string {
    return CronTime.everyWeekday(3, hour)
  }

  // Generate a cron expression for every Thursday at a specified hour
    // Example: everyThursday(5) -> "0 0 5 * * 4"
  static everyThursday(hour: number = 0): string {
    return CronTime.everyWeekday(4, hour)
  }

  // Generate a cron expression for every Friday at a specified hour
    // Example: everyFriday(6) -> "0 0 6 * * 5"
  static everyFriday(hour: number = 0): string {
    return CronTime.everyWeekday(5, hour)
  }

  // Generate a cron expression for every Saturday at a specified hour
    // Example: everySaturday(7) -> "0 0 7 * * 6"
  static everySaturday(hour: number = 0): string {
    return CronTime.everyWeekday(6, hour)
  }

  // Generate a cron expression for every Sunday at a specified hour
    // Example: everySunday(8) -> "0 0 8 * * 0"
  static everySunday(hour: number = 0): string {
    return CronTime.everyWeekday(0, hour)
  }

  // Helper method for generating a cron expression for a specific weekday
  private static everyWeekday(dayOfWeek: number, hour: number): string {
    if (hour < 0 || hour > 23) {
      throw new Error('Hour must be between 0 and 23')
    }
    if (dayOfWeek < 0 || dayOfWeek > 6) {
      throw new Error('Day of week must be between 0 (Sunday) and 6 (Saturday)')
    }
    return `0 0 ${hour} * * ${dayOfWeek}`
  }

  // Generate a cron expression for every hour
    static everyHour(): string {
    return '0 0 * * * *'
  }

  // Generate a cron expression for every minute
  static everyMinute(): string {
    return '0 * * * * *'
  }

    // Generate a cron expression for every N seconds
    static everyNSeconds(seconds: number): string {
        if (seconds <= 0 || seconds > 59) {
            throw new Error('Seconds must be between 1 and 59')
        }
        return `*/${seconds} * * * * *`
    }

  // Generate a cron expression for every N minutes
    // Example: everyNMinutes(15) -> "0 */15 * * * *"
  static everyNMinutes(minutes: number): string {
    if (minutes <= 0 || minutes > 59) {
      throw new Error('Minutes must be between 1 and 59')
    }
    return `0 */${minutes} * * * *`
  }

  // Generate a cron expression for every N hours
    // Example: everyNHours(3) -> "0 0 */3 * * *"
  static everyNHours(hours: number): string {
    if (hours <= 0 || hours > 23) {
      throw new Error('Hours must be between 1 and 23')
    }
    return `0 0 */${hours} * * *`
  }

  // Generate a cron expression for a specific time on a specific day of the week
    // Example: atHourOnDayOfWeek(3, 5) -> "0 0 3 * * 5"
  static atHourOnDayOfWeek(hour: number, dayOfWeek: number): string {
    return CronTime.everyWeekday(dayOfWeek, hour)
  }

  // Generate a cron expression for a specific time every month on a specific date
    // Example: atHourOnDayOfMonth(15, 5) -> "0 0 5 15 * *"
  static atHourOnDayOfMonth(day: number, hour: number): string {
    return CronTime.everyMonthOn(day, hour)
  }
}

Enter fullscreen mode Exit fullscreen mode

JavaScript Version

/**
 * @description Generate cron expressions for different time intervals with 6 fields for node-cron
 */
class CronTime {
  // Generate a cron expression for every month on a specified day
  // Example: everyMonthOn(15) -> "0 0 0 15 * *"
  static everyMonthOn(day = 1, hour = 0) {
    if (day < 1 || day > 31) {
      throw new Error('Day must be between 1 and 31')
    }
    if (hour < 0 || hour > 23) {
      throw new Error('Hour must be between 0 and 23')
    }
    return `0 0 ${hour} ${day} * *`
  }

  // Generate a cron expression for every day of the week at a specified hour
  // Example: everyDay(3) -> "0 0 3 * * *"
  static everyDay(hour = 0) {
    if (hour < 0 || hour > 23) {
      throw new Error('Hour must be between 0 and 23')
    }
    return `0 0 ${hour} * * *`
  }

  // Generate a cron expression for every Monday at a specified hour
  // Example: everyMonday(2) -> "0 0 2 * * 1"
  static everyMonday(hour = 0) {
    return CronTime.everyWeekday(1, hour)
  }

  // Generate a cron expression for every Tuesday at a specified hour
  // Example: everyTuesday(3) -> "0 0 3 * * 2"
  static everyTuesday(hour = 0) {
    return CronTime.everyWeekday(2, hour)
  }

  // Generate a cron expression for every Wednesday at a specified hour
  // Example: everyWednesday(4) -> "0 0 4 * * 3"
  static everyWednesday(hour = 0) {
    return CronTime.everyWeekday(3, hour)
  }

  // Generate a cron expression for every Thursday at a specified hour
  // Example: everyThursday(5) -> "0 0 5 * * 4"
  static everyThursday(hour = 0) {
    return CronTime.everyWeekday(4, hour)
  }

  // Generate a cron expression for every Friday at a specified hour
  // Example: everyFriday(6) -> "0 0 6 * * 5"
  static everyFriday(hour = 0) {
    return CronTime.everyWeekday(5, hour)
  }

  // Generate a cron expression for every Saturday at a specified hour
  // Example: everySaturday(7) -> "0 0 7 * * 6"
  static everySaturday(hour = 0) {
    return CronTime.everyWeekday(6, hour)
  }

  // Generate a cron expression for every Sunday at a specified hour
  // Example: everySunday(8) -> "0 0 8 * * 0"
  static everySunday(hour = 0) {
    return CronTime.everyWeekday(0, hour)
  }

  // Helper method for generating a cron expression for a specific weekday
  static everyWeekday(dayOfWeek, hour) {
    if (hour < 0 || hour > 23) {
      throw new Error('Hour must be between 0 and 23')
    }
    if (dayOfWeek < 0 || dayOfWeek > 6) {
      throw new Error('Day of week must be between 0 (Sunday) and 6 (Saturday)')
    }
    return `0 0 ${hour} * * ${dayOfWeek}`
  }

  // Generate a cron expression for every hour
  static everyHour() {
    return '0 0 * * * *'
  }

  // Generate a cron expression for every minute
  static everyMinute() {
    return '0 * * * * *'
  }

  // Generate a cron expression for every N seconds
  static everyNSeconds(seconds) {
    if (seconds <= 0 || seconds > 59) {
      throw new Error('Seconds must be between 1 and 59')
    }
    return `*/${seconds} * * * * *`
  }

  // Generate a cron expression for every N minutes
  // Example: everyNMinutes(15) -> "0 */15 * * * *"
  static everyNMinutes(minutes) {
    if (minutes <= 0 || minutes > 59) {
      throw new Error('Minutes must be between 1 and 59')
    }
    return `0 */${minutes} * * * *`
  }

  // Generate a cron expression for every N hours
  // Example: everyNHours(3) -> "0 0 */3 * * *"
  static everyNHours(hours) {
    if (hours <= 0 || hours > 23) {
      throw new Error('Hours must be between 1 and 23')
    }
    return `0 0 */${hours} * * *`
  }

  // Generate a cron expression for a specific time on a specific day of the week
  // Example: atHourOnDayOfWeek(3, 5) -> "0 0 3 * * 5"
  static atHourOnDayOfWeek(hour, dayOfWeek) {
    return CronTime.everyWeekday(dayOfWeek, hour)
  }

  // Generate a cron expression for a specific time every month on a specific date
  // Example: atHourOnDayOfMonth(15, 5) -> "0 0 5 15 * *"
  static atHourOnDayOfMonth(day, hour) {
    return CronTime.everyMonthOn(day, hour)
  }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

So, I hope you find this article helpful. If you have any questions, feel free to ask in the comments below or contact me on Twitter/X @thesohailjafri.

Also save this article for future reference so you dont schedule your cron jobs wrong ever again 😄.

Top comments (0)