Skip to content

Commit 5403939

Browse files
authored
Change period semantics to include end date (#893)
2 parents 57b0120 + 2319a12 commit 5403939

File tree

9 files changed

+74
-544
lines changed

9 files changed

+74
-544
lines changed

stdlib/c/period_internal.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,11 @@ PeriodInternal__split_by_month(const CATALA_TUPLE(CATALA_DATE; CATALA_DATE) p)
9090
CATALA_DATE stop = p[1].content;
9191
int estimated_size;
9292
CATALA_ARRAY(CATALA_TUPLE(CATALA_DATE; CATALA_DATE)) ret;
93+
dc_date * next_end;
9394
dc_date * next;
9495
dc_date tmp;
9596
dc_period one_month;
97+
dc_period m_one_day;
9698
char should_continue;
9799
int idx;
98100

@@ -109,6 +111,7 @@ PeriodInternal__split_by_month(const CATALA_TUPLE(CATALA_DATE; CATALA_DATE) p)
109111
ret->elements = catala_malloc(estimated_size * sizeof(CATALA_TUPLE(_)));
110112

111113
dc_make_period(&one_month, 0, 1, 0);
114+
dc_make_period(&m_one_day, 0, 0, -1);
112115
idx = 0;
113116

114117
while (1) {
@@ -117,7 +120,9 @@ PeriodInternal__split_by_month(const CATALA_TUPLE(CATALA_DATE; CATALA_DATE) p)
117120
dc_add_dates(next, dc_date_round_abort, &tmp, &one_month);
118121

119122
if (dc_compare_dates(next, stop) < 0){
120-
ret->elements[idx++] = mk_period(start, next);
123+
next_end = catala_malloc(sizeof(dc_date));
124+
dc_add_dates(next_end, dc_date_round_abort, next, &m_one_day);
125+
ret->elements[idx++] = mk_period(start, next_end);
121126
start = next;
122127
continue;
123128
}
@@ -150,8 +155,10 @@ PeriodInternal__split_by_year(CATALA_INT start_month, const CATALA_TUPLE(CATALA_
150155
int estimated_size;
151156
CATALA_ARRAY(CATALA_TUPLE(CATALA_DATE; CATALA_DATE)) ret;
152157
dc_date * next;
158+
dc_date * next_end;
153159
dc_date tmp;
154160
dc_period one_year;
161+
dc_period m_one_day;
155162
char should_continue;
156163
int idx;
157164

@@ -169,6 +176,7 @@ PeriodInternal__split_by_year(CATALA_INT start_month, const CATALA_TUPLE(CATALA_
169176
estimated_size = (dc_date_year(stop) - dc_date_year(start) + 1);
170177
ret->elements = catala_malloc(estimated_size * sizeof(CATALA_TUPLE(_)));
171178
dc_make_period(&one_year, 1, 0, 0);
179+
dc_make_period(&m_one_day, 0, 0, -1);
172180
idx = 0;
173181

174182
while (1) {
@@ -177,7 +185,9 @@ PeriodInternal__split_by_year(CATALA_INT start_month, const CATALA_TUPLE(CATALA_
177185
dc_add_dates(next, dc_date_round_abort, &tmp, &one_year);
178186

179187
if (dc_compare_dates(next, stop) < 0){
180-
ret->elements[idx++] = mk_period(start, next);
188+
next_end = catala_malloc(sizeof(dc_date));
189+
dc_add_dates(next_end, dc_date_round_abort, next, &m_one_day);
190+
ret->elements[idx++] = mk_period(start, next_end);
181191
start = next;
182192
continue;
183193
}

stdlib/java/period_internal.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static class Globals {
3838
};
3939

4040
/**
41-
* Splits the given period, returning one period per calendar month.
41+
* Splits the given period, returning one period per calendar month.
4242
* The first and last elements may be non-whole months.
4343
* Edge-case: if the given period is empty (begin >= end), an empty list
4444
* is returned.
@@ -52,16 +52,20 @@ public static class Globals {
5252

5353
while(cur.compareTo(end) < 0){
5454
CatalaDate fdmNext = cur.getFirstDayOfMonth().addDurationAbortOnRound(null, CatalaDuration.of(0, 1, 0));
55-
int cmp = end.compareTo(fdmNext);
56-
CatalaDate cut = cmp <= 0 ? end : fdmNext;
57-
res.add(new CatalaTuple(cur, cut));
58-
cur = cut;
55+
CatalaDate fdmEndPeriod = fdmNext.addDurationAbortOnRound(null, CatalaDuration.of(0, 0, -1));
56+
if (end.compareTo(fdmNext) <= 0) {
57+
res.add(new CatalaTuple(cur, end));
58+
break;
59+
} else {
60+
res.add(new CatalaTuple(cur, fdmEndPeriod));
61+
}
62+
cur = fdmNext;
5963
}
6064

6165
return new CatalaArray<>(res.toArray(CatalaTuple[]::new));
6266
};
6367

64-
/**
68+
/**
6569
* Splits the given period, returning one period per year, split on the first
6670
* of the given month. The first and last elements returned may be non-whole
6771
* years.
@@ -79,9 +83,14 @@ public static class Globals {
7983
while(cur.compareTo(end) < 0){
8084
CatalaDate fdyNext =
8185
new CatalaDate(firstDayOfNextRollingYear(startMonth.asBigInteger().intValueExact(), cur.date));
82-
CatalaDate cut = end.compareTo(fdyNext) <= 0 ? end : fdyNext;
83-
res.add(new CatalaTuple(cur, cut));
84-
cur = cut;
86+
CatalaDate fdyEndPeriod = fdyNext.addDurationAbortOnRound(null, CatalaDuration.of(0, 0, -1));
87+
if (end.compareTo(fdyNext) <= 0) {
88+
res.add(new CatalaTuple(cur, end));
89+
break;
90+
} else {
91+
res.add(new CatalaTuple(cur, fdyEndPeriod));
92+
}
93+
cur = fdyNext;
8594
}
8695

8796
return new CatalaArray<>(res.toArray(CatalaTuple[]::new));

stdlib/ocaml/period_internal.ml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,22 @@ let sort : ((date * date) * 'a) array -> ((date * date) * 'a) array =
1010
Array.stable_sort (fun ((beg1, _), _) ((beg2, _), _) -> cmp beg1 beg2) ret;
1111
ret
1212

13+
let one_day = Dates.make_period ~years:0 ~months:0 ~days:1
1314
let one_month = Dates.make_period ~years:0 ~months:1 ~days:0
15+
let one_year = Dates.make_period ~years:1 ~months:0 ~days:0
1416

1517
(* Toplevel def split_by_month *)
1618
let split_by_month : date * date -> (date * date) array =
1719
fun (start, stop) ->
1820
let rec split start =
1921
let next = Dates.add_dates (Dates.first_day_of_month start) one_month in
20-
if cmp next stop < 0 then (start, next) :: split next
22+
let end_period = Dates.(add_dates next (neg_period one_day)) in
23+
if cmp next stop < 0 then (start, end_period) :: split next
2124
else if cmp start stop < 0 then [start, stop]
2225
else []
2326
in
2427
split start |> Array.of_list
2528

26-
let one_year = Dates.make_period ~years:1 ~months:0 ~days:0
27-
2829
let first_day_of_rolling_year date start_month =
2930
let year, month, _ = Dates.date_to_ymd date in
3031
let year = if month < start_month then year - 1 else year in
@@ -39,7 +40,8 @@ let split_by_year : integer -> date * date -> (date * date) array =
3940
let next =
4041
Dates.add_dates (first_day_of_rolling_year start start_month) one_year
4142
in
42-
if cmp next stop < 0 then (start, next) :: split next
43+
let end_period = Dates.(add_dates next (neg_period one_day)) in
44+
if cmp next stop < 0 then (start, end_period) :: split next
4345
else if cmp start stop < 0 then [start, stop]
4446
else []
4547
in

0 commit comments

Comments
 (0)