@@ -1154,16 +1154,10 @@ def nonsingular(self, vmin, vmax):
11541154class RRuleLocator (DateLocator ):
11551155 # use the dateutil rrule instance
11561156
1157- def __init__ (self , o , tz = None , interval_multiples = False ):
1157+ def __init__ (self , o , tz = None ):
11581158 super ().__init__ (tz )
11591159 self .rule = o
11601160
1161- # rrule cannot create interval multiples for YEARLY, this
1162- # needs to be handled separately
1163- self .mult_base = None
1164- if interval_multiples and o ._rrule ._freq == YEARLY :
1165- self .mult_base = ticker ._Edge_integer (self ._get_interval (), 0 )
1166-
11671161 def __call__ (self ):
11681162 # if no data have been set, this will tank with a ValueError
11691163 try :
@@ -1174,52 +1168,35 @@ def __call__(self):
11741168 return self .tick_values (dmin , dmax )
11751169
11761170 def tick_values (self , vmin , vmax ):
1177- if self .mult_base :
1178- # start and stop need to be multiples of the interval
1179- start , stop = self ._get_intmult_limits (vmin , vmax )
1180- vmin , vmax = start , stop
1181-
1182- else :
1183- delta = relativedelta (vmax , vmin )
1184-
1185- # We need to cap at the endpoints of valid datetime
1186- try :
1187- start = vmin - delta
1188- except (ValueError , OverflowError ):
1189- # cap
1190- start = datetime .datetime (1 , 1 , 1 , 0 , 0 , 0 ,
1191- tzinfo = datetime .timezone .utc )
1192-
1193- try :
1194- stop = vmax + delta
1195- except (ValueError , OverflowError ):
1196- # cap
1197- stop = datetime .datetime (9999 , 12 , 31 , 23 , 59 , 59 ,
1198- tzinfo = datetime .timezone .utc )
1199-
1200- self .rule .set (dtstart = start , until = stop )
1201-
1202- dates = self .rule .between (vmin , vmax , True )
1171+ start , stop = self ._create_rrule (vmin , vmax )
1172+ dates = self .rule .between (start , stop , True )
12031173 if len (dates ) == 0 :
12041174 return date2num ([vmin , vmax ])
12051175 return self .raise_if_exceeds (date2num (dates ))
12061176
1207- def _get_intmult_limits (self , vmin , vmax ):
1208- # used for interval multiples when freq == YEARLY; make start and stop
1209- # multiples of the interval but cap at the endpoints of valid datetime
1210- ymin = max (self .mult_base .le (vmin .year ) * self .mult_base .step , 1 )
1211- ymax = min (self .mult_base .ge (vmax .year ) * self .mult_base .step , 9999 )
1177+ def _create_rrule (self , vmin , vmax ):
1178+ # set appropriate rrule dtstart and until and return
1179+ # start and end
1180+ delta = relativedelta (vmax , vmin )
12121181
1213- c = self .rule ._construct
1214- replace = {'year' : ymin ,
1215- 'month' : getattr (c , 'bymonth' , 1 ),
1216- 'day' : getattr (c , 'bymonthday' , 1 ),
1217- 'hour' : 0 , 'minute' : 0 , 'second' : 0 }
1182+ # We need to cap at the endpoints of valid datetime
1183+ try :
1184+ start = vmin - delta
1185+ except (ValueError , OverflowError ):
1186+ # cap
1187+ start = datetime .datetime (1 , 1 , 1 , 0 , 0 , 0 ,
1188+ tzinfo = datetime .timezone .utc )
12181189
1219- start = vmin .replace (** replace )
1220- stop = vmax .replace (year = ymax )
1190+ try :
1191+ stop = vmax + delta
1192+ except (ValueError , OverflowError ):
1193+ # cap
1194+ stop = datetime .datetime (9999 , 12 , 31 , 23 , 59 , 59 ,
1195+ tzinfo = datetime .timezone .utc )
12211196
1222- return start , stop
1197+ self .rule .set (dtstart = start , until = stop )
1198+
1199+ return vmin , vmax
12231200
12241201 def _get_unit (self ):
12251202 # docstring inherited
@@ -1459,16 +1436,17 @@ def get_locator(self, dmin, dmax):
14591436 else :
14601437 interval = 1
14611438
1462- if use_rrule_locator [i ]:
1439+ if (freq == YEARLY ) and self .interval_multiples :
1440+ locator = YearLocator (interval , tz = self .tz )
1441+ elif use_rrule_locator [i ]:
14631442 _ , bymonth , bymonthday , byhour , byminute , bysecond , _ = byranges
14641443 rrule = rrulewrapper (self ._freq , interval = interval ,
14651444 dtstart = dmin , until = dmax ,
14661445 bymonth = bymonth , bymonthday = bymonthday ,
14671446 byhour = byhour , byminute = byminute ,
14681447 bysecond = bysecond )
14691448
1470- locator = RRuleLocator (rrule , self .tz ,
1471- interval_multiples = self .interval_multiples )
1449+ locator = RRuleLocator (rrule , self .tz )
14721450 else :
14731451 locator = MicrosecondLocator (interval , tz = self .tz )
14741452 if date2num (dmin ) > 70 * 365 and interval < 1000 :
@@ -1501,7 +1479,26 @@ def __init__(self, base=1, month=1, day=1, tz=None):
15011479 """
15021480 rule = rrulewrapper (YEARLY , interval = base , bymonth = month ,
15031481 bymonthday = day , ** self .hms0d )
1504- super ().__init__ (rule , tz , interval_multiples = True )
1482+ super ().__init__ (rule , tz )
1483+ self .base = ticker ._Edge_integer (base , 0 )
1484+
1485+ def _create_rrule (self , vmin , vmax ):
1486+ # 'start' needs to be a multiple of the interval to create ticks on
1487+ # interval multiples when the tick frequency is YEARLY
1488+ ymin = max (self .base .le (vmin .year ) * self .base .step , 1 )
1489+ ymax = min (self .base .ge (vmax .year ) * self .base .step , 9999 )
1490+
1491+ c = self .rule ._construct
1492+ replace = {'year' : ymin ,
1493+ 'month' : c .get ('bymonth' , 1 ),
1494+ 'day' : c .get ('bymonthday' , 1 ),
1495+ 'hour' : 0 , 'minute' : 0 , 'second' : 0 }
1496+
1497+ start = vmin .replace (** replace )
1498+ stop = start .replace (year = ymax )
1499+ self .rule .set (dtstart = start , until = stop )
1500+
1501+ return start , stop
15051502
15061503
15071504class MonthLocator (RRuleLocator ):
0 commit comments