Search code examples
laravellaravel-5cronjobs

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


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?.


Solution

  • 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