7
7
8
8
import numpy as np
9
9
10
- from pandas ._libs .tslibs import OutOfBoundsDatetime , Timestamp
10
+ from pandas ._libs .tslibs import OutOfBoundsDatetime , Timedelta , Timestamp
11
11
12
12
from pandas .tseries .offsets import DateOffset , Tick , generate_range
13
13
14
14
15
- def generate_regular_range (
15
+ def generate_timestamps_range (
16
16
start : Timestamp , end : Timestamp , periods : int , freq : DateOffset
17
17
) -> Tuple [np .ndarray , str ]:
18
18
"""
@@ -32,57 +32,79 @@ def generate_regular_range(
32
32
33
33
Returns
34
34
-------
35
- ndarray[np.int64] representing nanosecond unix timestamps
35
+ (tuple): containing:
36
+
37
+ values : ndarray[np.int64] representing nanosecond unix timestamps
38
+ tz : the timezone of the range
36
39
"""
37
40
if isinstance (freq , Tick ):
38
- stride = freq .nanos
39
- if periods is None :
40
- b = Timestamp (start ).value
41
- # cannot just use e = Timestamp(end) + 1 because arange breaks when
42
- # stride is too large, see GH10887
43
- e = b + (Timestamp (end ).value - b ) // stride * stride + stride // 2 + 1
44
- # end.tz == start.tz by this point due to _generate implementation
45
- tz = start .tz
46
- elif start is not None :
47
- b = Timestamp (start ).value
48
- e = _generate_range_overflow_safe (b , periods , stride , side = "start" )
49
- tz = start .tz
50
- elif end is not None :
51
- e = Timestamp (end ).value + stride
52
- b = _generate_range_overflow_safe (e , periods , stride , side = "end" )
53
- tz = end .tz
54
- else :
55
- raise ValueError (
56
- "at least 'start' or 'end' should be specified "
57
- "if a 'period' is given."
58
- )
59
-
60
- with np .errstate (over = "raise" ):
61
- # If the range is sufficiently large, np.arange may overflow
62
- # and incorrectly return an empty array if not caught.
63
- try :
64
- values = np .arange (b , e , stride , dtype = np .int64 )
65
- except FloatingPointError :
66
- xdr = [b ]
67
- while xdr [- 1 ] != e :
68
- xdr .append (xdr [- 1 ] + stride )
69
- values = np .array (xdr [:- 1 ], dtype = np .int64 )
70
-
41
+ start_value = Timestamp (start ).value if start is not None else None
42
+ end_value = Timestamp (end ).value if end is not None else None
43
+ values = _generate_regular_range (start_value , end_value , periods , freq .nanos )
71
44
else :
72
- tz = None
73
- # start and end should have the same timezone by this point
74
- if start is not None :
75
- tz = start .tz
76
- elif end is not None :
77
- tz = end .tz
78
-
79
45
xdr = generate_range (start = start , end = end , periods = periods , offset = freq )
80
-
81
46
values = np .array ([x .value for x in xdr ], dtype = np .int64 )
82
47
48
+ tz = start .tz if start is not None else end .tz
83
49
return values , tz
84
50
85
51
52
+ def generate_timedeltas_range (
53
+ start : Timedelta , end : Timedelta , periods : int , freq : DateOffset
54
+ ):
55
+ """
56
+ Generate a range of dates with the spans between dates described by
57
+ the given `freq` DateOffset.
58
+
59
+ Parameters
60
+ ----------
61
+ start : Timedelta or None
62
+ first point of produced date range
63
+ end : Timedelta or None
64
+ last point of produced date range
65
+ periods : int
66
+ number of periods in produced date range
67
+ freq : DateOffset
68
+ describes space between dates in produced date range
69
+
70
+ Returns
71
+ -------
72
+ ndarray[np.int64] representing nanosecond timedeltas
73
+ """
74
+ start_value = Timedelta (start ).value if start is not None else None
75
+ end_value = Timedelta (end ).value if end is not None else None
76
+ return _generate_regular_range (start_value , end_value , periods , freq .nanos )
77
+
78
+
79
+ def _generate_regular_range (start : int , end : int , periods : int , stride : int ):
80
+ b = start
81
+ if periods is None :
82
+ # cannot just use e = Timestamp(end) + 1 because arange breaks when
83
+ # stride is too large, see GH10887
84
+ e = b + (Timestamp (end ).value - b ) // stride * stride + stride // 2 + 1
85
+ elif start is not None :
86
+ e = _generate_range_overflow_safe (b , periods , stride , side = "start" )
87
+ elif end is not None :
88
+ e = end + stride
89
+ b = _generate_range_overflow_safe (end , periods , stride , side = "end" )
90
+ else :
91
+ raise ValueError (
92
+ "at least 'start' or 'end' should be specified if a 'period' is given."
93
+ )
94
+
95
+ with np .errstate (over = "raise" ):
96
+ # If the range is sufficiently large, np.arange may overflow
97
+ # and incorrectly return an empty array if not caught.
98
+ try :
99
+ values = np .arange (b , e , stride , dtype = np .int64 )
100
+ except FloatingPointError :
101
+ xdr = [b ]
102
+ while xdr [- 1 ] != e :
103
+ xdr .append (xdr [- 1 ] + stride )
104
+ values = np .array (xdr [:- 1 ], dtype = np .int64 )
105
+ return values
106
+
107
+
86
108
def _generate_range_overflow_safe (
87
109
endpoint : int , periods : int , stride : int , side : str = "start"
88
110
) -> int :
0 commit comments