New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Incompatibility with datetutil.rrule and pytz.timezone? #102
Comments
I am pretty sure this is at least partially a duplicate of #88. I think the dateutil timezones work because the utc offsets are more lazily calculated than in pytz, where they are cached after the first invocation. I'll have to dig in a bit more deeply to make sure, but this may be an issue with pytz - or at least just an improper usage of pytz time zones. I'm guessing that the correct behavior here is that the rule should generate 12 dates with the 8th of each month, at 19:00. One easy solution is to start import pytz
from datetime import datetime
from dateutil import rrule as rr
from dateutil.tz import gettz
try:
from itertools import imap
except ImportError:
imap = map
BERLIN = pytz.timezone("Europe/Berlin")
local_time = datetime(2015, 4, 8, 19, 0)
local_time_du = datetime(2015, 4, 8, 19, 0, tzinfo=gettz("Europe/Berlin"))
local_time_pt = BERLIN.localize(datetime(2015, 4, 8, 19, 0))
rrn = rr.rrule(freq=rr.MONTHLY, count=12, dtstart=local_time) # Naive rule
rrdu = rr.rrule(freq=rr.MONTHLY, count=12, dtstart=local_time_du) # tzfile
rrpt = rr.rrule(freq=rr.MONTHLY, count=12, dtstart=local_time_pt) # tzfile
rrm = imap(BERLIN.localize, rrn) # Map the localizing function to the naive
comp_rrule = lambda rr1, rr2: [cdu == cpt for cdu, cpt in zip(rr1, rr2)]
print("Compare pytz to dateutil:")
print(comp_rrule(rrpt, rrdu))
print("Compare naive->pytz mapping to dateutil:")
print(comp_rrule(rrm, rrdu)) This returns: Compare pytz to dateutil:
[True, True, True, True, True, True, True, False, False, False, False, False]
Compare naive->pytz mapping to dateutil:
[True, True, True, True, True, True, True, True, True, True, True, True] I think there are other options as well, such as wrapping pytz in a |
Reference to an effect of this issue in matplotlib: matplotlib/matplotlib#2737 |
pytz internally uses fixed offset timezones, swapping in the 'correct' one after arithmetic is completed. This allows it to reliably do timeline arithmetic across DST boundaries using Python's naive arithmetic (because with fixed offset timezones, they are the same thing). Arithmetic is done using the starting point's timezone rules (so DST in the original example). Adding one month will add one month in DST. When this is 'normalized' (in this case, implicitly by astimezone), the timezone is corrected to STD and you lose an hour. I think the best way of mixing rrule and pytz is to strip the tzinfo using .replace(tzinfo=None), add the rrule, and then timezone.localize(result) to put the timezone back. import pytz
from datetime import datetime
from dateutil.rrule import rrulestr
BERLIN = pytz.timezone('Europe/Berlin')
naive_local_time = datetime(2015, 4, 8, 19)
date_list = list(rrulestr('FREQ=MONTHLY;COUNT=12', dtstart=naive_local_time))
print([BERLIN.localize(dtime) for dtime in date_list]) |
OK, I'm resolving this as wontfix. |
For some time I've been using pytz's timezone implementation together with dateutil's rrule and have stumbled on an incompatibility several times. When expanding a RRULE over DST boundaries, those DST transition are disregarded (see below for an example). Is this a general incompatibility between those two packages, am I doing it wrong or is there a bug hidden somewhere (either in dateutil or pytz)?
Example
outputs:
doing the same with a dateutil timezone works fine:
outputs:
The text was updated successfully, but these errors were encountered: