@@ -105,7 +105,7 @@ def _test_parse_iso8601(ts: str):
105
105
@ cython.wraparound (False )
106
106
@ cython.boundscheck (False )
107
107
def format_array_from_datetime (
108
- ndarray[int64_t] values ,
108
+ ndarray values ,
109
109
tzinfo tz = None ,
110
110
str format = None ,
111
111
object na_rep = None ,
@@ -129,14 +129,21 @@ def format_array_from_datetime(
129
129
np.ndarray[object]
130
130
"""
131
131
cdef:
132
- int64_t val , ns , N = len ( values)
132
+ int64_t val , ns , N = values.size
133
133
bint show_ms = False , show_us = False , show_ns = False
134
134
bint basic_format = False
135
- ndarray[object] result = cnp.PyArray_EMPTY(values.ndim, values.shape, cnp.NPY_OBJECT, 0 )
136
135
_Timestamp ts
137
- str res
136
+ object res
138
137
npy_datetimestruct dts
139
138
139
+ # Note that `result` (and thus `result_flat`) is C-order and
140
+ # `it` iterates C-order as well , so the iteration matches
141
+ # See discussion at
142
+ # github.com/pandas-dev/pandas/pull/46886#discussion_r860261305
143
+ ndarray result = cnp.PyArray_EMPTY(values.ndim, values.shape, cnp.NPY_OBJECT, 0 )
144
+ object[::1] res_flat = result.ravel() # should NOT be a copy
145
+ cnp.flatiter it = cnp.PyArray_IterNew(values)
146
+
140
147
if na_rep is None:
141
148
na_rep = ' NaT'
142
149
@@ -150,10 +157,11 @@ def format_array_from_datetime(
150
157
show_ms = reso_obj == Resolution.RESO_MS
151
158
152
159
for i in range(N ):
153
- val = values[i]
160
+ # Analogous to: utc_val = values[i]
161
+ val = (< int64_t* > cnp.PyArray_ITER_DATA(it))[0 ]
154
162
155
163
if val == NPY_NAT:
156
- result[i] = na_rep
164
+ res = na_rep
157
165
elif basic_format:
158
166
159
167
pandas_datetime_to_datetimestruct(val, reso, & dts)
@@ -168,22 +176,31 @@ def format_array_from_datetime(
168
176
elif show_ms:
169
177
res += f' .{dts.us // 1000:03d}'
170
178
171
- result[i] = res
172
179
173
180
else :
174
181
175
182
ts = Timestamp._from_value_and_reso(val, reso = reso, tz = tz)
176
183
if format is None :
177
- result[i] = str (ts)
184
+ res = str (ts)
178
185
else :
179
186
180
187
# invalid format string
181
188
# requires dates > 1900
182
189
try :
183
190
# Note: dispatches to pydatetime
184
- result[i] = ts.strftime(format)
191
+ res = ts.strftime(format)
185
192
except ValueError :
186
- result[i] = str (ts)
193
+ res = str (ts)
194
+
195
+ # Note: we can index result directly instead of using PyArray_MultiIter_DATA
196
+ # like we do for the other functions because result is known C-contiguous
197
+ # and is the first argument to PyArray_MultiIterNew2. The usual pattern
198
+ # does not seem to work with object dtype.
199
+ # See discussion at
200
+ # github.com/pandas-dev/pandas/pull/46886#discussion_r860261305
201
+ res_flat[i] = res
202
+
203
+ cnp.PyArray_ITER_NEXT(it)
187
204
188
205
return result
189
206
0 commit comments