【问题标题】:Celery periodic tasks timezones芹菜定期任务时区
【发布时间】:2014-04-28 15:03:33
【问题描述】:

我有一些周期性任务需要在每个月的第一天午夜运行,但需要在客户端的特定时区运行。我正在尝试将所有内容都保留为 UTC,所以我有

CELERY_ENABLE_UTC = True

因此,如果我有多个任务,每个任务都需要在特定时区的午夜运行,那么使用 Celery 执行此操作的最干净的方法是什么?例如,在各自的时区午夜运行这 2 个任务?

#for Client 1, this needs to run at Midnight EST (US/Eastern)
schedule1 = crontab(day_of_month=1, 
                     hour = 0, 
                     minute = 0
                   )
#for Client 2, this needs to run at Midnight PST (US/Pacific)
schedule1 = crontab(day_of_month=1, 
                     hour = 0, 
                     minute = 0
                   )

【问题讨论】:

    标签: python celery


    【解决方案1】:

    crontab() 函数仅接受 minutehourday_of_weekday_of_monthday_of_yearmonth_of_year 作为参数。如果您想在午夜为不同的时区运行任务,您必须根据 UTC(或 Celery 配置中设置的任何其他默认时区)为它们计算时间。

    from datetime import datetime
    from pytz import timezone
    
    def get_utc_for_midnight_in_timezone(tzstring):
        local_midnight = datetime(2000, 1, 1, 0, 0, 0, tzinfo=timezone(tzstring))
        utc = local_midnight.astimezone(timezone('UTC'))
        return {
            'day_of_month': utc.day,
            'hour': utc.hour,
            'minute': utc.minute
        }
    

    你可以这样使用上面的函数:

    client1_schedule = crontab(**get_utc_for_midnight_in_timezone('US/Pacific'))
    client2_schedule = crontab(**get_utc_for_midnight_in_timezone('US/Eastern'))
    

    【讨论】:

    • 是的,这就是我正在做的事情。问题是,只要有该死的夏令时更改,它就会不同步。它将关闭一个小时。
    • 所以也许你可以使用timezone.localize() 方法和is_dst 参数。唯一的问题是您必须自己确定 is_dst 在什么日期是 True 或 False。
    • 是的,我不知道如何确定日期是否在 dst 中。我想我可能只是有另一个每小时运行并设定时间的芹菜工作
    【解决方案2】:

    尝试crontab 中的nowfun 参数,它采用datetime 对象

    Celery beat - different time zone per task

    【讨论】: