@@ -1741,6 +1741,7 @@ def _get_time_bins(self, ax: DatetimeIndex):
1741
1741
ax .min (),
1742
1742
ax .max (),
1743
1743
self .freq ,
1744
+ unit = ax .unit ,
1744
1745
closed = self .closed ,
1745
1746
origin = self .origin ,
1746
1747
offset = self .offset ,
@@ -1760,7 +1761,8 @@ def _get_time_bins(self, ax: DatetimeIndex):
1760
1761
name = ax .name ,
1761
1762
ambiguous = True ,
1762
1763
nonexistent = "shift_forward" ,
1763
- ).as_unit (ax .unit )
1764
+ unit = ax .unit ,
1765
+ )
1764
1766
1765
1767
ax_values = ax .asi8
1766
1768
binner , bin_edges = self ._adjust_bin_edges (binner , ax_values )
@@ -1970,6 +1972,7 @@ def _get_timestamp_range_edges(
1970
1972
first : Timestamp ,
1971
1973
last : Timestamp ,
1972
1974
freq : BaseOffset ,
1975
+ unit : str ,
1973
1976
closed : Literal ["right" , "left" ] = "left" ,
1974
1977
origin : TimeGrouperOrigin = "start_day" ,
1975
1978
offset : Timedelta | None = None ,
@@ -2025,7 +2028,7 @@ def _get_timestamp_range_edges(
2025
2028
origin = origin .tz_localize (None )
2026
2029
2027
2030
first , last = _adjust_dates_anchored (
2028
- first , last , freq , closed = closed , origin = origin , offset = offset
2031
+ first , last , freq , closed = closed , origin = origin , offset = offset , unit = unit
2029
2032
)
2030
2033
if isinstance (freq , Day ):
2031
2034
first = first .tz_localize (index_tz )
@@ -2092,7 +2095,7 @@ def _get_period_range_edges(
2092
2095
adjust_last = freq .is_on_offset (last_ts )
2093
2096
2094
2097
first_ts , last_ts = _get_timestamp_range_edges (
2095
- first_ts , last_ts , freq , closed = closed , origin = origin , offset = offset
2098
+ first_ts , last_ts , freq , unit = "ns" , closed = closed , origin = origin , offset = offset
2096
2099
)
2097
2100
2098
2101
first = (first_ts + int (adjust_first ) * freq ).to_period (freq )
@@ -2125,32 +2128,35 @@ def _adjust_dates_anchored(
2125
2128
closed : Literal ["right" , "left" ] = "right" ,
2126
2129
origin : TimeGrouperOrigin = "start_day" ,
2127
2130
offset : Timedelta | None = None ,
2131
+ unit : str = "ns" ,
2128
2132
) -> tuple [Timestamp , Timestamp ]:
2129
2133
# First and last offsets should be calculated from the start day to fix an
2130
2134
# error cause by resampling across multiple days when a one day period is
2131
2135
# not a multiple of the frequency. See GH 8683
2132
2136
# To handle frequencies that are not multiple or divisible by a day we let
2133
2137
# the possibility to define a fixed origin timestamp. See GH 31809
2134
- first = first .as_unit ("ns" )
2135
- last = last .as_unit ("ns" )
2138
+ first = first .as_unit (unit )
2139
+ last = last .as_unit (unit )
2136
2140
if offset is not None :
2137
- offset = offset .as_unit ("ns" )
2141
+ offset = offset .as_unit (unit )
2142
+
2143
+ freq_value = Timedelta (freq ).as_unit (unit )._value
2138
2144
2139
- origin_nanos = 0 # origin == "epoch"
2145
+ origin_timestamp = 0 # origin == "epoch"
2140
2146
if origin == "start_day" :
2141
- origin_nanos = first .normalize ()._value
2147
+ origin_timestamp = first .normalize ()._value
2142
2148
elif origin == "start" :
2143
- origin_nanos = first ._value
2149
+ origin_timestamp = first ._value
2144
2150
elif isinstance (origin , Timestamp ):
2145
- origin_nanos = origin .as_unit ("ns" )._value
2151
+ origin_timestamp = origin .as_unit (unit )._value
2146
2152
elif origin in ["end" , "end_day" ]:
2147
2153
origin_last = last if origin == "end" else last .ceil ("D" )
2148
- sub_freq_times = (origin_last ._value - first ._value ) // freq . nanos
2154
+ sub_freq_times = (origin_last ._value - first ._value ) // freq_value
2149
2155
if closed == "left" :
2150
2156
sub_freq_times += 1
2151
2157
first = origin_last - sub_freq_times * freq
2152
- origin_nanos = first ._value
2153
- origin_nanos += offset ._value if offset else 0
2158
+ origin_timestamp = first ._value
2159
+ origin_timestamp += offset ._value if offset else 0
2154
2160
2155
2161
# GH 10117 & GH 19375. If first and last contain timezone information,
2156
2162
# Perform the calculation in UTC in order to avoid localizing on an
@@ -2162,19 +2168,19 @@ def _adjust_dates_anchored(
2162
2168
if last_tzinfo is not None :
2163
2169
last = last .tz_convert ("UTC" )
2164
2170
2165
- foffset = (first ._value - origin_nanos ) % freq . nanos
2166
- loffset = (last ._value - origin_nanos ) % freq . nanos
2171
+ foffset = (first ._value - origin_timestamp ) % freq_value
2172
+ loffset = (last ._value - origin_timestamp ) % freq_value
2167
2173
2168
2174
if closed == "right" :
2169
2175
if foffset > 0 :
2170
2176
# roll back
2171
2177
fresult_int = first ._value - foffset
2172
2178
else :
2173
- fresult_int = first ._value - freq . nanos
2179
+ fresult_int = first ._value - freq_value
2174
2180
2175
2181
if loffset > 0 :
2176
2182
# roll forward
2177
- lresult_int = last ._value + (freq . nanos - loffset )
2183
+ lresult_int = last ._value + (freq_value - loffset )
2178
2184
else :
2179
2185
# already the end of the road
2180
2186
lresult_int = last ._value
@@ -2187,11 +2193,11 @@ def _adjust_dates_anchored(
2187
2193
2188
2194
if loffset > 0 :
2189
2195
# roll forward
2190
- lresult_int = last ._value + (freq . nanos - loffset )
2196
+ lresult_int = last ._value + (freq_value - loffset )
2191
2197
else :
2192
- lresult_int = last ._value + freq . nanos
2193
- fresult = Timestamp (fresult_int )
2194
- lresult = Timestamp (lresult_int )
2198
+ lresult_int = last ._value + freq_value
2199
+ fresult = Timestamp (fresult_int , unit = unit )
2200
+ lresult = Timestamp (lresult_int , unit = unit )
2195
2201
if first_tzinfo is not None :
2196
2202
fresult = fresult .tz_localize ("UTC" ).tz_convert (first_tzinfo )
2197
2203
if last_tzinfo is not None :
0 commit comments