1
1
from datetime import datetime
2
2
import pickle
3
3
import unittest
4
+ import nose
4
5
5
6
import numpy as np
6
7
9
10
10
11
from pandas import Timestamp
11
12
from pandas .tseries .offsets import generate_range
12
- from pandas .tseries .index import bdate_range , date_range
13
+ from pandas .tseries .index import cdate_range , bdate_range , date_range
13
14
import pandas .tseries .tools as tools
14
15
15
16
import pandas .core .datetools as datetools
@@ -23,6 +24,11 @@ def _skip_if_no_pytz():
23
24
raise nose .SkipTest
24
25
25
26
27
+ def _skip_if_no_cday ():
28
+ if datetools .cday is None :
29
+ raise nose .SkipTest ("CustomBusinessDay not available." )
30
+
31
+
26
32
def eq_gen_range (kwargs , expected ):
27
33
rng = generate_range (** kwargs )
28
34
assert (np .array_equal (list (rng ), expected ))
@@ -37,6 +43,12 @@ def test_generate(self):
37
43
rng2 = list (generate_range (START , END , time_rule = 'B' ))
38
44
self .assert_ (np .array_equal (rng1 , rng2 ))
39
45
46
+ def test_generate_cday (self ):
47
+ _skip_if_no_cday ()
48
+ rng1 = list (generate_range (START , END , offset = datetools .cday ))
49
+ rng2 = list (generate_range (START , END , time_rule = 'C' ))
50
+ self .assert_ (np .array_equal (rng1 , rng2 ))
51
+
40
52
def test_1 (self ):
41
53
eq_gen_range (dict (start = datetime (2009 , 3 , 25 ), periods = 2 ),
42
54
[datetime (2009 , 3 , 25 ), datetime (2009 , 3 , 26 )])
@@ -364,7 +376,235 @@ def test_month_range_union_tz(self):
364
376
early_dr .union (late_dr )
365
377
366
378
379
+ class TestCustomDateRange (unittest .TestCase ):
380
+
381
+ def setUp (self ):
382
+ _skip_if_no_cday ()
383
+ self .rng = cdate_range (START , END )
384
+
385
+ def test_constructor (self ):
386
+ rng = cdate_range (START , END , freq = datetools .cday )
387
+ rng = cdate_range (START , periods = 20 , freq = datetools .cday )
388
+ rng = cdate_range (end = START , periods = 20 , freq = datetools .cday )
389
+ self .assertRaises (ValueError , date_range , '2011-1-1' , '2012-1-1' , 'C' )
390
+ self .assertRaises (ValueError , cdate_range , '2011-1-1' , '2012-1-1' , 'C' )
391
+
392
+ def test_cached_range (self ):
393
+ rng = DatetimeIndex ._cached_range (START , END ,
394
+ offset = datetools .cday )
395
+ rng = DatetimeIndex ._cached_range (START , periods = 20 ,
396
+ offset = datetools .cday )
397
+ rng = DatetimeIndex ._cached_range (end = START , periods = 20 ,
398
+ offset = datetools .cday )
399
+
400
+ self .assertRaises (Exception , DatetimeIndex ._cached_range , START , END )
401
+
402
+ self .assertRaises (Exception , DatetimeIndex ._cached_range , START ,
403
+ freq = datetools .cday )
404
+
405
+ self .assertRaises (Exception , DatetimeIndex ._cached_range , end = END ,
406
+ freq = datetools .cday )
407
+
408
+ self .assertRaises (Exception , DatetimeIndex ._cached_range , periods = 20 ,
409
+ freq = datetools .cday )
410
+
411
+ def test_comparison (self ):
412
+ d = self .rng [10 ]
413
+
414
+ comp = self .rng > d
415
+ self .assert_ (comp [11 ])
416
+ self .assert_ (not comp [9 ])
417
+
418
+ def test_copy (self ):
419
+ cp = self .rng .copy ()
420
+ repr (cp )
421
+ self .assert_ (cp .equals (self .rng ))
422
+
423
+ def test_repr (self ):
424
+ # only really care that it works
425
+ repr (self .rng )
426
+
427
+ def test_getitem (self ):
428
+ smaller = self .rng [:5 ]
429
+ self .assert_ (np .array_equal (smaller , self .rng .view (np .ndarray )[:5 ]))
430
+ self .assertEquals (smaller .offset , self .rng .offset )
431
+
432
+ sliced = self .rng [::5 ]
433
+ self .assertEquals (sliced .offset , datetools .cday * 5 )
434
+
435
+ fancy_indexed = self .rng [[4 , 3 , 2 , 1 , 0 ]]
436
+ self .assertEquals (len (fancy_indexed ), 5 )
437
+ self .assert_ (isinstance (fancy_indexed , DatetimeIndex ))
438
+ self .assert_ (fancy_indexed .freq is None )
439
+
440
+ # 32-bit vs. 64-bit platforms
441
+ self .assertEquals (self .rng [4 ], self .rng [np .int_ (4 )])
442
+
443
+ def test_getitem_matplotlib_hackaround (self ):
444
+ values = self .rng [:, None ]
445
+ expected = self .rng .values [:, None ]
446
+ self .assert_ (np .array_equal (values , expected ))
447
+
448
+ def test_shift (self ):
449
+ shifted = self .rng .shift (5 )
450
+ self .assertEquals (shifted [0 ], self .rng [5 ])
451
+ self .assertEquals (shifted .offset , self .rng .offset )
452
+
453
+ shifted = self .rng .shift (- 5 )
454
+ self .assertEquals (shifted [5 ], self .rng [0 ])
455
+ self .assertEquals (shifted .offset , self .rng .offset )
456
+
457
+ shifted = self .rng .shift (0 )
458
+ self .assertEquals (shifted [0 ], self .rng [0 ])
459
+ self .assertEquals (shifted .offset , self .rng .offset )
460
+
461
+ rng = date_range (START , END , freq = datetools .bmonthEnd )
462
+ shifted = rng .shift (1 , freq = datetools .cday )
463
+ self .assertEquals (shifted [0 ], rng [0 ] + datetools .cday )
464
+
465
+ def test_pickle_unpickle (self ):
466
+ pickled = pickle .dumps (self .rng )
467
+ unpickled = pickle .loads (pickled )
468
+
469
+ self .assert_ (unpickled .offset is not None )
470
+
471
+ def test_union (self ):
472
+ # overlapping
473
+ left = self .rng [:10 ]
474
+ right = self .rng [5 :10 ]
475
+
476
+ the_union = left .union (right )
477
+ self .assert_ (isinstance (the_union , DatetimeIndex ))
478
+
479
+ # non-overlapping, gap in middle
480
+ left = self .rng [:5 ]
481
+ right = self .rng [10 :]
482
+
483
+ the_union = left .union (right )
484
+ self .assert_ (isinstance (the_union , Index ))
485
+
486
+ # non-overlapping, no gap
487
+ left = self .rng [:5 ]
488
+ right = self .rng [5 :10 ]
489
+
490
+ the_union = left .union (right )
491
+ self .assert_ (isinstance (the_union , DatetimeIndex ))
492
+
493
+ # order does not matter
494
+ self .assert_ (np .array_equal (right .union (left ), the_union ))
495
+
496
+ # overlapping, but different offset
497
+ rng = date_range (START , END , freq = datetools .bmonthEnd )
498
+
499
+ the_union = self .rng .union (rng )
500
+ self .assert_ (isinstance (the_union , DatetimeIndex ))
501
+
502
+ def test_outer_join (self ):
503
+ # should just behave as union
504
+
505
+ # overlapping
506
+ left = self .rng [:10 ]
507
+ right = self .rng [5 :10 ]
508
+
509
+ the_join = left .join (right , how = 'outer' )
510
+ self .assert_ (isinstance (the_join , DatetimeIndex ))
511
+
512
+ # non-overlapping, gap in middle
513
+ left = self .rng [:5 ]
514
+ right = self .rng [10 :]
515
+
516
+ the_join = left .join (right , how = 'outer' )
517
+ self .assert_ (isinstance (the_join , DatetimeIndex ))
518
+ self .assert_ (the_join .freq is None )
519
+
520
+ # non-overlapping, no gap
521
+ left = self .rng [:5 ]
522
+ right = self .rng [5 :10 ]
523
+
524
+ the_join = left .join (right , how = 'outer' )
525
+ self .assert_ (isinstance (the_join , DatetimeIndex ))
526
+
527
+ # overlapping, but different offset
528
+ rng = date_range (START , END , freq = datetools .bmonthEnd )
529
+
530
+ the_join = self .rng .join (rng , how = 'outer' )
531
+ self .assert_ (isinstance (the_join , DatetimeIndex ))
532
+ self .assert_ (the_join .freq is None )
533
+
534
+ def test_intersection_bug (self ):
535
+ # GH #771
536
+ a = cdate_range ('11/30/2011' , '12/31/2011' )
537
+ b = cdate_range ('12/10/2011' , '12/20/2011' )
538
+ result = a .intersection (b )
539
+ self .assert_ (result .equals (b ))
540
+
541
+ def test_summary (self ):
542
+ self .rng .summary ()
543
+ self .rng [2 :2 ].summary ()
544
+
545
+ def test_summary_pytz (self ):
546
+ _skip_if_no_pytz ()
547
+ import pytz
548
+ cdate_range ('1/1/2005' , '1/1/2009' , tz = pytz .utc ).summary ()
549
+
550
+ def test_misc (self ):
551
+ end = datetime (2009 , 5 , 13 )
552
+ dr = cdate_range (end = end , periods = 20 )
553
+ firstDate = end - 19 * datetools .cday
554
+
555
+ assert len (dr ) == 20
556
+ assert dr [0 ] == firstDate
557
+ assert dr [- 1 ] == end
558
+
559
+ def test_date_parse_failure (self ):
560
+ badly_formed_date = '2007/100/1'
561
+
562
+ self .assertRaises (ValueError , Timestamp , badly_formed_date )
563
+
564
+ self .assertRaises (ValueError , cdate_range , start = badly_formed_date ,
565
+ periods = 10 )
566
+ self .assertRaises (ValueError , cdate_range , end = badly_formed_date ,
567
+ periods = 10 )
568
+ self .assertRaises (ValueError , cdate_range , badly_formed_date ,
569
+ badly_formed_date )
570
+
571
+ def test_equals (self ):
572
+ self .assertFalse (self .rng .equals (list (self .rng )))
573
+
574
+ def test_daterange_bug_456 (self ):
575
+ # GH #456
576
+ rng1 = cdate_range ('12/5/2011' , '12/5/2011' )
577
+ rng2 = cdate_range ('12/2/2011' , '12/5/2011' )
578
+ rng2 .offset = datetools .CDay ()
579
+
580
+ result = rng1 .union (rng2 )
581
+ self .assert_ (isinstance (result , DatetimeIndex ))
582
+
583
+ def test_cdaterange (self ):
584
+ rng = cdate_range ('2013-05-01' , periods = 3 )
585
+ xp = DatetimeIndex (['2013-05-01' , '2013-05-02' , '2013-05-03' ])
586
+ self .assert_ (xp .equals (rng ))
587
+
588
+ def test_cdaterange_weekmask (self ):
589
+ rng = cdate_range ('2013-05-01' , periods = 3 ,
590
+ weekmask = 'Sun Mon Tue Wed Thu' )
591
+ xp = DatetimeIndex (['2013-05-01' , '2013-05-02' , '2013-05-05' ])
592
+ self .assert_ (xp .equals (rng ))
593
+
594
+ def test_cdaterange_holidays (self ):
595
+ rng = cdate_range ('2013-05-01' , periods = 3 ,
596
+ holidays = ['2013-05-01' ])
597
+ xp = DatetimeIndex (['2013-05-02' , '2013-05-03' , '2013-05-06' ])
598
+ self .assert_ (xp .equals (rng ))
599
+
600
+ def test_cdaterange_weekmask_and_holidays (self ):
601
+ rng = cdate_range ('2013-05-01' , periods = 3 ,
602
+ weekmask = 'Sun Mon Tue Wed Thu' ,
603
+ holidays = ['2013-05-01' ])
604
+ xp = DatetimeIndex (['2013-05-02' , '2013-05-05' , '2013-05-06' ])
605
+ self .assert_ (xp .equals (rng ))
606
+
607
+
367
608
if __name__ == '__main__' :
368
- import nose
369
609
nose .runmodule (argv = [__file__ , '-vvs' , '-x' , '--pdb' , '--pdb-failure' ],
370
610
exit = False )
0 commit comments