@@ -358,7 +358,8 @@ def __new__(cls, data=None,
358358 msg = 'periods must be a number, got {periods}'
359359 raise TypeError (msg .format (periods = periods ))
360360
361- if data is None and freq is None :
361+ if data is None and freq is None \
362+ and com ._any_none (periods , start , end ):
362363 raise ValueError ("Must provide freq argument if no data is "
363364 "supplied" )
364365
@@ -466,9 +467,9 @@ def __new__(cls, data=None,
466467 @classmethod
467468 def _generate (cls , start , end , periods , name , freq ,
468469 tz = None , normalize = False , ambiguous = 'raise' , closed = None ):
469- if com ._count_not_none (start , end , periods ) != 2 :
470- raise ValueError ('Of the three parameters: start, end, and '
471- 'periods , exactly two must be specified' )
470+ if com ._count_not_none (start , end , periods , freq ) != 3 :
471+ raise ValueError ('Of the four parameters: start, end, periods, '
472+ 'and freq , exactly three must be specified' )
472473
473474 _normalized = True
474475
@@ -566,23 +567,30 @@ def _generate(cls, start, end, periods, name, freq,
566567 if end .tz is None and start .tz is not None :
567568 start = start .replace (tzinfo = None )
568569
569- if _use_cached_range (freq , _normalized , start , end ):
570- index = cls ._cached_range (start , end , periods = periods ,
571- freq = freq , name = name )
570+ if freq is not None :
571+ if _use_cached_range (freq , _normalized , start , end ):
572+ index = cls ._cached_range (start , end , periods = periods ,
573+ freq = freq , name = name )
574+ else :
575+ index = _generate_regular_range (start , end , periods , freq )
576+
577+ if tz is not None and getattr (index , 'tz' , None ) is None :
578+ index = conversion .tz_localize_to_utc (_ensure_int64 (index ),
579+ tz ,
580+ ambiguous = ambiguous )
581+ index = index .view (_NS_DTYPE )
582+
583+ # index is localized datetime64 array -> have to convert
584+ # start/end as well to compare
585+ if start is not None :
586+ start = start .tz_localize (tz ).asm8
587+ if end is not None :
588+ end = end .tz_localize (tz ).asm8
572589 else :
573- index = _generate_regular_range (start , end , periods , freq )
574-
575- if tz is not None and getattr (index , 'tz' , None ) is None :
576- index = conversion .tz_localize_to_utc (_ensure_int64 (index ), tz ,
577- ambiguous = ambiguous )
578- index = index .view (_NS_DTYPE )
579-
580- # index is localized datetime64 array -> have to convert
581- # start/end as well to compare
582- if start is not None :
583- start = start .tz_localize (tz ).asm8
584- if end is not None :
585- end = end .tz_localize (tz ).asm8
590+ index = tools .to_datetime (np .linspace (start .value ,
591+ end .value , periods ))
592+ if tz is not None :
593+ index = index .tz_localize ('UTC' ).tz_convert (tz )
586594
587595 if not left_closed and len (index ) and index [0 ] == start :
588596 index = index [1 :]
@@ -2565,13 +2573,15 @@ def _generate_regular_range(start, end, periods, freq):
25652573 return data
25662574
25672575
2568- def date_range (start = None , end = None , periods = None , freq = 'D' , tz = None ,
2576+ def date_range (start = None , end = None , periods = None , freq = None , tz = None ,
25692577 normalize = False , name = None , closed = None , ** kwargs ):
25702578 """
25712579 Return a fixed frequency DatetimeIndex.
25722580
2573- Exactly two of the three parameters `start`, `end` and `periods`
2574- must be specified.
2581+ Of the three parameters `start`, `end`, `periods`, and `freq` exactly
2582+ three must be specified. If `freq` is omitted, the resulting DatetimeIndex
2583+ will have `periods` linearly spaced elements between `start` and `end`
2584+ (closed on both sides).
25752585
25762586 Parameters
25772587 ----------
@@ -2613,7 +2623,7 @@ def date_range(start=None, end=None, periods=None, freq='D', tz=None,
26132623 --------
26142624 **Specifying the values**
26152625
2616- The next three examples generate the same `DatetimeIndex`, but vary
2626+ The next four examples generate the same `DatetimeIndex`, but vary
26172627 the combination of `start`, `end` and `periods`.
26182628
26192629 Specify `start` and `end`, with the default daily frequency.
@@ -2637,6 +2647,13 @@ def date_range(start=None, end=None, periods=None, freq='D', tz=None,
26372647 '2017-12-29', '2017-12-30', '2017-12-31', '2018-01-01'],
26382648 dtype='datetime64[ns]', freq='D')
26392649
2650+ Specify `start`, `end`, and `periods`; the frequency is generated
2651+ automatically (linearly spaced).
2652+
2653+ >>> pd.date_range(start='2018-04-24', end='2018-04-27', periods=3)
2654+ DatetimeIndex(['2018-04-24 00:00:00', '2018-04-25 12:00:00',
2655+ '2018-04-27 00:00:00'], freq=None)
2656+
26402657 **Other Parameters**
26412658
26422659 Changed the `freq` (frequency) to ``'M'`` (month end frequency).
@@ -2687,6 +2704,10 @@ def date_range(start=None, end=None, periods=None, freq='D', tz=None,
26872704 DatetimeIndex(['2017-01-02', '2017-01-03', '2017-01-04'],
26882705 dtype='datetime64[ns]', freq='D')
26892706 """
2707+
2708+ if freq is None and com ._any_none (periods , start , end ):
2709+ freq = 'D'
2710+
26902711 return DatetimeIndex (start = start , end = end , periods = periods ,
26912712 freq = freq , tz = tz , normalize = normalize , name = name ,
26922713 closed = closed , ** kwargs )
0 commit comments