CRON JOB - Schedule Laravel command for different timezones - Manage for different regions

Viewed 2037

I'm using Laravel 5.8 and I like to auto-generate Invoices should be generated auto from Monday - Sunday. every Sunday night at 23:59:00

Let's say I have

"23:59:00 according to the region time zone".

Every store is related to a region, from the region table you'll find the time zone.

Questions How should I set the CRON JOB so I can generate invoices automatically according to the list of timezone I will get from the table?.

2 Answers

I have two suggestions;

if you want it to be static, define each command with the corresponding timezone from your database. Different timezones may have same time such as Europe/Amsterdam and Europe/Berlin

$schedule->command('generate:report')->timezone('one-of-the-timezone')->at('23:59');
$schedule->command('generate:report')->timezone('another-timezone')->at('23:59');
$schedule->command('generate:report')->timezone('yet-another-timezone')->at('23:59');
$schedule->command('generate:report')->timezone('some-other-timezone')->at('23:59');

If you want it to be dynamic, make it run every 59. min hourly and try to match it with the timezones via using hour.

$schedule->command('generate:report')->hourlyAt(59);

Inside your command class;

public function handle(TimezoneRepository $timezoneRepository)
{
    $timezones = $timezoneRepository->getUniqueTimezones(); // the unique timezones in your database - cache if you want

    foreach ($timezones as $timezone) {
        $date = Carbon::now($timezone); // Carbon::now('Europe/Moscow'), Carbon::now('Europe/Amsterdam') etc..

        if ($date->hour === 23) { // you are in that timezone
            $currentTimezone = $date->getTimezone();
            dispatch(new ReportMaker($currentTimezone)); // dispatch your report maker job
        }
    }
}

With the dynamic one, you will hit to multiple timezones at one iteration(when generate:report is executed) as i said at then beginning.

  • one of the possible flaw may be; if the execution of getting timezones etc takes more than 1 minute you may be in 00:00 instead of 23:59. It is better to calculate your report asynchronous and cache the list of timezones to not face problems while executing this loop.

  • Another possible flaw;

According to wiki;

A few zones are offset by 30 or 45 minutes (e.g. Newfoundland Standard Time is UTC−03:30, Nepal Standard Time is UTC+05:45, Indian Standard Time is UTC+05:30 and Myanmar Standard Time is UTC+06:30).

If you want to cover any of these, then it is better to execute the command like this

$schedule->command('generate:report')->cron('14,29,44,59 * * * *');

and make both hour and minute comparison such as;

$date->hour === 23 && $date->hour === 59

You can use the timezone() method in your task Schedulding

Using the timezone method, you may specify that a scheduled task's time should be interpreted within a given timezone:

$schedule->command('report:generate')
         ->timezone('America/New_York')
         ->at('02:00')
Related