1use crate::scheduling::DateRoll;
2use chrono::prelude::*;
3use chrono::Days;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
8pub enum Adjuster {
9 Actual {},
11 Following {},
13 ModifiedFollowing {},
15 Previous {},
17 ModifiedPrevious {},
19 FollowingSettle {},
21 ModifiedFollowingSettle {},
23 PreviousSettle {},
25 ModifiedPreviousSettle {},
27 BusDaysLagSettle(i32),
30 CalDaysLagSettle(i32),
33 FollowingExLast {},
35 FollowingExLastSettle {},
37 BusDaysLagSettleInAdvance(i32),
39}
40
41pub trait Adjustment {
43 fn adjust<T: DateRoll>(&self, udate: &NaiveDateTime, calendar: &T) -> NaiveDateTime;
45
46 fn reverse<T: DateRoll>(&self, adate: &NaiveDateTime, calendar: &T) -> Vec<NaiveDateTime>;
48
49 fn adjusts<T: DateRoll>(&self, udates: &Vec<NaiveDateTime>, calendar: &T)
51 -> Vec<NaiveDateTime>;
52}
53
54pub trait CalendarAdjustment {
56 fn adjust(&self, udate: &NaiveDateTime, adjuster: &Adjuster) -> NaiveDateTime
58 where
59 Self: Sized + DateRoll,
60 {
61 adjuster.adjust(udate, self)
62 }
63
64 fn adjusts(&self, udates: &Vec<NaiveDateTime>, adjuster: &Adjuster) -> Vec<NaiveDateTime>
66 where
67 Self: Sized + DateRoll,
68 {
69 adjuster.adjusts(udates, self)
70 }
71}
72
73impl Adjustment for Adjuster {
74 fn adjust<T: DateRoll>(&self, udate: &NaiveDateTime, calendar: &T) -> NaiveDateTime {
75 match self {
76 Adjuster::Actual {} => *udate,
77 Adjuster::Following {} => calendar.roll_forward_bus_day(udate),
78 Adjuster::Previous {} => calendar.roll_backward_bus_day(udate),
79 Adjuster::ModifiedFollowing {} => calendar.roll_mod_forward_bus_day(udate),
80 Adjuster::ModifiedPrevious {} => calendar.roll_mod_backward_bus_day(udate),
81 Adjuster::FollowingSettle {} => calendar.roll_forward_settled_bus_day(udate),
82 Adjuster::PreviousSettle {} => calendar.roll_backward_settled_bus_day(udate),
83 Adjuster::ModifiedFollowingSettle {} => {
84 calendar.roll_forward_mod_settled_bus_day(udate)
85 }
86 Adjuster::ModifiedPreviousSettle {} => {
87 calendar.roll_backward_mod_settled_bus_day(udate)
88 }
89 Adjuster::BusDaysLagSettle(n) => calendar.lag_bus_days(udate, *n, true),
90 Adjuster::CalDaysLagSettle(n) => {
91 let adj = if *n < 0 {
92 Adjuster::PreviousSettle {}
93 } else {
94 Adjuster::FollowingSettle {}
95 };
96 calendar.add_cal_days(udate, *n, &adj)
97 }
98 Adjuster::FollowingExLast {} => calendar.roll_forward_bus_day(udate), Adjuster::FollowingExLastSettle {} => calendar.roll_forward_settled_bus_day(udate), Adjuster::BusDaysLagSettleInAdvance(n) => calendar.lag_bus_days(udate, *n, true), }
102 }
103
104 fn reverse<T: DateRoll>(&self, adate: &NaiveDateTime, calendar: &T) -> Vec<NaiveDateTime> {
105 match self {
106 Adjuster::Actual {} => vec![*adate],
107 Adjuster::Following {} => reverse_forward_type(adate, self, calendar),
108 Adjuster::Previous {} => reverse_backward_type(adate, self, calendar),
109 Adjuster::ModifiedFollowing {} => reverse_modified_type(adate, self, calendar),
110 Adjuster::ModifiedPrevious {} => reverse_modified_type(adate, self, calendar),
111 Adjuster::FollowingSettle {} => reverse_forward_type(adate, self, calendar),
112 Adjuster::PreviousSettle {} => reverse_backward_type(adate, self, calendar),
113 Adjuster::ModifiedFollowingSettle {} => reverse_modified_type(adate, self, calendar),
114 Adjuster::ModifiedPreviousSettle {} => reverse_modified_type(adate, self, calendar),
115 Adjuster::BusDaysLagSettle(n) => reverse_lag_settle_type(adate, self, calendar, n),
116 Adjuster::CalDaysLagSettle(n) => reverse_lag_settle_type(adate, self, calendar, n),
117 Adjuster::FollowingExLast {} => reverse_forward_type(adate, self, calendar), Adjuster::FollowingExLastSettle {} => reverse_forward_type(adate, self, calendar), Adjuster::BusDaysLagSettleInAdvance(n) => {
120 reverse_lag_settle_type(adate, self, calendar, n)
121 } }
123 }
124
125 fn adjusts<T: DateRoll>(
126 &self,
127 udates: &Vec<NaiveDateTime>,
128 calendar: &T,
129 ) -> Vec<NaiveDateTime> {
130 let mut non_vector_adates: Vec<NaiveDateTime> = udates
131 .iter()
132 .map(|udate| self.adjust(udate, calendar))
133 .collect();
134
135 match self {
137 Adjuster::FollowingExLast {} | Adjuster::FollowingExLastSettle {} => {
138 non_vector_adates[udates.len() - 1] = udates[udates.len() - 1];
139 }
140 Adjuster::BusDaysLagSettleInAdvance(_n) => {
141 for i in (1..udates.len()).rev() {
142 non_vector_adates[i] = non_vector_adates[i - 1];
143 }
144 }
145 _ => {}
146 }
147 non_vector_adates
148 }
149}
150
151fn reverse_forward_type<T: DateRoll>(
152 adate: &NaiveDateTime,
153 adjuster: &Adjuster,
154 calendar: &T,
155) -> Vec<NaiveDateTime> {
156 let mut ret: Vec<NaiveDateTime>;
157 if (*adjuster).adjust(adate, calendar) == *adate {
158 ret = vec![*adate];
160 } else {
161 return vec![];
163 }
164 let mut date = *adate - Days::new(1);
165 while (*adjuster).adjust(&date, calendar) == *adate {
166 ret.push(date);
167 date = date - Days::new(1);
168 }
169 ret
170}
171
172fn reverse_backward_type<T: DateRoll>(
173 adate: &NaiveDateTime,
174 adjuster: &Adjuster,
175 calendar: &T,
176) -> Vec<NaiveDateTime> {
177 let mut ret: Vec<NaiveDateTime>;
178 if (*adjuster).adjust(adate, calendar) == *adate {
179 ret = vec![*adate];
181 } else {
182 return vec![];
184 }
185 let mut date = *adate + Days::new(1);
186 while (*adjuster).adjust(&date, calendar) == *adate {
187 ret.push(date);
188 date = date + Days::new(1);
189 }
190 ret
191}
192
193fn reverse_modified_type<T: DateRoll>(
194 adate: &NaiveDateTime,
195 adjuster: &Adjuster,
196 calendar: &T,
197) -> Vec<NaiveDateTime> {
198 let mut ret: Vec<NaiveDateTime>;
199 if (*adjuster).adjust(adate, calendar) == *adate {
200 ret = vec![*adate];
202 } else {
203 return vec![];
205 }
206 let mut date = *adate - Days::new(1);
207 let mut adj = (*adjuster).adjust(&date, calendar);
208 while adj == *adate && date.month() == adate.month() {
209 ret.push(date);
210 date = date - Days::new(1);
211 adj = (*adjuster).adjust(&date, calendar);
212 }
213 date = *adate + Days::new(1);
214 adj = (*adjuster).adjust(&date, calendar);
215 while adj == *adate && date.month() == adate.month() {
216 ret.push(date);
217 date = date + Days::new(1);
218 adj = (*adjuster).adjust(&date, calendar);
219 }
220 ret
221}
222
223fn reverse_lag_settle_type<T: DateRoll>(
224 adate: &NaiveDateTime,
225 adjuster: &Adjuster,
226 calendar: &T,
227 n: &i32,
228) -> Vec<NaiveDateTime> {
229 if (Adjuster::FollowingSettle {}).adjust(adate, calendar) != *adate {
230 vec![]
232 } else {
233 let mut ret: Vec<NaiveDateTime> = vec![];
235 if (*adjuster).adjust(adate, calendar) == *adate {
236 ret.push(*adate);
237 }
238
239 let mut date = *adate;
240 let mut adj_date: NaiveDateTime;
241 if *n < 0 {
242 loop {
243 date = date + Days::new(1);
244 adj_date = (*adjuster).adjust(&date, calendar);
245 if adj_date == *adate {
246 ret.push(date);
247 } else if adj_date > *adate {
248 break;
249 }
250 }
251 } else {
252 loop {
253 date = date - Days::new(1);
254 adj_date = (*adjuster).adjust(&date, calendar);
255 if adj_date == *adate {
256 ret.push(date);
257 } else if adj_date < *adate {
258 break;
259 }
260 }
261 }
262 ret
263 }
264}
265
266#[cfg(test)]
268mod tests {
269 use super::*;
270 use crate::scheduling::{ndt, Cal, Calendar, UnionCal};
271
272 fn fixture_hol_cal() -> Cal {
273 let hols = vec![ndt(2015, 9, 5), ndt(2015, 9, 7)]; Cal::new(hols, vec![5, 6])
275 }
276
277 #[test]
278 fn test_equality() {
279 assert_eq!(Adjuster::Following {}, Adjuster::Following {});
280 assert_eq!(Adjuster::BusDaysLagSettle(3), Adjuster::BusDaysLagSettle(3));
281 assert_ne!(Adjuster::BusDaysLagSettle(3), Adjuster::BusDaysLagSettle(5));
282 }
283
284 #[test]
285 fn test_adjusts() {
286 let cal = fixture_hol_cal();
287 let udates = vec![
288 ndt(2015, 9, 4),
289 ndt(2015, 9, 5),
290 ndt(2015, 9, 6),
291 ndt(2015, 9, 7),
292 ];
293 let result = Adjuster::Following {}.adjusts(&udates, &cal);
294 assert_eq!(
295 result,
296 vec![
297 ndt(2015, 9, 4),
298 ndt(2015, 9, 8),
299 ndt(2015, 9, 8),
300 ndt(2015, 9, 8)
301 ]
302 );
303 }
304
305 #[test]
306 fn test_adjusts_ex_last() {
307 let cal = fixture_hol_cal();
309 let udates = vec![
310 ndt(2015, 9, 4),
311 ndt(2015, 9, 5),
312 ndt(2015, 9, 6),
313 ndt(2015, 9, 7),
314 ];
315 let result = Adjuster::FollowingExLast {}.adjusts(&udates, &cal);
316 assert_eq!(
317 result,
318 vec![
319 ndt(2015, 9, 4),
320 ndt(2015, 9, 8),
321 ndt(2015, 9, 8),
322 ndt(2015, 9, 7)
323 ]
324 );
325 }
326
327 #[test]
328 fn test_adjusts_in_advance() {
329 let cal = fixture_hol_cal();
331 let udates = vec![
332 ndt(2015, 9, 4),
333 ndt(2015, 9, 5),
334 ndt(2015, 9, 6),
335 ndt(2015, 9, 7),
336 ];
337 let result = Adjuster::BusDaysLagSettleInAdvance(0).adjusts(&udates, &cal);
338 assert_eq!(
339 result,
340 vec![
341 ndt(2015, 9, 4),
342 ndt(2015, 9, 4),
343 ndt(2015, 9, 8),
344 ndt(2015, 9, 8)
345 ]
346 );
347 }
348
349 #[test]
350 fn test_reverse() {
351 let cal = Cal::new(
352 vec![
353 ndt(2000, 1, 31),
354 ndt(2000, 1, 29),
355 ndt(2000, 1, 10),
356 ndt(2000, 1, 11),
357 ndt(2000, 1, 16),
358 ndt(2000, 1, 1),
359 ndt(2000, 1, 3),
360 ],
361 vec![],
362 );
363
364 let options: Vec<(NaiveDateTime, Adjuster, Vec<NaiveDateTime>)> = vec![
365 (ndt(2000, 1, 1), Adjuster::Following {}, vec![]),
367 (ndt(2000, 1, 1), Adjuster::Previous {}, vec![]),
368 (ndt(2000, 1, 1), Adjuster::ModifiedPrevious {}, vec![]),
369 (ndt(2000, 1, 11), Adjuster::CalDaysLagSettle(3), vec![]),
370 (ndt(2000, 1, 11), Adjuster::BusDaysLagSettle(3), vec![]),
371 (
373 ndt(2000, 1, 2),
374 Adjuster::Following {},
375 vec![ndt(2000, 1, 2), ndt(2000, 1, 1)],
376 ),
377 (
378 ndt(2000, 1, 30),
379 Adjuster::Following {},
380 vec![ndt(2000, 1, 30), ndt(2000, 1, 29)],
381 ),
382 (
383 ndt(2000, 1, 2),
384 Adjuster::FollowingSettle {},
385 vec![ndt(2000, 1, 2), ndt(2000, 1, 1)],
386 ),
387 (
388 ndt(2000, 1, 30),
389 Adjuster::FollowingSettle {},
390 vec![ndt(2000, 1, 30), ndt(2000, 1, 29)],
391 ),
392 (
393 ndt(2000, 1, 2),
394 Adjuster::Previous {},
395 vec![ndt(2000, 1, 2), ndt(2000, 1, 3)],
396 ),
397 (
398 ndt(2000, 1, 30),
399 Adjuster::Previous {},
400 vec![ndt(2000, 1, 30), ndt(2000, 1, 31)],
401 ),
402 (
403 ndt(2000, 1, 2),
404 Adjuster::PreviousSettle {},
405 vec![ndt(2000, 1, 2), ndt(2000, 1, 3)],
406 ),
407 (
408 ndt(2000, 1, 30),
409 Adjuster::PreviousSettle {},
410 vec![ndt(2000, 1, 30), ndt(2000, 1, 31)],
411 ),
412 (
413 ndt(2000, 1, 2),
414 Adjuster::FollowingExLast {},
415 vec![ndt(2000, 1, 2), ndt(2000, 1, 1)],
416 ),
417 (
418 ndt(2000, 1, 30),
419 Adjuster::FollowingExLast {},
420 vec![ndt(2000, 1, 30), ndt(2000, 1, 29)],
421 ),
422 (
423 ndt(2000, 1, 2),
424 Adjuster::FollowingExLastSettle {},
425 vec![ndt(2000, 1, 2), ndt(2000, 1, 1)],
426 ),
427 (
428 ndt(2000, 1, 30),
429 Adjuster::FollowingExLastSettle {},
430 vec![ndt(2000, 1, 30), ndt(2000, 1, 29)],
431 ),
432 (
433 ndt(2000, 1, 2),
434 Adjuster::ModifiedFollowing {},
435 vec![ndt(2000, 1, 2), ndt(2000, 1, 1)],
436 ),
437 (
438 ndt(2000, 1, 30),
439 Adjuster::ModifiedFollowing {},
440 vec![ndt(2000, 1, 30), ndt(2000, 1, 29), ndt(2000, 1, 31)],
441 ),
442 (
443 ndt(2000, 1, 2),
444 Adjuster::ModifiedPrevious {},
445 vec![ndt(2000, 1, 2), ndt(2000, 1, 1), ndt(2000, 1, 3)],
446 ),
447 (
448 ndt(2000, 1, 30),
449 Adjuster::ModifiedPrevious {},
450 vec![ndt(2000, 1, 30), ndt(2000, 1, 31)],
451 ),
452 (
453 ndt(2000, 1, 2),
454 Adjuster::ModifiedFollowingSettle {},
455 vec![ndt(2000, 1, 2), ndt(2000, 1, 1)],
456 ),
457 (
458 ndt(2000, 1, 30),
459 Adjuster::ModifiedFollowingSettle {},
460 vec![ndt(2000, 1, 30), ndt(2000, 1, 29), ndt(2000, 1, 31)],
461 ),
462 (
463 ndt(2000, 1, 2),
464 Adjuster::ModifiedPreviousSettle {},
465 vec![ndt(2000, 1, 2), ndt(2000, 1, 1), ndt(2000, 1, 3)],
466 ),
467 (
468 ndt(2000, 1, 30),
469 Adjuster::ModifiedPreviousSettle {},
470 vec![ndt(2000, 1, 30), ndt(2000, 1, 31)],
471 ),
472 (ndt(2000, 1, 2), Adjuster::Actual {}, vec![ndt(2000, 1, 2)]),
473 (
474 ndt(2000, 1, 30),
475 Adjuster::Actual {},
476 vec![ndt(2000, 1, 30)],
477 ),
478 (
479 ndt(2000, 1, 30),
480 Adjuster::Actual {},
481 vec![ndt(2000, 1, 30)],
482 ),
483 (
484 ndt(2000, 1, 15),
485 Adjuster::CalDaysLagSettle(5),
486 vec![ndt(2000, 1, 10)],
487 ),
488 (
489 ndt(2000, 1, 12),
490 Adjuster::CalDaysLagSettle(5),
491 vec![ndt(2000, 1, 7), ndt(2000, 1, 6), ndt(2000, 1, 5)],
492 ),
493 (
494 ndt(2000, 1, 18),
495 Adjuster::BusDaysLagSettle(5),
496 vec![ndt(2000, 1, 12)],
497 ),
498 (
499 ndt(2000, 1, 17),
500 Adjuster::BusDaysLagSettle(5),
501 vec![ndt(2000, 1, 11), ndt(2000, 1, 10), ndt(2000, 1, 9)],
502 ),
503 ];
504 for option in options {
505 let result = option.1.reverse(&option.0, &Calendar::Cal(cal.clone()));
506 assert_eq!(result, option.2)
507 }
508 }
509
510 #[test]
511 fn test_forward_book_reverse() {
512 let cal = Cal::new(vec![ndt(2000, 6, 27), ndt(2000, 6, 30)], vec![]);
514 let settle = Cal::new(
515 vec![
516 ndt(2000, 6, 26),
517 ndt(2000, 6, 29),
518 ndt(2000, 6, 30),
519 ndt(2000, 7, 1),
520 ],
521 vec![],
522 );
523 let uni = UnionCal::new(vec![cal], Some(vec![settle]));
524
525 let options: Vec<(NaiveDateTime, NaiveDateTime)> = vec![
527 (ndt(2000, 6, 26), ndt(2000, 6, 26)),
528 (ndt(2000, 6, 27), ndt(2000, 6, 28)),
529 (ndt(2000, 6, 28), ndt(2000, 6, 28)),
530 (ndt(2000, 6, 29), ndt(2000, 6, 29)),
531 (ndt(2000, 6, 30), ndt(2000, 7, 1)),
532 (ndt(2000, 7, 1), ndt(2000, 7, 1)),
533 (ndt(2000, 7, 2), ndt(2000, 7, 2)),
534 ];
535 for option in options {
536 let result = Adjuster::Following {}.adjust(&option.0, &Calendar::UnionCal(uni.clone()));
537 assert_eq!(result, option.1)
538 }
539
540 let options: Vec<(NaiveDateTime, Vec<NaiveDateTime>)> = vec![
542 (ndt(2000, 6, 26), vec![ndt(2000, 6, 26)]),
543 (ndt(2000, 6, 27), vec![]),
544 (ndt(2000, 6, 28), vec![ndt(2000, 6, 28), ndt(2000, 6, 27)]),
545 (ndt(2000, 6, 29), vec![ndt(2000, 6, 29)]),
546 (ndt(2000, 6, 30), vec![]),
547 (ndt(2000, 7, 1), vec![ndt(2000, 7, 1), ndt(2000, 6, 30)]),
548 (ndt(2000, 7, 2), vec![ndt(2000, 7, 2)]),
549 ];
550 for option in options {
551 let result =
552 Adjuster::Following {}.reverse(&option.0, &Calendar::UnionCal(uni.clone()));
553 assert_eq!(result, option.1)
554 }
555
556 let options: Vec<(NaiveDateTime, NaiveDateTime)> = vec![
558 (ndt(2000, 6, 26), ndt(2000, 6, 28)),
559 (ndt(2000, 6, 27), ndt(2000, 6, 28)),
560 (ndt(2000, 6, 28), ndt(2000, 6, 28)),
561 (ndt(2000, 6, 29), ndt(2000, 7, 2)),
562 (ndt(2000, 6, 30), ndt(2000, 7, 2)),
563 (ndt(2000, 7, 1), ndt(2000, 7, 2)),
564 (ndt(2000, 7, 2), ndt(2000, 7, 2)),
565 ];
566 for option in options {
567 let result =
568 Adjuster::FollowingSettle {}.adjust(&option.0, &Calendar::UnionCal(uni.clone()));
569 assert_eq!(result, option.1)
570 }
571
572 let options: Vec<(NaiveDateTime, Vec<NaiveDateTime>)> = vec![
574 (ndt(2000, 6, 26), vec![]),
575 (ndt(2000, 6, 27), vec![]),
576 (
577 ndt(2000, 6, 28),
578 vec![ndt(2000, 6, 28), ndt(2000, 6, 27), ndt(2000, 6, 26)],
579 ),
580 (ndt(2000, 6, 29), vec![]),
581 (ndt(2000, 6, 30), vec![]),
582 (ndt(2000, 7, 1), vec![]),
583 (
584 ndt(2000, 7, 2),
585 vec![
586 ndt(2000, 7, 2),
587 ndt(2000, 7, 1),
588 ndt(2000, 6, 30),
589 ndt(2000, 6, 29),
590 ],
591 ),
592 ];
593 for option in options {
594 let result =
595 Adjuster::FollowingSettle {}.reverse(&option.0, &Calendar::UnionCal(uni.clone()));
596 assert_eq!(result, option.1)
597 }
598 }
599
600 #[test]
601 fn test_backward_book_reverse() {
602 let cal = Cal::new(vec![ndt(2000, 6, 27), ndt(2000, 6, 30)], vec![]);
604 let settle = Cal::new(
605 vec![
606 ndt(2000, 6, 26),
607 ndt(2000, 6, 29),
608 ndt(2000, 6, 30),
609 ndt(2000, 7, 1),
610 ],
611 vec![],
612 );
613 let uni = UnionCal::new(vec![cal], Some(vec![settle]));
614
615 let options: Vec<(NaiveDateTime, NaiveDateTime)> = vec![
617 (ndt(2000, 6, 26), ndt(2000, 6, 26)),
618 (ndt(2000, 6, 27), ndt(2000, 6, 26)),
619 (ndt(2000, 6, 28), ndt(2000, 6, 28)),
620 (ndt(2000, 6, 29), ndt(2000, 6, 29)),
621 (ndt(2000, 6, 30), ndt(2000, 6, 29)),
622 (ndt(2000, 7, 1), ndt(2000, 7, 1)),
623 (ndt(2000, 7, 2), ndt(2000, 7, 2)),
624 ];
625 for option in options {
626 let result = Adjuster::Previous {}.adjust(&option.0, &Calendar::UnionCal(uni.clone()));
627 assert_eq!(result, option.1)
628 }
629
630 let options: Vec<(NaiveDateTime, Vec<NaiveDateTime>)> = vec![
632 (ndt(2000, 6, 26), vec![ndt(2000, 6, 26), ndt(2000, 6, 27)]),
633 (ndt(2000, 6, 27), vec![]),
634 (ndt(2000, 6, 28), vec![ndt(2000, 6, 28)]),
635 (ndt(2000, 6, 29), vec![ndt(2000, 6, 29), ndt(2000, 6, 30)]),
636 (ndt(2000, 6, 30), vec![]),
637 (ndt(2000, 7, 1), vec![ndt(2000, 7, 1)]),
638 (ndt(2000, 7, 2), vec![ndt(2000, 7, 2)]),
639 ];
640 for option in options {
641 let result = Adjuster::Previous {}.reverse(&option.0, &Calendar::UnionCal(uni.clone()));
642 assert_eq!(result, option.1)
643 }
644
645 let options: Vec<(NaiveDateTime, NaiveDateTime)> = vec![
647 (ndt(2000, 6, 26), ndt(2000, 6, 25)),
648 (ndt(2000, 6, 27), ndt(2000, 6, 25)),
649 (ndt(2000, 6, 28), ndt(2000, 6, 28)),
650 (ndt(2000, 6, 29), ndt(2000, 6, 28)),
651 (ndt(2000, 6, 30), ndt(2000, 6, 28)),
652 (ndt(2000, 7, 1), ndt(2000, 6, 28)),
653 (ndt(2000, 7, 2), ndt(2000, 7, 2)),
654 ];
655 for option in options {
656 let result =
657 Adjuster::PreviousSettle {}.adjust(&option.0, &Calendar::UnionCal(uni.clone()));
658 assert_eq!(result, option.1)
659 }
660
661 let options: Vec<(NaiveDateTime, Vec<NaiveDateTime>)> = vec![
663 (
664 ndt(2000, 6, 25),
665 vec![ndt(2000, 6, 25), ndt(2000, 6, 26), ndt(2000, 6, 27)],
666 ),
667 (ndt(2000, 6, 26), vec![]),
668 (ndt(2000, 6, 27), vec![]),
669 (
670 ndt(2000, 6, 28),
671 vec![
672 ndt(2000, 6, 28),
673 ndt(2000, 6, 29),
674 ndt(2000, 6, 30),
675 ndt(2000, 7, 1),
676 ],
677 ),
678 (ndt(2000, 6, 29), vec![]),
679 (ndt(2000, 6, 30), vec![]),
680 (ndt(2000, 7, 1), vec![]),
681 (ndt(2000, 7, 2), vec![ndt(2000, 7, 2)]),
682 ];
683 for option in options {
684 let result =
685 Adjuster::PreviousSettle {}.reverse(&option.0, &Calendar::UnionCal(uni.clone()));
686 assert_eq!(result, option.1)
687 }
688 }
689
690 #[test]
691 fn test_modified_forward_book_reverse() {
692 let cal = Cal::new(vec![ndt(2000, 6, 27), ndt(2000, 6, 30)], vec![]);
694 let settle = Cal::new(
695 vec![
696 ndt(2000, 6, 26),
697 ndt(2000, 6, 29),
698 ndt(2000, 6, 30),
699 ndt(2000, 7, 1),
700 ],
701 vec![],
702 );
703 let uni = UnionCal::new(vec![cal], Some(vec![settle]));
704
705 let options: Vec<(NaiveDateTime, NaiveDateTime)> = vec![
707 (ndt(2000, 6, 26), ndt(2000, 6, 26)),
708 (ndt(2000, 6, 27), ndt(2000, 6, 28)),
709 (ndt(2000, 6, 28), ndt(2000, 6, 28)),
710 (ndt(2000, 6, 29), ndt(2000, 6, 29)),
711 (ndt(2000, 6, 30), ndt(2000, 6, 29)),
712 (ndt(2000, 7, 1), ndt(2000, 7, 1)),
713 (ndt(2000, 7, 2), ndt(2000, 7, 2)),
714 ];
715 for option in options {
716 let result =
717 Adjuster::ModifiedFollowing {}.adjust(&option.0, &Calendar::UnionCal(uni.clone()));
718 assert_eq!(result, option.1)
719 }
720
721 let options: Vec<(NaiveDateTime, Vec<NaiveDateTime>)> = vec![
723 (ndt(2000, 6, 26), vec![ndt(2000, 6, 26)]),
724 (ndt(2000, 6, 27), vec![]),
725 (ndt(2000, 6, 28), vec![ndt(2000, 6, 28), ndt(2000, 6, 27)]),
726 (ndt(2000, 6, 29), vec![ndt(2000, 6, 29), ndt(2000, 6, 30)]),
727 (ndt(2000, 6, 30), vec![]),
728 (ndt(2000, 7, 1), vec![ndt(2000, 7, 1)]),
729 (ndt(2000, 7, 2), vec![ndt(2000, 7, 2)]),
730 ];
731 for option in options {
732 let result =
733 Adjuster::ModifiedFollowing {}.reverse(&option.0, &Calendar::UnionCal(uni.clone()));
734 assert_eq!(result, option.1)
735 }
736
737 let options: Vec<(NaiveDateTime, NaiveDateTime)> = vec![
739 (ndt(2000, 6, 26), ndt(2000, 6, 28)),
740 (ndt(2000, 6, 27), ndt(2000, 6, 28)),
741 (ndt(2000, 6, 28), ndt(2000, 6, 28)),
742 (ndt(2000, 6, 29), ndt(2000, 6, 28)),
743 (ndt(2000, 6, 30), ndt(2000, 6, 28)),
744 (ndt(2000, 7, 1), ndt(2000, 7, 2)),
745 (ndt(2000, 7, 2), ndt(2000, 7, 2)),
746 ];
747 for option in options {
748 let result = Adjuster::ModifiedFollowingSettle {}
749 .adjust(&option.0, &Calendar::UnionCal(uni.clone()));
750 assert_eq!(result, option.1)
751 }
752
753 let options: Vec<(NaiveDateTime, Vec<NaiveDateTime>)> = vec![
755 (ndt(2000, 6, 26), vec![]),
756 (ndt(2000, 6, 27), vec![]),
757 (
758 ndt(2000, 6, 28),
759 vec![
760 ndt(2000, 6, 28),
761 ndt(2000, 6, 27),
762 ndt(2000, 6, 26),
763 ndt(2000, 6, 29),
764 ndt(2000, 6, 30),
765 ],
766 ),
767 (ndt(2000, 6, 29), vec![]),
768 (ndt(2000, 6, 30), vec![]),
769 (ndt(2000, 7, 1), vec![]),
770 (ndt(2000, 7, 2), vec![ndt(2000, 7, 2), ndt(2000, 7, 1)]),
771 ];
772 for option in options {
773 let result = Adjuster::ModifiedFollowingSettle {}
774 .reverse(&option.0, &Calendar::UnionCal(uni.clone()));
775 assert_eq!(result, option.1)
776 }
777 }
778
779 #[test]
780 fn test_modified_backward_book_reverse() {
781 let cal = Cal::new(vec![ndt(2000, 6, 27), ndt(2000, 6, 30)], vec![]);
783 let settle = Cal::new(
784 vec![
785 ndt(2000, 6, 26),
786 ndt(2000, 6, 29),
787 ndt(2000, 6, 30),
788 ndt(2000, 7, 1),
789 ],
790 vec![],
791 );
792 let uni = UnionCal::new(vec![cal], Some(vec![settle]));
793
794 let options: Vec<(NaiveDateTime, NaiveDateTime)> = vec![
796 (ndt(2000, 6, 26), ndt(2000, 6, 26)),
797 (ndt(2000, 6, 27), ndt(2000, 6, 26)),
798 (ndt(2000, 6, 28), ndt(2000, 6, 28)),
799 (ndt(2000, 6, 29), ndt(2000, 6, 29)),
800 (ndt(2000, 6, 30), ndt(2000, 6, 29)),
801 (ndt(2000, 7, 1), ndt(2000, 7, 1)),
802 (ndt(2000, 7, 2), ndt(2000, 7, 2)),
803 ];
804 for option in options {
805 let result =
806 Adjuster::ModifiedPrevious {}.adjust(&option.0, &Calendar::UnionCal(uni.clone()));
807 assert_eq!(result, option.1)
808 }
809
810 let options: Vec<(NaiveDateTime, Vec<NaiveDateTime>)> = vec![
812 (ndt(2000, 6, 25), vec![ndt(2000, 6, 25)]),
813 (ndt(2000, 6, 26), vec![ndt(2000, 6, 26), ndt(2000, 6, 27)]),
814 (ndt(2000, 6, 27), vec![]),
815 (ndt(2000, 6, 28), vec![ndt(2000, 6, 28)]),
816 (ndt(2000, 6, 29), vec![ndt(2000, 6, 29), ndt(2000, 6, 30)]),
817 (ndt(2000, 6, 30), vec![]),
818 (ndt(2000, 7, 1), vec![ndt(2000, 7, 1)]),
819 (ndt(2000, 7, 2), vec![ndt(2000, 7, 2)]),
820 ];
821 for option in options {
822 let result =
823 Adjuster::ModifiedPrevious {}.reverse(&option.0, &Calendar::UnionCal(uni.clone()));
824 assert_eq!(result, option.1)
825 }
826
827 let options: Vec<(NaiveDateTime, NaiveDateTime)> = vec![
829 (ndt(2000, 6, 26), ndt(2000, 6, 25)),
830 (ndt(2000, 6, 27), ndt(2000, 6, 25)),
831 (ndt(2000, 6, 28), ndt(2000, 6, 28)),
832 (ndt(2000, 6, 29), ndt(2000, 6, 28)),
833 (ndt(2000, 6, 30), ndt(2000, 6, 28)),
834 (ndt(2000, 7, 1), ndt(2000, 7, 2)),
835 (ndt(2000, 7, 2), ndt(2000, 7, 2)),
836 ];
837 for option in options {
838 let result = Adjuster::ModifiedPreviousSettle {}
839 .adjust(&option.0, &Calendar::UnionCal(uni.clone()));
840 assert_eq!(result, option.1)
841 }
842
843 let options: Vec<(NaiveDateTime, Vec<NaiveDateTime>)> = vec![
845 (
846 ndt(2000, 6, 25),
847 vec![ndt(2000, 6, 25), ndt(2000, 6, 26), ndt(2000, 6, 27)],
848 ),
849 (ndt(2000, 6, 26), vec![]),
850 (ndt(2000, 6, 27), vec![]),
851 (
852 ndt(2000, 6, 28),
853 vec![ndt(2000, 6, 28), ndt(2000, 6, 29), ndt(2000, 6, 30)],
854 ),
855 (ndt(2000, 6, 29), vec![]),
856 (ndt(2000, 6, 30), vec![]),
857 (ndt(2000, 7, 1), vec![]),
858 (ndt(2000, 7, 2), vec![ndt(2000, 7, 2), ndt(2000, 7, 1)]),
859 ];
860 for option in options {
861 let result = Adjuster::ModifiedPreviousSettle {}
862 .reverse(&option.0, &Calendar::UnionCal(uni.clone()));
863 assert_eq!(result, option.1)
864 }
865 }
866
867 #[test]
868 fn test_bus_days_lag_settle_reverse() {
869 let cal = Cal::new(vec![ndt(2000, 6, 27), ndt(2000, 6, 30)], vec![]);
871 let settle = Cal::new(
872 vec![
873 ndt(2000, 6, 26),
874 ndt(2000, 6, 29),
875 ndt(2000, 6, 30),
876 ndt(2000, 7, 1),
877 ],
878 vec![],
879 );
880 let uni = UnionCal::new(vec![cal], Some(vec![settle]));
881
882 let options: Vec<(NaiveDateTime, NaiveDateTime)> = vec![
884 (ndt(2000, 6, 25), ndt(2000, 6, 28)),
885 (ndt(2000, 6, 26), ndt(2000, 7, 2)),
886 (ndt(2000, 6, 27), ndt(2000, 7, 2)),
887 (ndt(2000, 6, 28), ndt(2000, 7, 2)),
888 (ndt(2000, 6, 29), ndt(2000, 7, 2)),
889 (ndt(2000, 6, 30), ndt(2000, 7, 2)),
890 ];
891 for option in options {
892 let result =
893 Adjuster::BusDaysLagSettle(2).adjust(&option.0, &Calendar::UnionCal(uni.clone()));
894 assert_eq!(result, option.1)
895 }
896
897 let options: Vec<(NaiveDateTime, Vec<NaiveDateTime>)> = vec![
899 (ndt(2000, 6, 28), vec![ndt(2000, 6, 25), ndt(2000, 6, 24)]),
900 (ndt(2000, 6, 29), vec![]),
901 (ndt(2000, 6, 30), vec![]),
902 (ndt(2000, 7, 1), vec![]),
903 (
904 ndt(2000, 7, 2),
905 vec![
906 ndt(2000, 6, 30),
907 ndt(2000, 6, 29),
908 ndt(2000, 6, 28),
909 ndt(2000, 6, 27),
910 ndt(2000, 6, 26),
911 ],
912 ),
913 ];
914 for option in options {
915 let result =
916 Adjuster::BusDaysLagSettle(2).reverse(&option.0, &Calendar::UnionCal(uni.clone()));
917 assert_eq!(result, option.1)
918 }
919
920 let options: Vec<(NaiveDateTime, NaiveDateTime)> = vec![
922 (ndt(2000, 6, 25), ndt(2000, 6, 28)),
923 (ndt(2000, 6, 26), ndt(2000, 6, 28)),
924 (ndt(2000, 6, 27), ndt(2000, 6, 28)),
925 (ndt(2000, 6, 28), ndt(2000, 7, 2)),
926 (ndt(2000, 6, 29), ndt(2000, 7, 2)),
927 (ndt(2000, 6, 30), ndt(2000, 7, 2)),
928 (ndt(2000, 7, 1), ndt(2000, 7, 2)),
929 ];
930 for option in options {
931 let result =
932 Adjuster::BusDaysLagSettle(1).adjust(&option.0, &Calendar::UnionCal(uni.clone()));
933 assert_eq!(result, option.1)
934 }
935
936 let options: Vec<(NaiveDateTime, Vec<NaiveDateTime>)> = vec![
938 (
939 ndt(2000, 6, 28),
940 vec![ndt(2000, 6, 27), ndt(2000, 6, 26), ndt(2000, 6, 25)],
941 ),
942 (ndt(2000, 6, 29), vec![]),
943 (ndt(2000, 6, 30), vec![]),
944 (ndt(2000, 7, 1), vec![]),
945 (
946 ndt(2000, 7, 2),
947 vec![
948 ndt(2000, 7, 1),
949 ndt(2000, 6, 30),
950 ndt(2000, 6, 29),
951 ndt(2000, 6, 28),
952 ],
953 ),
954 ];
955 for option in options {
956 let result =
957 Adjuster::BusDaysLagSettle(1).reverse(&option.0, &Calendar::UnionCal(uni.clone()));
958 assert_eq!(result, option.1)
959 }
960
961 let options: Vec<(NaiveDateTime, NaiveDateTime)> = vec![
963 (ndt(2000, 6, 25), ndt(2000, 6, 25)),
964 (ndt(2000, 6, 26), ndt(2000, 6, 28)),
965 (ndt(2000, 6, 27), ndt(2000, 6, 28)),
966 (ndt(2000, 6, 28), ndt(2000, 6, 28)),
967 (ndt(2000, 6, 29), ndt(2000, 7, 2)),
968 (ndt(2000, 6, 30), ndt(2000, 7, 2)),
969 (ndt(2000, 7, 1), ndt(2000, 7, 2)),
970 (ndt(2000, 7, 2), ndt(2000, 7, 2)),
971 ];
972 for option in options {
973 let result =
974 Adjuster::BusDaysLagSettle(0).adjust(&option.0, &Calendar::UnionCal(uni.clone()));
975 assert_eq!(result, option.1)
976 }
977
978 let options: Vec<(NaiveDateTime, Vec<NaiveDateTime>)> = vec![
980 (ndt(2000, 6, 25), vec![ndt(2000, 6, 25)]),
981 (
982 ndt(2000, 6, 28),
983 vec![ndt(2000, 6, 28), ndt(2000, 6, 27), ndt(2000, 6, 26)],
984 ),
985 (ndt(2000, 6, 29), vec![]),
986 (ndt(2000, 6, 30), vec![]),
987 (ndt(2000, 7, 1), vec![]),
988 (
989 ndt(2000, 7, 2),
990 vec![
991 ndt(2000, 7, 2),
992 ndt(2000, 7, 1),
993 ndt(2000, 6, 30),
994 ndt(2000, 6, 29),
995 ],
996 ),
997 ];
998 for option in options {
999 let result =
1000 Adjuster::BusDaysLagSettle(0).reverse(&option.0, &Calendar::UnionCal(uni.clone()));
1001 assert_eq!(result, option.1)
1002 }
1003 }
1004}