Skip to content

Commit 2fad756

Browse files
jbrockmendeljreback
authored andcommitted
transition period_helper to use pandas_datetimestruct (pandas-dev#19918)
1 parent 53606ff commit 2fad756

File tree

3 files changed

+140
-180
lines changed

3 files changed

+140
-180
lines changed

pandas/_libs/src/period_helper.c

+52-61
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,6 @@ npy_int64 unix_date_from_ymd(int year, int month, int day) {
5858
return unix_date;
5959
}
6060

61-
/* Sets the date part of the date_info struct
62-
Assumes GREGORIAN_CALENDAR */
63-
static int dInfoCalc_SetFromAbsDate(register struct date_info *dinfo,
64-
npy_int64 unix_date) {
65-
pandas_datetimestruct dts;
66-
67-
pandas_datetime_to_datetimestruct(unix_date, PANDAS_FR_D, &dts);
68-
dinfo->year = dts.year;
69-
dinfo->month = dts.month;
70-
dinfo->day = dts.day;
71-
return 0;
72-
}
7361

7462
///////////////////////////////////////////////
7563

@@ -139,9 +127,9 @@ static npy_int64 DtoB_weekday(npy_int64 unix_date) {
139127
return floordiv(unix_date + 4, 7) * 5 + mod_compat(unix_date + 4, 7) - 4;
140128
}
141129

142-
static npy_int64 DtoB(struct date_info *dinfo,
130+
static npy_int64 DtoB(pandas_datetimestruct *dts,
143131
int roll_back, npy_int64 unix_date) {
144-
int day_of_week = dayofweek(dinfo->year, dinfo->month, dinfo->day);
132+
int day_of_week = dayofweek(dts->year, dts->month, dts->day);
145133

146134
if (roll_back == 1) {
147135
if (day_of_week > 4) {
@@ -161,32 +149,32 @@ static npy_int64 DtoB(struct date_info *dinfo,
161149
//************ FROM DAILY ***************
162150

163151
static npy_int64 asfreq_DTtoA(npy_int64 ordinal, asfreq_info *af_info) {
164-
struct date_info dinfo;
152+
pandas_datetimestruct dts;
165153
ordinal = downsample_daytime(ordinal, af_info);
166-
dInfoCalc_SetFromAbsDate(&dinfo, ordinal);
167-
if (dinfo.month > af_info->to_a_year_end) {
168-
return (npy_int64)(dinfo.year + 1 - 1970);
154+
pandas_datetime_to_datetimestruct(ordinal, PANDAS_FR_D, &dts);
155+
if (dts.month > af_info->to_end) {
156+
return (npy_int64)(dts.year + 1 - 1970);
169157
} else {
170-
return (npy_int64)(dinfo.year - 1970);
158+
return (npy_int64)(dts.year - 1970);
171159
}
172160
}
173161

174162
static int DtoQ_yq(npy_int64 ordinal, asfreq_info *af_info, int *year) {
175-
struct date_info dinfo;
163+
pandas_datetimestruct dts;
176164
int quarter;
177165

178-
dInfoCalc_SetFromAbsDate(&dinfo, ordinal);
179-
if (af_info->to_q_year_end != 12) {
180-
dinfo.month -= af_info->to_q_year_end;
181-
if (dinfo.month <= 0) {
182-
dinfo.month += 12;
166+
pandas_datetime_to_datetimestruct(ordinal, PANDAS_FR_D, &dts);
167+
if (af_info->to_end != 12) {
168+
dts.month -= af_info->to_end;
169+
if (dts.month <= 0) {
170+
dts.month += 12;
183171
} else {
184-
dinfo.year += 1;
172+
dts.year += 1;
185173
}
186174
}
187175

188-
*year = dinfo.year;
189-
quarter = monthToQuarter(dinfo.month);
176+
*year = dts.year;
177+
quarter = monthToQuarter(dts.month);
190178
return quarter;
191179
}
192180

@@ -200,29 +188,28 @@ static npy_int64 asfreq_DTtoQ(npy_int64 ordinal, asfreq_info *af_info) {
200188
}
201189

202190
static npy_int64 asfreq_DTtoM(npy_int64 ordinal, asfreq_info *af_info) {
203-
struct date_info dinfo;
191+
pandas_datetimestruct dts;
204192

205193
ordinal = downsample_daytime(ordinal, af_info);
206194

207-
dInfoCalc_SetFromAbsDate(&dinfo, ordinal);
208-
return (npy_int64)((dinfo.year - 1970) * 12 + dinfo.month - 1);
195+
pandas_datetime_to_datetimestruct(ordinal, PANDAS_FR_D, &dts);
196+
return (npy_int64)((dts.year - 1970) * 12 + dts.month - 1);
209197
}
210198

211199
static npy_int64 asfreq_DTtoW(npy_int64 ordinal, asfreq_info *af_info) {
212200
ordinal = downsample_daytime(ordinal, af_info);
213-
return floordiv(ordinal + 3 - af_info->to_week_end, 7) + 1;
201+
return floordiv(ordinal + 3 - af_info->to_end, 7) + 1;
214202
}
215203

216204
static npy_int64 asfreq_DTtoB(npy_int64 ordinal, asfreq_info *af_info) {
217-
struct date_info dinfo;
218205
int roll_back;
219-
220-
ordinal = downsample_daytime(ordinal, af_info);
221-
dInfoCalc_SetFromAbsDate(&dinfo, ordinal);
206+
pandas_datetimestruct dts;
207+
npy_int64 unix_date = downsample_daytime(ordinal, af_info);
208+
pandas_datetime_to_datetimestruct(unix_date, PANDAS_FR_D, &dts);
222209

223210
// This usage defines roll_back the opposite way from the others
224211
roll_back = 1 - af_info->is_end;
225-
return DtoB(&dinfo, roll_back, ordinal);
212+
return DtoB(&dts, roll_back, unix_date);
226213
}
227214

228215
//************ FROM BUSINESS ***************
@@ -252,7 +239,7 @@ static npy_int64 asfreq_BtoW(npy_int64 ordinal, asfreq_info *af_info) {
252239
//************ FROM WEEKLY ***************
253240

254241
static npy_int64 asfreq_WtoDT(npy_int64 ordinal, asfreq_info *af_info) {
255-
ordinal = ordinal * 7 + af_info->from_week_end - 4 +
242+
ordinal = ordinal * 7 + af_info->from_end - 4 +
256243
(7 - 1) * (af_info->is_end - 1);
257244
return upsample_daytime(ordinal, af_info);
258245
}
@@ -274,12 +261,13 @@ static npy_int64 asfreq_WtoW(npy_int64 ordinal, asfreq_info *af_info) {
274261
}
275262

276263
static npy_int64 asfreq_WtoB(npy_int64 ordinal, asfreq_info *af_info) {
277-
struct date_info dinfo;
264+
int roll_back;
265+
pandas_datetimestruct dts;
278266
npy_int64 unix_date = asfreq_WtoDT(ordinal, af_info);
279267

280-
int roll_back = af_info->is_end;
281-
dInfoCalc_SetFromAbsDate(&dinfo, unix_date);
282-
return DtoB(&dinfo, roll_back, unix_date);
268+
pandas_datetime_to_datetimestruct(unix_date, PANDAS_FR_D, &dts);
269+
roll_back = af_info->is_end;
270+
return DtoB(&dts, roll_back, unix_date);
283271
}
284272

285273
//************ FROM MONTHLY ***************
@@ -313,12 +301,13 @@ static npy_int64 asfreq_MtoW(npy_int64 ordinal, asfreq_info *af_info) {
313301
}
314302

315303
static npy_int64 asfreq_MtoB(npy_int64 ordinal, asfreq_info *af_info) {
316-
struct date_info dinfo;
304+
int roll_back;
305+
pandas_datetimestruct dts;
317306
npy_int64 unix_date = asfreq_MtoDT(ordinal, af_info);
318307

319-
int roll_back = af_info->is_end;
320-
dInfoCalc_SetFromAbsDate(&dinfo, unix_date);
321-
return DtoB(&dinfo, roll_back, unix_date);
308+
pandas_datetime_to_datetimestruct(unix_date, PANDAS_FR_D, &dts);
309+
roll_back = af_info->is_end;
310+
return DtoB(&dts, roll_back, unix_date);
322311
}
323312

324313
//************ FROM QUARTERLY ***************
@@ -328,8 +317,8 @@ static void QtoD_ym(npy_int64 ordinal, int *year, int *month,
328317
*year = floordiv(ordinal, 4) + 1970;
329318
*month = mod_compat(ordinal, 4) * 3 + 1;
330319

331-
if (af_info->from_q_year_end != 12) {
332-
*month += af_info->from_q_year_end;
320+
if (af_info->from_end != 12) {
321+
*month += af_info->from_end;
333322
if (*month > 12) {
334323
*month -= 12;
335324
} else {
@@ -367,23 +356,24 @@ static npy_int64 asfreq_QtoW(npy_int64 ordinal, asfreq_info *af_info) {
367356
}
368357

369358
static npy_int64 asfreq_QtoB(npy_int64 ordinal, asfreq_info *af_info) {
370-
struct date_info dinfo;
359+
int roll_back;
360+
pandas_datetimestruct dts;
371361
npy_int64 unix_date = asfreq_QtoDT(ordinal, af_info);
372362

373-
int roll_back = af_info->is_end;
374-
dInfoCalc_SetFromAbsDate(&dinfo, unix_date);
375-
return DtoB(&dinfo, roll_back, unix_date);
363+
pandas_datetime_to_datetimestruct(unix_date, PANDAS_FR_D, &dts);
364+
roll_back = af_info->is_end;
365+
return DtoB(&dts, roll_back, unix_date);
376366
}
377367

378368
//************ FROM ANNUAL ***************
379369

380-
static void AtoD_ym(npy_int64 ordinal, int *year, int *month,
370+
static void AtoD_ym(npy_int64 ordinal, npy_int64 *year, int *month,
381371
asfreq_info *af_info) {
382372
*year = ordinal + 1970;
383373
*month = 1;
384374

385-
if (af_info->from_a_year_end != 12) {
386-
*month += af_info->from_a_year_end;
375+
if (af_info->from_end != 12) {
376+
*month += af_info->from_end;
387377
if (*month > 12) {
388378
// This case is never reached, but is kept for symmetry
389379
// with QtoD_ym
@@ -395,8 +385,8 @@ static void AtoD_ym(npy_int64 ordinal, int *year, int *month,
395385
}
396386

397387
static npy_int64 asfreq_AtoDT(npy_int64 ordinal, asfreq_info *af_info) {
398-
npy_int64 unix_date;
399-
int year, month;
388+
npy_int64 unix_date, year;
389+
int month;
400390

401391
ordinal += af_info->is_end;
402392
AtoD_ym(ordinal, &year, &month, af_info);
@@ -423,12 +413,13 @@ static npy_int64 asfreq_AtoW(npy_int64 ordinal, asfreq_info *af_info) {
423413
}
424414

425415
static npy_int64 asfreq_AtoB(npy_int64 ordinal, asfreq_info *af_info) {
426-
struct date_info dinfo;
416+
int roll_back;
417+
pandas_datetimestruct dts;
427418
npy_int64 unix_date = asfreq_AtoDT(ordinal, af_info);
428419

429-
int roll_back = af_info->is_end;
430-
dInfoCalc_SetFromAbsDate(&dinfo, unix_date);
431-
return DtoB(&dinfo, roll_back, unix_date);
420+
pandas_datetime_to_datetimestruct(unix_date, PANDAS_FR_D, &dts);
421+
roll_back = af_info->is_end;
422+
return DtoB(&dts, roll_back, unix_date);
432423
}
433424

434425
static npy_int64 nofunc(npy_int64 ordinal, asfreq_info *af_info) {

pandas/_libs/src/period_helper.h

+13-17
Original file line numberDiff line numberDiff line change
@@ -81,27 +81,23 @@ typedef struct asfreq_info {
8181
// char relation == 'S' (for START) --> is_end = 0
8282
// char relation == 'E' (for END) --> is_end = 1
8383

84-
int from_week_end; // day the week ends on in the "from" frequency
85-
int to_week_end; // day the week ends on in the "to" frequency
86-
87-
int from_a_year_end; // month the year ends on in the "from" frequency
88-
int to_a_year_end; // month the year ends on in the "to" frequency
89-
90-
int from_q_year_end; // month the year ends on in the "from" frequency
91-
int to_q_year_end; // month the year ends on in the "to" frequency
84+
int from_end;
85+
int to_end;
86+
// weekly:
87+
// from_end --> day the week ends on in the "from" frequency
88+
// to_end --> day the week ends on in the "to" frequency
89+
//
90+
// annual:
91+
// from_end --> month the year ends on in the "from" frequency
92+
// to_end --> month the year ends on in the "to" frequency
93+
//
94+
// quarterly:
95+
// from_end --> month the year ends on in the "from" frequency
96+
// to_end --> month the year ends on in the "to" frequency
9297

9398
npy_int64 intraday_conversion_factor;
9499
} asfreq_info;
95100

96-
typedef struct date_info {
97-
double second;
98-
int minute;
99-
int hour;
100-
int day;
101-
int month;
102-
int year;
103-
} date_info;
104-
105101
typedef npy_int64 (*freq_conv_func)(npy_int64, asfreq_info *af_info);
106102

107103
/*

0 commit comments

Comments
 (0)