Skip to content

Commit 034614c

Browse files
louis-reddberenbaum
authored andcommitted
Bug in date_range with semi-open interval and freq='B' (pandas-dev#22095)
1 parent 3ed25d7 commit 034614c

File tree

1 file changed

+178
-166
lines changed

1 file changed

+178
-166
lines changed

pandas/tests/indexes/datetimes/test_date_range.py

Lines changed: 178 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -301,172 +301,6 @@ def test_construct_with_different_start_end_string_format(self):
301301
Timestamp('2013-01-01 02:00:00+09:00')])
302302
tm.assert_index_equal(result, expected)
303303

304-
305-
class TestGenRangeGeneration(object):
306-
307-
def test_generate(self):
308-
rng1 = list(generate_range(START, END, offset=BDay()))
309-
rng2 = list(generate_range(START, END, time_rule='B'))
310-
assert rng1 == rng2
311-
312-
def test_generate_cday(self):
313-
rng1 = list(generate_range(START, END, offset=CDay()))
314-
rng2 = list(generate_range(START, END, time_rule='C'))
315-
assert rng1 == rng2
316-
317-
def test_1(self):
318-
rng = list(generate_range(start=datetime(2009, 3, 25), periods=2))
319-
expected = [datetime(2009, 3, 25), datetime(2009, 3, 26)]
320-
assert rng == expected
321-
322-
def test_2(self):
323-
rng = list(generate_range(start=datetime(2008, 1, 1),
324-
end=datetime(2008, 1, 3)))
325-
expected = [datetime(2008, 1, 1),
326-
datetime(2008, 1, 2),
327-
datetime(2008, 1, 3)]
328-
assert rng == expected
329-
330-
def test_3(self):
331-
rng = list(generate_range(start=datetime(2008, 1, 5),
332-
end=datetime(2008, 1, 6)))
333-
expected = []
334-
assert rng == expected
335-
336-
def test_precision_finer_than_offset(self):
337-
# GH 9907
338-
result1 = DatetimeIndex(start='2015-04-15 00:00:03',
339-
end='2016-04-22 00:00:00', freq='Q')
340-
result2 = DatetimeIndex(start='2015-04-15 00:00:03',
341-
end='2015-06-22 00:00:04', freq='W')
342-
expected1_list = ['2015-06-30 00:00:03', '2015-09-30 00:00:03',
343-
'2015-12-31 00:00:03', '2016-03-31 00:00:03']
344-
expected2_list = ['2015-04-19 00:00:03', '2015-04-26 00:00:03',
345-
'2015-05-03 00:00:03', '2015-05-10 00:00:03',
346-
'2015-05-17 00:00:03', '2015-05-24 00:00:03',
347-
'2015-05-31 00:00:03', '2015-06-07 00:00:03',
348-
'2015-06-14 00:00:03', '2015-06-21 00:00:03']
349-
expected1 = DatetimeIndex(expected1_list, dtype='datetime64[ns]',
350-
freq='Q-DEC', tz=None)
351-
expected2 = DatetimeIndex(expected2_list, dtype='datetime64[ns]',
352-
freq='W-SUN', tz=None)
353-
tm.assert_index_equal(result1, expected1)
354-
tm.assert_index_equal(result2, expected2)
355-
356-
dt1, dt2 = '2017-01-01', '2017-01-01'
357-
tz1, tz2 = 'US/Eastern', 'Europe/London'
358-
359-
@pytest.mark.parametrize("start,end", [
360-
(pd.Timestamp(dt1, tz=tz1), pd.Timestamp(dt2)),
361-
(pd.Timestamp(dt1), pd.Timestamp(dt2, tz=tz2)),
362-
(pd.Timestamp(dt1, tz=tz1), pd.Timestamp(dt2, tz=tz2)),
363-
(pd.Timestamp(dt1, tz=tz2), pd.Timestamp(dt2, tz=tz1))
364-
])
365-
def test_mismatching_tz_raises_err(self, start, end):
366-
# issue 18488
367-
with pytest.raises(TypeError):
368-
pd.date_range(start, end)
369-
with pytest.raises(TypeError):
370-
pd.DatetimeIndex(start, end, freq=BDay())
371-
372-
373-
class TestBusinessDateRange(object):
374-
375-
def test_constructor(self):
376-
bdate_range(START, END, freq=BDay())
377-
bdate_range(START, periods=20, freq=BDay())
378-
bdate_range(end=START, periods=20, freq=BDay())
379-
380-
msg = 'periods must be a number, got B'
381-
with tm.assert_raises_regex(TypeError, msg):
382-
date_range('2011-1-1', '2012-1-1', 'B')
383-
384-
with tm.assert_raises_regex(TypeError, msg):
385-
bdate_range('2011-1-1', '2012-1-1', 'B')
386-
387-
msg = 'freq must be specified for bdate_range; use date_range instead'
388-
with tm.assert_raises_regex(TypeError, msg):
389-
bdate_range(START, END, periods=10, freq=None)
390-
391-
def test_naive_aware_conflicts(self):
392-
naive = bdate_range(START, END, freq=BDay(), tz=None)
393-
aware = bdate_range(START, END, freq=BDay(), tz="Asia/Hong_Kong")
394-
395-
msg = 'tz-naive.*tz-aware'
396-
with tm.assert_raises_regex(TypeError, msg):
397-
naive.join(aware)
398-
399-
with tm.assert_raises_regex(TypeError, msg):
400-
aware.join(naive)
401-
402-
def test_cached_range(self):
403-
DatetimeIndex._cached_range(START, END, freq=BDay())
404-
DatetimeIndex._cached_range(START, periods=20, freq=BDay())
405-
DatetimeIndex._cached_range(end=START, periods=20, freq=BDay())
406-
407-
with tm.assert_raises_regex(TypeError, "freq"):
408-
DatetimeIndex._cached_range(START, END)
409-
410-
with tm.assert_raises_regex(TypeError, "specify period"):
411-
DatetimeIndex._cached_range(START, freq=BDay())
412-
413-
with tm.assert_raises_regex(TypeError, "specify period"):
414-
DatetimeIndex._cached_range(end=END, freq=BDay())
415-
416-
with tm.assert_raises_regex(TypeError, "start or end"):
417-
DatetimeIndex._cached_range(periods=20, freq=BDay())
418-
419-
def test_cached_range_bug(self):
420-
rng = date_range('2010-09-01 05:00:00', periods=50,
421-
freq=DateOffset(hours=6))
422-
assert len(rng) == 50
423-
assert rng[0] == datetime(2010, 9, 1, 5)
424-
425-
def test_timezone_comparaison_bug(self):
426-
# smoke test
427-
start = Timestamp('20130220 10:00', tz='US/Eastern')
428-
result = date_range(start, periods=2, tz='US/Eastern')
429-
assert len(result) == 2
430-
431-
def test_timezone_comparaison_assert(self):
432-
start = Timestamp('20130220 10:00', tz='US/Eastern')
433-
msg = 'Inferred time zone not equal to passed time zone'
434-
with tm.assert_raises_regex(AssertionError, msg):
435-
date_range(start, periods=2, tz='Europe/Berlin')
436-
437-
def test_misc(self):
438-
end = datetime(2009, 5, 13)
439-
dr = bdate_range(end=end, periods=20)
440-
firstDate = end - 19 * BDay()
441-
442-
assert len(dr) == 20
443-
assert dr[0] == firstDate
444-
assert dr[-1] == end
445-
446-
def test_date_parse_failure(self):
447-
badly_formed_date = '2007/100/1'
448-
449-
with pytest.raises(ValueError):
450-
Timestamp(badly_formed_date)
451-
452-
with pytest.raises(ValueError):
453-
bdate_range(start=badly_formed_date, periods=10)
454-
455-
with pytest.raises(ValueError):
456-
bdate_range(end=badly_formed_date, periods=10)
457-
458-
with pytest.raises(ValueError):
459-
bdate_range(badly_formed_date, badly_formed_date)
460-
461-
def test_daterange_bug_456(self):
462-
# GH #456
463-
rng1 = bdate_range('12/5/2011', '12/5/2011')
464-
rng2 = bdate_range('12/2/2011', '12/5/2011')
465-
rng2.freq = BDay()
466-
467-
result = rng1.union(rng2)
468-
assert isinstance(result, DatetimeIndex)
469-
470304
def test_error_with_zero_monthends(self):
471305
msg = r'Offset <0 \* MonthEnds> did not increment date'
472306
with tm.assert_raises_regex(ValueError, msg):
@@ -658,6 +492,184 @@ def test_freq_divides_end_in_nanos(self):
658492
tm.assert_index_equal(result_1, expected_1)
659493
tm.assert_index_equal(result_2, expected_2)
660494

