在不同时区安排
Schedule in different time zone
我正在开发一个 Django
项目。
我想自动同步 classes。
我的代码:
from datetime import timedelta
from celery.schedules import crontab
CELERYBEAT_SCHEDULE = {
'sync-classes': {
'task': 'scheduler.tasks.sync_classes',
'schedule': crontab(hour='0', minute=0),
}
CELERY_ENABLE_UTC = False
CELERY_TIMEZONE = 'Europe/London'
它适用于伦敦时区。
每个 class 都有不同的时区。我希望时间表根据 classes 的相关时区自动 运行。
在 sync_classes()
方法中,我获取所有 classes 并在伦敦时区同步它。
问题:如何根据时区同步每个 class?
此代码在 Django/Celery 部分未经测试,但思路如下:
将您的 Celery-Beat 的时间表更改为每 15 分钟 运行。这应该几乎涵盖 all the TZ offsets in existence 因为大多数是小时的倍数或半小时的倍数,只有少数情况是一刻钟的倍数(所以这个 15 分钟的决议应该涵盖 all 世界时区偏移量):
CELERYBEAT_SCHEDULE = {
'sync-classes': {
'task': 'scheduler.tasks.sync_classes',
'schedule': crontab(minute='*/15'),
}
CELERY_ENABLE_UTC = False
CELERY_TIMEZONE = 'Europe/London'
在这一点上,Celery 的时区并不重要,因为我们将使用唯一的 decent 时区作为参考:UTC。
创建一个辅助函数,它将为您提供 现在 ("now" 意思是 "when your task is run") 是“almost”午夜。您的任务将 运行 每 15 分钟...可能在 15 分钟标记后几毫秒...所以让我们给它 10 分钟的缓冲时间(应该是这样,way 绰绰有余)。只要缓冲少于 15 分钟,你应该没问题(fine 意味着你不会有一个任务,下一个认为 "now" 是午夜,因此 运行 同步两次)
这应该有帮助:
import pytz
import datetime
utc_now = pytz.utc.localize(datetime.datetime.utcnow())
collected_tz_names = []
for tz in pytz.all_timezones_set:
test_dt = utc_now.astimezone(pytz.timezone(tz))
print("tz: %s, test_dt.time() %s" % (tz, test_dt.time()))
is_midnight = (
datetime.time(hour=0, minute=0, second=0) <=
test_dt.time() <=
datetime.time(hour=0, minute=10, second=0)
)
if is_midnight:
collected_tz_names.append(tz)
print("collected %s" % collected_tz_names)
如果你想测试它,将utc_now = pytz.utc.localize(datetime.datetime.utcnow())
"probe"(或参考)更改为一些手动值,例如utc_now = pytz.utc.localize(datetime.datetime(year=2018, month=1, day=4, hour=4, minute=1, second=0)
)
一旦您收集了now
是午夜的时区collected_tz_names
列表,运行 您的同步方法。假设您需要同步的对象是 User
(s),对吧?并且您的 User
模型有一个属性 tz_name
指示哪个是每个用户的时区。在那种情况下,应该这样做:
for user in User.objects.filter(tz_name__in=collected_tz_names):
user.synchronize()
请记住,在 夏令时 开关中,您可能最终会同步两次。
我正在开发一个 Django
项目。
我想自动同步 classes。
我的代码:
from datetime import timedelta
from celery.schedules import crontab
CELERYBEAT_SCHEDULE = {
'sync-classes': {
'task': 'scheduler.tasks.sync_classes',
'schedule': crontab(hour='0', minute=0),
}
CELERY_ENABLE_UTC = False
CELERY_TIMEZONE = 'Europe/London'
它适用于伦敦时区。
每个 class 都有不同的时区。我希望时间表根据 classes 的相关时区自动 运行。
在 sync_classes()
方法中,我获取所有 classes 并在伦敦时区同步它。
问题:如何根据时区同步每个 class?
此代码在 Django/Celery 部分未经测试,但思路如下:
将您的 Celery-Beat 的时间表更改为每 15 分钟 运行。这应该几乎涵盖 all the TZ offsets in existence 因为大多数是小时的倍数或半小时的倍数,只有少数情况是一刻钟的倍数(所以这个 15 分钟的决议应该涵盖 all 世界时区偏移量):
CELERYBEAT_SCHEDULE = { 'sync-classes': { 'task': 'scheduler.tasks.sync_classes', 'schedule': crontab(minute='*/15'), } CELERY_ENABLE_UTC = False CELERY_TIMEZONE = 'Europe/London'
在这一点上,Celery 的时区并不重要,因为我们将使用唯一的 decent 时区作为参考:UTC。
创建一个辅助函数,它将为您提供 现在 ("now" 意思是 "when your task is run") 是“almost”午夜。您的任务将 运行 每 15 分钟...可能在 15 分钟标记后几毫秒...所以让我们给它 10 分钟的缓冲时间(应该是这样,way 绰绰有余)。只要缓冲少于 15 分钟,你应该没问题(fine 意味着你不会有一个任务,下一个认为 "now" 是午夜,因此 运行 同步两次)
这应该有帮助:
import pytz import datetime utc_now = pytz.utc.localize(datetime.datetime.utcnow()) collected_tz_names = [] for tz in pytz.all_timezones_set: test_dt = utc_now.astimezone(pytz.timezone(tz)) print("tz: %s, test_dt.time() %s" % (tz, test_dt.time())) is_midnight = ( datetime.time(hour=0, minute=0, second=0) <= test_dt.time() <= datetime.time(hour=0, minute=10, second=0) ) if is_midnight: collected_tz_names.append(tz) print("collected %s" % collected_tz_names)
如果你想测试它,将
utc_now = pytz.utc.localize(datetime.datetime.utcnow())
"probe"(或参考)更改为一些手动值,例如utc_now = pytz.utc.localize(datetime.datetime(year=2018, month=1, day=4, hour=4, minute=1, second=0)
)一旦您收集了
now
是午夜的时区collected_tz_names
列表,运行 您的同步方法。假设您需要同步的对象是User
(s),对吧?并且您的User
模型有一个属性tz_name
指示哪个是每个用户的时区。在那种情况下,应该这样做:for user in User.objects.filter(tz_name__in=collected_tz_names): user.synchronize()
请记住,在 夏令时 开关中,您可能最终会同步两次。