@@ -1168,6 +1168,15 @@ def __call__(self):
1168
1168
return self .tick_values (dmin , dmax )
1169
1169
1170
1170
def tick_values (self , vmin , vmax ):
1171
+ start , stop = self ._create_rrule (vmin , vmax )
1172
+ dates = self .rule .between (start , stop , True )
1173
+ if len (dates ) == 0 :
1174
+ return date2num ([vmin , vmax ])
1175
+ return self .raise_if_exceeds (date2num (dates ))
1176
+
1177
+ def _create_rrule (self , vmin , vmax ):
1178
+ # set appropriate rrule dtstart and until and return
1179
+ # start and end
1171
1180
delta = relativedelta (vmax , vmin )
1172
1181
1173
1182
# We need to cap at the endpoints of valid datetime
@@ -1187,10 +1196,7 @@ def tick_values(self, vmin, vmax):
1187
1196
1188
1197
self .rule .set (dtstart = start , until = stop )
1189
1198
1190
- dates = self .rule .between (vmin , vmax , True )
1191
- if len (dates ) == 0 :
1192
- return date2num ([vmin , vmax ])
1193
- return self .raise_if_exceeds (date2num (dates ))
1199
+ return vmin , vmax
1194
1200
1195
1201
def _get_unit (self ):
1196
1202
# docstring inherited
@@ -1454,7 +1460,7 @@ def get_locator(self, dmin, dmax):
1454
1460
return locator
1455
1461
1456
1462
1457
- class YearLocator (DateLocator ):
1463
+ class YearLocator (RRuleLocator ):
1458
1464
"""
1459
1465
Make ticks on a given day of each year that is a multiple of base.
1460
1466
@@ -1471,52 +1477,28 @@ def __init__(self, base=1, month=1, day=1, tz=None):
1471
1477
Mark years that are multiple of base on a given month and day
1472
1478
(default jan 1).
1473
1479
"""
1474
- super ().__init__ (tz )
1480
+ rule = rrulewrapper (YEARLY , interval = base , bymonth = month ,
1481
+ bymonthday = day , ** self .hms0d )
1482
+ super ().__init__ (rule , tz )
1475
1483
self .base = ticker ._Edge_integer (base , 0 )
1476
- self .replaced = {'month' : month ,
1477
- 'day' : day ,
1478
- 'hour' : 0 ,
1479
- 'minute' : 0 ,
1480
- 'second' : 0 ,
1481
- }
1482
- if not hasattr (tz , 'localize' ):
1483
- # if tz is pytz, we need to do this w/ the localize fcn,
1484
- # otherwise datetime.replace works fine...
1485
- self .replaced ['tzinfo' ] = tz
1486
1484
1487
- def __call__ (self ):
1488
- # if no data have been set, this will tank with a ValueError
1489
- try :
1490
- dmin , dmax = self .viewlim_to_dt ()
1491
- except ValueError :
1492
- return []
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 )
1493
1490
1494
- return self .tick_values (dmin , dmax )
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 }
1495
1496
1496
- def tick_values (self , vmin , vmax ):
1497
- ymin = self .base .le (vmin .year ) * self .base .step
1498
- ymax = self .base .ge (vmax .year ) * self .base .step
1499
-
1500
- vmin = vmin .replace (year = ymin , ** self .replaced )
1501
- if hasattr (self .tz , 'localize' ):
1502
- # look after pytz
1503
- if not vmin .tzinfo :
1504
- vmin = self .tz .localize (vmin , is_dst = True )
1505
-
1506
- ticks = [vmin ]
1507
-
1508
- while True :
1509
- dt = ticks [- 1 ]
1510
- if dt .year >= ymax :
1511
- return date2num (ticks )
1512
- year = dt .year + self .base .step
1513
- dt = dt .replace (year = year , ** self .replaced )
1514
- if hasattr (self .tz , 'localize' ):
1515
- # look after pytz
1516
- if not dt .tzinfo :
1517
- dt = self .tz .localize (dt , is_dst = True )
1518
-
1519
- ticks .append (dt )
1497
+ start = vmin .replace (** replace )
1498
+ stop = start .replace (year = ymax )
1499
+ self .rule .set (dtstart = start , until = stop )
1500
+
1501
+ return start , stop
1520
1502
1521
1503
1522
1504
class MonthLocator (RRuleLocator ):
0 commit comments