495+
def test_cached_range_bug(self):
496+
rng = date_range('2010-09-01 05:00:00', periods=50,
497+
freq=DateOffset(hours=6))
498+
assert len(rng) == 50
499+
assert rng[0] == datetime(2010, 9, 1, 5)
500+
501+
def test_timezone_comparaison_bug(self):
502+
# smoke test
503+
start = Timestamp('20130220 10:00', tz='US/Eastern')
504+
result = date_range(start, periods=2, tz='US/Eastern')
505+
assert len(result) == 2
506+
507+
def test_timezone_comparaison_assert(self):
508+
start = Timestamp('20130220 10:00', tz='US/Eastern')
509+
msg = 'Inferred time zone not equal to passed time zone'
510+
with tm.assert_raises_regex(AssertionError, msg):
511+
date_range(start, periods=2, tz='Europe/Berlin')
512+
513+
514+
class TestGenRangeGeneration(object):
515+
516+
def test_generate(self):
517+
rng1 = list(generate_range(START, END, offset=BDay()))
518+
rng2 = list(generate_range(START, END, time_rule='B'))
519+
assert rng1 == rng2
520+
521+
def test_generate_cday(self):
522+
rng1 = list(generate_range(START, END, offset=CDay()))
523+
rng2 = list(generate_range(START, END, time_rule='C'))
524+
assert rng1 == rng2
525+
526+
def test_1(self):
527+
rng = list(generate_range(start=datetime(2009, 3, 25), periods=2))
528+
expected = [datetime(2009, 3, 25), datetime(2009, 3, 26)]
529+
assert rng == expected
530+
531+
def test_2(self):
532+
rng = list(generate_range(start=datetime(2008, 1, 1),
533+
end=datetime(2008, 1, 3)))
534+
expected = [datetime(2008, 1, 1),
535+
datetime(2008, 1, 2),
536+
datetime(2008, 1, 3)]
537+
assert rng == expected
538+
539+
def test_3(self):
540+
rng = list(generate_range(start=datetime(2008, 1, 5),
541+
end=datetime(2008, 1, 6)))
542+
expected = []
543+
assert rng == expected
544+
545+
def test_precision_finer_than_offset(self):
546+
# GH 9907
547+
result1 = DatetimeIndex(start='2015-04-15 00:00:03',
548+
end='2016-04-22 00:00:00', freq='Q')
549+
result2 = DatetimeIndex(start='2015-04-15 00:00:03',
550+
end='2015-06-22 00:00:04', freq='W')
551+
expected1_list = ['2015-06-30 00:00:03', '2015-09-30 00:00:03',
552+
'2015-12-31 00:00:03', '2016-03-31 00:00:03']
553+
expected2_list = ['2015-04-19 00:00:03', '2015-04-26 00:00:03',
554+
'2015-05-03 00:00:03', '2015-05-10 00:00:03',
555+
'2015-05-17 00:00:03', '2015-05-24 00:00:03',
556+
'2015-05-31 00:00:03', '2015-06-07 00:00:03',
557+
'2015-06-14 00:00:03', '2015-06-21 00:00:03']
558+
expected1 = DatetimeIndex(expected1_list, dtype='datetime64[ns]',
559+
freq='Q-DEC', tz=None)
560+
expected2 = DatetimeIndex(expected2_list, dtype='datetime64[ns]',
561+
freq='W-SUN', tz=None)
562+
tm.assert_index_equal(result1, expected1)
563+
tm.assert_index_equal(result2, expected2)
564+
565+
dt1, dt2 = '2017-01-01', '2017-01-01'
566+
tz1, tz2 = 'US/Eastern', 'Europe/London'
567+
568+
@pytest.mark.parametrize("start,end", [
569+
(pd.Timestamp(dt1, tz=tz1), pd.Timestamp(dt2)),
570+
(pd.Timestamp(dt1), pd.Timestamp(dt2, tz=tz2)),
571+
(pd.Timestamp(dt1, tz=tz1), pd.Timestamp(dt2, tz=tz2)),
572+
(pd.Timestamp(dt1, tz=tz2), pd.Timestamp(dt2, tz=tz1))
573+
])
574+
def test_mismatching_tz_raises_err(self, start, end):
575+
# issue 18488
576+
with pytest.raises(TypeError):
577+
pd.date_range(start, end)
578+
with pytest.raises(TypeError):
579+
pd.DatetimeIndex(start, end, freq=BDay())
580+
581+
582+
class TestBusinessDateRange(object):
583+
584+
def test_constructor(self):
585+
bdate_range(START, END, freq=BDay())
586+
bdate_range(START, periods=20, freq=BDay())
587+
bdate_range(end=START, periods=20, freq=BDay())
588+
589+
msg = 'periods must be a number, got B'
590+
with tm.assert_raises_regex(TypeError, msg):
591+
date_range('2011-1-1', '2012-1-1', 'B')
592+
593+
with tm.assert_raises_regex(TypeError, msg):
594+
bdate_range('2011-1-1', '2012-1-1', 'B')
595+
596+
msg = 'freq must be specified for bdate_range; use date_range instead'
597+
with tm.assert_raises_regex(TypeError, msg):
598+
bdate_range(START, END, periods=10, freq=None)
599+
600+
def test_naive_aware_conflicts(self):
601+
naive = bdate_range(START, END, freq=BDay(), tz=None)
602+
aware = bdate_range(START, END, freq=BDay(), tz="Asia/Hong_Kong")
603+
604+
msg = 'tz-naive.*tz-aware'
605+
with tm.assert_raises_regex(TypeError, msg):
606+
naive.join(aware)
607+
608+
with tm.assert_raises_regex(TypeError, msg):
609+
aware.join(naive)
610+
611+
def test_cached_range(self):
612+
DatetimeIndex._cached_range(START, END, freq=BDay())
613+
DatetimeIndex._cached_range(START, periods=20, freq=BDay())
614+
DatetimeIndex._cached_range(end=START, periods=20, freq=BDay())
615+
616+
with tm.assert_raises_regex(TypeError, "freq"):
617+
DatetimeIndex._cached_range(START, END)
618+
619+
with tm.assert_raises_regex(TypeError, "specify period"):
620+
DatetimeIndex._cached_range(START, freq=BDay())
621+
622+
with tm.assert_raises_regex(TypeError, "specify period"):
623+
DatetimeIndex._cached_range(end=END, freq=BDay())
624+
625+
with tm.assert_raises_regex(TypeError, "start or end"):
626+
DatetimeIndex._cached_range(periods=20, freq=BDay())
627+
628+
def test_misc(self):
629+
end = datetime(2009, 5, 13)
630+
dr = bdate_range(end=end, periods=20)
631+
firstDate = end - 19 * BDay()
632+
633+
assert len(dr) == 20
634+
assert dr[0] == firstDate
635+
assert dr[-1] == end
636+
637+
def test_date_parse_failure(self):
638+
badly_formed_date = '2007/100/1'
639+
640+
with pytest.raises(ValueError):
641+
Timestamp(badly_formed_date)
642+
643+
with pytest.raises(ValueError):
644+
bdate_range(start=badly_formed_date, periods=10)
645+
646+
with pytest.raises(ValueError):
647+
bdate_range(end=badly_formed_date, periods=10)
648+
649+
with pytest.raises(ValueError):
650+
bdate_range(badly_formed_date, badly_formed_date)
651+
652+
def test_daterange_bug_456(self):
653+
# GH #456
654+
rng1 = bdate_range('12/5/2011', '12/5/2011')
655+
rng2 = bdate_range('12/2/2011', '12/5/2011')
656+
rng2.freq = BDay()
657+
658+
result = rng1.union(rng2)
659+
assert isinstance(result, DatetimeIndex)
660+
661+
@pytest.mark.parametrize('closed', ['left', 'right'])
662+
def test_bdays_and_open_boundaries(self, closed):
663+
# GH 6673
664+
start = '2018-07-21' # Saturday
665+
end = '2018-07-29' # Sunday
666+
result = pd.date_range(start, end, freq='B', closed=closed)
667+
668+
bday_start = '2018-07-23' # Monday
669+
bday_end = '2018-07-27' # Friday
670+
expected = pd.date_range(bday_start, bday_end, freq='D')
671+
tm.assert_index_equal(result, expected)
672+
661673

662674
class TestCustomDateRange(object):
663675

0 commit comments

Comments
 (0)