Fix Issue #604: Celery Beat Crashing at the End of Daylight Savings#605
Fix Issue #604: Celery Beat Crashing at the End of Daylight Savings#605polarmt wants to merge 11 commits intocelery:mainfrom
Conversation
auvipy
left a comment
There was a problem hiding this comment.
beside it will be very useful to have proper unit tests for this change
| value = timezone.make_aware(value, timezone.get_default_timezone()) | ||
| tm_isdst = time.localtime().tm_isdst | ||
|
|
||
| # tm_isdst may return -1 if it cannot be determined |
There was a problem hiding this comment.
I am not sure about this part, can any other way we can check it?
There was a problem hiding this comment.
I referenced these posts 1 (top answer only) and 2. There are other suggested solutions online. I can summarize the problems with these solutions.
Use of localize
The root cause was inside localize. Using the localize to fix the problem with localize sounds counterintuitive. For instance, link 1 mentions the following in the final solution:
Once you've **localized** a datetime in fact you can simply check it's .dst() method to see if it's zero.
time.daylight
This solution might work, but the underlying code is just to do a similar check to what I do here. This code is cleaner, and I can change it if you would like.
Calculations
One way is to calculate the timezone based on the current time and a previous time, but I think that this solution is long and too ad-hoc when we can achieve this with a few lines of code.
Conclusion
I think that time.daylight or time.localtime+tm_isdst is the best way to go for this. If you believe in the other solutions, please let me know.
There was a problem hiding this comment.
I have to check to give you proper answer
There was a problem hiding this comment.
Sounds good. Let me know when you've checked.
I added the unit tests. |
bc6f65c to
b75637f
Compare
…g in None all the time
for more information, see https://pre-commit.ci
|
Now that tests are passing on Django v5 this all becomes more difficult because:
https://docs.djangoproject.com/en/5.0/releases/5.0/#features-removed-in-5-0 |
|
@polarmt Please rebase to resolve the git conflicts. |
|
@polarmt Tests are ~50/50 pass/fail and in Django v5 the default value of the USE_TZ setting is changed from False to True. Now that we have release v2.6.0 that supports Django v5, how should we proceed with this effort? |
auvipy
left a comment
There was a problem hiding this comment.
we need to fix the conflict and make the ci green as the related pr seems to be passing in celery
|
@alirafiei75 sorry to ping you again here. since you are doing a lot recently, can you please check this PR and related celery issue, that if it is needed any more? if yes, if possible send a new pr with fixing the old codes? |
Not a problem at all. Happy to help. I will check it in the upcoming week. |
|
@alirafiei75 any chance you might find time to update the PR to get it merged? I was hit by this issue, or maybe celery/celery#6438 last weekend at the DST change. |
Dependencies
celery/celery#7901
Note: The two PRs are codependent and need to be merged together.
Overview
This is my suggested fix for #604. The following issue assumes
America/Los_Angeles.Testing
All testing was done on the following versions:
django: 3.2.15
celery: 5.2.7
django-celery-beat: 2.4.0
USE_TZis not set.Reproducing the Issue
In the Django shell (
python manage.py shell):Without the changes in this PR, this should throw an
AmbiguousTimeError.Behavior of
remainingDuring Transition (Without celery/celery#7901)We can run the following script to test how the Celery beat will calculate the time remaining during the transition:
nowhere would be1:34 AM PSTor1:34:00-8:00whilestartwould be1:15 AM PDTor1:15:00-7:00. The correct return value oftime.remaining(...)here would be 1 minute since 1 hour 20 minutes fromstartwould be1:35:00-8:00. The problem is thattime.remaining(...)returns 1 hour 1 minute becausetime.remainingwill convert1:15:00-7:00to1:15-8:00.Behavior of
remainingDuring Transition (With celery/celery#7901)We can use the same script as the above subsection after making the changes in celery/celery#7901. This will cause
time.remaining(...)to return 1 minute instead of 1 hour 1 minute, which is the correct value.