1use crate::{
2 error::{
3 unit::{MustDivide, UnitConfigError},
4 util::RoundingIncrementError,
5 Error, ErrorContext,
6 },
7 util::b,
8 SignedDuration, Unit,
9};
10
11#[derive(Clone, Copy, Debug)]
32pub(crate) struct Increment {
33 unit: Unit,
34 value: i32,
35}
36
37impl Increment {
38 pub(crate) fn for_span(
40 unit: Unit,
41 value: i64,
42 ) -> Result<Increment, Error> {
43 static LIMITS: &[MustDivide] = &[
45 MustDivide::NanosPerMicro,
46 MustDivide::MicrosPerMilli,
47 MustDivide::MillisPerSec,
48 MustDivide::SecsPerMin,
49 MustDivide::MinsPerHour,
50 MustDivide::HoursPerCivilDay,
51 ];
52
53 if unit < Unit::Day {
60 Increment::for_limits(unit, value, LIMITS)
61 .context(RoundingIncrementError::ForSpan)
62 } else {
63 let value = b::Increment32::check(value)
66 .context(RoundingIncrementError::ForSpan)?;
67 Ok(Increment { unit, value })
68 }
69 }
70
71 pub(crate) fn for_signed_duration(
74 unit: Unit,
75 value: i64,
76 ) -> Result<Increment, Error> {
77 if unit > Unit::Hour {
78 return Err(Error::from(
79 UnitConfigError::SignedDurationCalendarUnit { smallest: unit },
80 ));
81 }
82
83 let value = b::Increment32::check(value)
85 .context(RoundingIncrementError::ForSignedDuration)?;
86 Ok(Increment { unit, value })
87 }
88
89 pub(crate) fn for_offset(
92 unit: Unit,
93 value: i64,
94 ) -> Result<Increment, Error> {
95 if !(Unit::Second <= unit && unit <= Unit::Hour) {
96 return Err(Error::from(UnitConfigError::TimeZoneOffset {
97 given: unit,
98 }));
99 }
100
101 let value = b::Increment32::check(value)
103 .context(RoundingIncrementError::ForOffset)?;
104 Ok(Increment { unit, value })
105 }
106
107 pub(crate) fn for_datetime(
110 unit: Unit,
111 value: i64,
112 ) -> Result<Increment, Error> {
113 static LIMITS: &[MustDivide] = &[
115 MustDivide::NanosPerMicro,
116 MustDivide::MicrosPerMilli,
117 MustDivide::MillisPerSec,
118 MustDivide::SecsPerMin,
119 MustDivide::MinsPerHour,
120 MustDivide::HoursPerCivilDay,
121 MustDivide::Days,
122 ];
123 Increment::for_limits(unit, value, LIMITS)
124 .context(RoundingIncrementError::ForDateTime)
125 }
126
127 pub(crate) fn for_time(
130 unit: Unit,
131 value: i64,
132 ) -> Result<Increment, Error> {
133 static LIMITS: &[MustDivide] = &[
135 MustDivide::NanosPerMicro,
136 MustDivide::MicrosPerMilli,
137 MustDivide::MillisPerSec,
138 MustDivide::SecsPerMin,
139 MustDivide::MinsPerHour,
140 MustDivide::HoursPerCivilDay,
141 ];
142 Increment::for_limits(unit, value, LIMITS)
143 .context(RoundingIncrementError::ForTime)
144 }
145
146 pub(crate) fn for_timestamp(
149 unit: Unit,
150 value: i64,
151 ) -> Result<Increment, Error> {
152 static MAXIMUMS: &[MustDivide] = &[
154 MustDivide::NanosPerCivilDay,
155 MustDivide::MicrosPerCivilDay,
156 MustDivide::MillisPerCivilDay,
157 MustDivide::SecsPerCivilDay,
158 MustDivide::MinsPerCivilDay,
159 MustDivide::HoursPerCivilDay,
160 ];
161 Increment::for_maximums(unit, value, MAXIMUMS)
162 .context(RoundingIncrementError::ForTimestamp)
163 }
164
165 pub(crate) fn round(
169 &self,
170 mode: RoundMode,
171 quantity: SignedDuration,
172 ) -> Result<SignedDuration, Error> {
173 let increment = self.value() * self.unit().duration();
178 mode.round_by_duration(quantity, increment)
179 }
180
181 pub(crate) fn unit(&self) -> Unit {
185 self.unit
186 }
187
188 pub(crate) fn value(&self) -> i32 {
196 self.value
197 }
198}
199
200impl Increment {
203 fn for_limits(
209 unit: Unit,
210 value: i64,
211 limits: &[MustDivide],
212 ) -> Result<Increment, Error> {
213 let Some(&must_divide) = limits.get(unit as usize) else {
214 return Err(Error::from(
215 UnitConfigError::RoundToUnitUnsupported { unit },
216 ));
217 };
218
219 let value32 = b::Increment32::check(value)?;
220 let must_divide_i64 = must_divide.as_i64();
221 if value < must_divide_i64 && must_divide_i64 % value == 0 {
222 return Ok(Increment { unit, value: value32 });
223 }
224 Err(Error::from(UnitConfigError::IncrementDivide {
225 unit,
226 must_divide,
227 }))
228 }
229
230 fn for_maximums(
236 unit: Unit,
237 value: i64,
238 maximums: &[MustDivide],
239 ) -> Result<Increment, Error> {
240 let Some(&must_divide) = maximums.get(unit as usize) else {
241 return Err(Error::from(
242 UnitConfigError::RoundToUnitUnsupported { unit },
243 ));
244 };
245
246 let value32 = b::Increment32::check(value)?;
247 let must_divide_i64 = must_divide.as_i64();
248 if value <= must_divide_i64 && must_divide_i64 % value == 0 {
249 return Ok(Increment { unit, value: value32 });
250 }
251 Err(Error::from(UnitConfigError::IncrementDivide {
252 unit,
253 must_divide,
254 }))
255 }
256}
257
258#[non_exhaustive]
293#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
294pub enum RoundMode {
295 Ceil,
301 Floor,
307 Expand,
310 Trunc,
316 HalfCeil,
319 HalfFloor,
322 HalfExpand,
331 HalfTrunc,
334 HalfEven,
340}
341
342impl RoundMode {
343 pub(crate) fn round_by_duration(
357 self,
358 quantity: SignedDuration,
359 increment: SignedDuration,
360 ) -> Result<SignedDuration, Error> {
361 let quantity = quantity.as_nanos();
362 let increment = increment.as_nanos();
363 assert!(increment >= 1);
364 let rounded = self.round_by_i128(quantity, increment);
365 SignedDuration::try_from_nanos_i128(rounded)
382 .ok_or_else(|| Error::from(b::SignedDurationSeconds::error()))
383 }
384
385 fn round_by_i128(self, quantity: i128, increment: i128) -> i128 {
401 assert!(increment >= 1);
402 let mode = self;
404 let mut quotient = quantity / increment;
405 let remainder = quantity % increment;
406 if remainder == 0 {
407 return quantity;
408 }
409 let sign = if remainder < 0 { -1 } else { 1 };
410 let tiebreaker = (remainder * 2).abs();
411 let tie = tiebreaker == increment;
412 let expand_is_nearer = tiebreaker > increment;
413 match mode {
415 RoundMode::Ceil => {
416 if sign > 0 {
417 quotient += sign;
418 }
419 }
420 RoundMode::Floor => {
421 if sign < 0 {
422 quotient += sign;
423 }
424 }
425 RoundMode::Expand => {
426 quotient += sign;
427 }
428 RoundMode::Trunc => {}
429 RoundMode::HalfCeil => {
430 if expand_is_nearer || (tie && sign > 0) {
431 quotient += sign;
432 }
433 }
434 RoundMode::HalfFloor => {
435 if expand_is_nearer || (tie && sign < 0) {
436 quotient += sign;
437 }
438 }
439 RoundMode::HalfExpand => {
440 if expand_is_nearer || tie {
441 quotient += sign;
442 }
443 }
444 RoundMode::HalfTrunc => {
445 if expand_is_nearer {
446 quotient += sign;
447 }
448 }
449 RoundMode::HalfEven => {
450 if expand_is_nearer || (tie && quotient.rem_euclid(2) == 1) {
451 quotient += sign;
452 }
453 }
454 }
455 quotient.saturating_mul(increment)
461 }
462}
463
464#[cfg(test)]
465mod tests {
466 use super::*;
467
468 #[test]
469 fn for_span() {
470 let get = |unit, value| Increment::for_span(unit, value);
471
472 assert!(get(Unit::Nanosecond, 1).is_ok());
473 assert!(get(Unit::Nanosecond, 500).is_ok());
474 assert!(get(Unit::Nanosecond, -1).is_err());
475 assert!(get(Unit::Nanosecond, 0).is_err());
476 assert!(get(Unit::Nanosecond, 7).is_err());
477 assert!(get(Unit::Nanosecond, 1_000).is_err());
478 assert!(get(Unit::Nanosecond, i64::MIN).is_err());
479 assert!(get(Unit::Nanosecond, i64::MAX).is_err());
480
481 assert!(get(Unit::Microsecond, 1).is_ok());
482 assert!(get(Unit::Microsecond, 500).is_ok());
483 assert!(get(Unit::Microsecond, -1).is_err());
484 assert!(get(Unit::Microsecond, 0).is_err());
485 assert!(get(Unit::Microsecond, 7).is_err());
486 assert!(get(Unit::Microsecond, 1_000).is_err());
487 assert!(get(Unit::Microsecond, i64::MIN).is_err());
488 assert!(get(Unit::Microsecond, i64::MAX).is_err());
489
490 assert!(get(Unit::Millisecond, 1).is_ok());
491 assert!(get(Unit::Millisecond, 500).is_ok());
492 assert!(get(Unit::Millisecond, -1).is_err());
493 assert!(get(Unit::Millisecond, 0).is_err());
494 assert!(get(Unit::Millisecond, 7).is_err());
495 assert!(get(Unit::Millisecond, 1_000).is_err());
496 assert!(get(Unit::Millisecond, i64::MIN).is_err());
497 assert!(get(Unit::Millisecond, i64::MAX).is_err());
498
499 assert!(get(Unit::Second, 1).is_ok());
500 assert!(get(Unit::Second, 15).is_ok());
501 assert!(get(Unit::Second, -1).is_err());
502 assert!(get(Unit::Second, 0).is_err());
503 assert!(get(Unit::Second, 7).is_err());
504 assert!(get(Unit::Second, 1_000).is_err());
505 assert!(get(Unit::Second, i64::MIN).is_err());
506 assert!(get(Unit::Second, i64::MAX).is_err());
507
508 assert!(get(Unit::Minute, 1).is_ok());
509 assert!(get(Unit::Minute, 15).is_ok());
510 assert!(get(Unit::Minute, -1).is_err());
511 assert!(get(Unit::Minute, 0).is_err());
512 assert!(get(Unit::Minute, 7).is_err());
513 assert!(get(Unit::Minute, 1_000).is_err());
514 assert!(get(Unit::Minute, i64::MIN).is_err());
515 assert!(get(Unit::Minute, i64::MAX).is_err());
516
517 assert!(get(Unit::Hour, 1).is_ok());
518 assert!(get(Unit::Hour, 6).is_ok());
519 assert!(get(Unit::Hour, 12).is_ok());
520 assert!(get(Unit::Hour, -1).is_err());
521 assert!(get(Unit::Hour, 0).is_err());
522 assert!(get(Unit::Hour, 15).is_err());
523 assert!(get(Unit::Hour, 18).is_err());
524 assert!(get(Unit::Hour, 23).is_err());
525 assert!(get(Unit::Hour, 24).is_err());
526 assert!(get(Unit::Hour, i64::MIN).is_err());
527 assert!(get(Unit::Hour, i64::MAX).is_err());
528
529 assert!(get(Unit::Day, 1).is_ok());
530 assert!(get(Unit::Day, 6).is_ok());
531 assert!(get(Unit::Day, 7).is_ok());
532 assert!(get(Unit::Day, 12).is_ok());
533 assert!(get(Unit::Day, 30).is_ok());
534 assert!(get(Unit::Day, 31).is_ok());
535 assert!(get(Unit::Day, 100).is_ok());
536 assert!(get(Unit::Day, 10_000_000).is_ok());
537 assert!(get(Unit::Day, 1_000_000_000).is_ok());
538 assert!(get(Unit::Day, -1).is_err());
539 assert!(get(Unit::Day, 0).is_err());
540 assert!(get(Unit::Day, 1_000_000_001).is_err());
541 assert!(get(Unit::Day, i64::MIN).is_err());
542 assert!(get(Unit::Day, i64::MAX).is_err());
543
544 assert!(get(Unit::Week, 1).is_ok());
545 assert!(get(Unit::Week, 6).is_ok());
546 assert!(get(Unit::Week, 7).is_ok());
547 assert!(get(Unit::Week, 12).is_ok());
548 assert!(get(Unit::Week, 30).is_ok());
549 assert!(get(Unit::Week, 31).is_ok());
550 assert!(get(Unit::Week, 100).is_ok());
551 assert!(get(Unit::Week, 2_000_000).is_ok());
552 assert!(get(Unit::Week, 1_000_000_000).is_ok());
553 assert!(get(Unit::Week, -1).is_err());
554 assert!(get(Unit::Week, 0).is_err());
555 assert!(get(Unit::Week, 1_000_000_001).is_err());
556 assert!(get(Unit::Week, i64::MIN).is_err());
557 assert!(get(Unit::Week, i64::MAX).is_err());
558
559 assert!(get(Unit::Month, 1).is_ok());
560 assert!(get(Unit::Month, 6).is_ok());
561 assert!(get(Unit::Month, 7).is_ok());
562 assert!(get(Unit::Month, 12).is_ok());
563 assert!(get(Unit::Month, 30).is_ok());
564 assert!(get(Unit::Month, 31).is_ok());
565 assert!(get(Unit::Month, 100).is_ok());
566 assert!(get(Unit::Month, 300_000).is_ok());
567 assert!(get(Unit::Month, 1_000_000_000).is_ok());
568 assert!(get(Unit::Month, -1).is_err());
569 assert!(get(Unit::Month, 0).is_err());
570 assert!(get(Unit::Month, 1_000_000_001).is_err());
571 assert!(get(Unit::Month, i64::MIN).is_err());
572 assert!(get(Unit::Month, i64::MAX).is_err());
573
574 assert!(get(Unit::Year, 1).is_ok());
575 assert!(get(Unit::Year, 6).is_ok());
576 assert!(get(Unit::Year, 7).is_ok());
577 assert!(get(Unit::Year, 12).is_ok());
578 assert!(get(Unit::Year, 30).is_ok());
579 assert!(get(Unit::Year, 31).is_ok());
580 assert!(get(Unit::Year, 100).is_ok());
581 assert!(get(Unit::Year, 50_000).is_ok());
582 assert!(get(Unit::Year, 1_000_000_000).is_ok());
583 assert!(get(Unit::Year, -1).is_err());
584 assert!(get(Unit::Year, 0).is_err());
585 assert!(get(Unit::Year, 1_000_000_001).is_err());
586 assert!(get(Unit::Year, i64::MIN).is_err());
587 assert!(get(Unit::Year, i64::MAX).is_err());
588 }
589
590 #[test]
591 fn for_datetime() {
592 let get = |unit, value| Increment::for_datetime(unit, value);
593
594 assert!(get(Unit::Nanosecond, 1).is_ok());
595 assert!(get(Unit::Nanosecond, 500).is_ok());
596 assert!(get(Unit::Nanosecond, -1).is_err());
597 assert!(get(Unit::Nanosecond, 0).is_err());
598 assert!(get(Unit::Nanosecond, 7).is_err());
599 assert!(get(Unit::Nanosecond, 1_000).is_err());
600 assert!(get(Unit::Nanosecond, i64::MIN).is_err());
601 assert!(get(Unit::Nanosecond, i64::MAX).is_err());
602
603 assert!(get(Unit::Microsecond, 1).is_ok());
604 assert!(get(Unit::Microsecond, 500).is_ok());
605 assert!(get(Unit::Microsecond, -1).is_err());
606 assert!(get(Unit::Microsecond, 0).is_err());
607 assert!(get(Unit::Microsecond, 7).is_err());
608 assert!(get(Unit::Microsecond, 1_000).is_err());
609 assert!(get(Unit::Microsecond, i64::MIN).is_err());
610 assert!(get(Unit::Microsecond, i64::MAX).is_err());
611
612 assert!(get(Unit::Millisecond, 1).is_ok());
613 assert!(get(Unit::Millisecond, 500).is_ok());
614 assert!(get(Unit::Millisecond, -1).is_err());
615 assert!(get(Unit::Millisecond, 0).is_err());
616 assert!(get(Unit::Millisecond, 7).is_err());
617 assert!(get(Unit::Millisecond, 1_000).is_err());
618 assert!(get(Unit::Millisecond, i64::MIN).is_err());
619 assert!(get(Unit::Millisecond, i64::MAX).is_err());
620
621 assert!(get(Unit::Second, 1).is_ok());
622 assert!(get(Unit::Second, 15).is_ok());
623 assert!(get(Unit::Second, -1).is_err());
624 assert!(get(Unit::Second, 0).is_err());
625 assert!(get(Unit::Second, 7).is_err());
626 assert!(get(Unit::Second, 1_000).is_err());
627 assert!(get(Unit::Second, i64::MIN).is_err());
628 assert!(get(Unit::Second, i64::MAX).is_err());
629
630 assert!(get(Unit::Minute, 1).is_ok());
631 assert!(get(Unit::Minute, 15).is_ok());
632 assert!(get(Unit::Minute, -1).is_err());
633 assert!(get(Unit::Minute, 0).is_err());
634 assert!(get(Unit::Minute, 7).is_err());
635 assert!(get(Unit::Minute, 1_000).is_err());
636 assert!(get(Unit::Minute, i64::MIN).is_err());
637 assert!(get(Unit::Minute, i64::MAX).is_err());
638
639 assert!(get(Unit::Hour, 1).is_ok());
640 assert!(get(Unit::Hour, 6).is_ok());
641 assert!(get(Unit::Hour, 12).is_ok());
642 assert!(get(Unit::Hour, -1).is_err());
643 assert!(get(Unit::Hour, 0).is_err());
644 assert!(get(Unit::Hour, 15).is_err());
645 assert!(get(Unit::Hour, 18).is_err());
646 assert!(get(Unit::Hour, 23).is_err());
647 assert!(get(Unit::Hour, 24).is_err());
648 assert!(get(Unit::Hour, i64::MIN).is_err());
649 assert!(get(Unit::Hour, i64::MAX).is_err());
650
651 assert!(get(Unit::Day, 1).is_ok());
652 assert!(get(Unit::Day, -1).is_err());
653 assert!(get(Unit::Day, 0).is_err());
654 assert!(get(Unit::Day, 2).is_err());
655 assert!(get(Unit::Day, 4).is_err());
656 assert!(get(Unit::Day, 7).is_err());
657 assert!(get(Unit::Day, i64::MIN).is_err());
658 assert!(get(Unit::Day, i64::MAX).is_err());
659 }
660
661 #[test]
662 fn for_time() {
663 let get = |unit, value| Increment::for_time(unit, value);
664
665 assert!(get(Unit::Nanosecond, 1).is_ok());
666 assert!(get(Unit::Nanosecond, 500).is_ok());
667 assert!(get(Unit::Nanosecond, -1).is_err());
668 assert!(get(Unit::Nanosecond, 0).is_err());
669 assert!(get(Unit::Nanosecond, 7).is_err());
670 assert!(get(Unit::Nanosecond, 1_000).is_err());
671 assert!(get(Unit::Nanosecond, i64::MIN).is_err());
672 assert!(get(Unit::Nanosecond, i64::MAX).is_err());
673
674 assert!(get(Unit::Microsecond, 1).is_ok());
675 assert!(get(Unit::Microsecond, 500).is_ok());
676 assert!(get(Unit::Microsecond, -1).is_err());
677 assert!(get(Unit::Microsecond, 0).is_err());
678 assert!(get(Unit::Microsecond, 7).is_err());
679 assert!(get(Unit::Microsecond, 1_000).is_err());
680 assert!(get(Unit::Microsecond, i64::MIN).is_err());
681 assert!(get(Unit::Microsecond, i64::MAX).is_err());
682
683 assert!(get(Unit::Millisecond, 1).is_ok());
684 assert!(get(Unit::Millisecond, 500).is_ok());
685 assert!(get(Unit::Millisecond, -1).is_err());
686 assert!(get(Unit::Millisecond, 0).is_err());
687 assert!(get(Unit::Millisecond, 7).is_err());
688 assert!(get(Unit::Millisecond, 1_000).is_err());
689 assert!(get(Unit::Millisecond, i64::MIN).is_err());
690 assert!(get(Unit::Millisecond, i64::MAX).is_err());
691
692 assert!(get(Unit::Second, 1).is_ok());
693 assert!(get(Unit::Second, 15).is_ok());
694 assert!(get(Unit::Second, -1).is_err());
695 assert!(get(Unit::Second, 0).is_err());
696 assert!(get(Unit::Second, 7).is_err());
697 assert!(get(Unit::Second, 1_000).is_err());
698 assert!(get(Unit::Second, i64::MIN).is_err());
699 assert!(get(Unit::Second, i64::MAX).is_err());
700
701 assert!(get(Unit::Minute, 1).is_ok());
702 assert!(get(Unit::Minute, 15).is_ok());
703 assert!(get(Unit::Minute, -1).is_err());
704 assert!(get(Unit::Minute, 0).is_err());
705 assert!(get(Unit::Minute, 7).is_err());
706 assert!(get(Unit::Minute, 1_000).is_err());
707 assert!(get(Unit::Minute, i64::MIN).is_err());
708 assert!(get(Unit::Minute, i64::MAX).is_err());
709
710 assert!(get(Unit::Hour, 1).is_ok());
711 assert!(get(Unit::Hour, 6).is_ok());
712 assert!(get(Unit::Hour, 12).is_ok());
713 assert!(get(Unit::Hour, -1).is_err());
714 assert!(get(Unit::Hour, 0).is_err());
715 assert!(get(Unit::Hour, 15).is_err());
716 assert!(get(Unit::Hour, 18).is_err());
717 assert!(get(Unit::Hour, 23).is_err());
718 assert!(get(Unit::Hour, 24).is_err());
719 assert!(get(Unit::Hour, i64::MIN).is_err());
720 assert!(get(Unit::Hour, i64::MAX).is_err());
721
722 assert!(get(Unit::Day, 1).is_err());
723 assert!(get(Unit::Day, -1).is_err());
724 assert!(get(Unit::Day, 0).is_err());
725 assert!(get(Unit::Day, 2).is_err());
726 assert!(get(Unit::Day, 4).is_err());
727 assert!(get(Unit::Day, 7).is_err());
728 assert!(get(Unit::Day, i64::MIN).is_err());
729 assert!(get(Unit::Day, i64::MAX).is_err());
730 }
731
732 #[test]
733 fn for_timestamp() {
734 let get = |unit, value| Increment::for_timestamp(unit, value);
735
736 assert!(get(Unit::Nanosecond, 1).is_ok());
737 assert!(get(Unit::Nanosecond, 500).is_ok());
738 assert!(get(Unit::Nanosecond, 1_000).is_ok());
739 assert!(get(Unit::Nanosecond, 1_000_000_000).is_ok());
740 assert!(get(Unit::Nanosecond, -1).is_err());
741 assert!(get(Unit::Nanosecond, 0).is_err());
742 assert!(get(Unit::Nanosecond, 7).is_err());
743 assert!(get(Unit::Nanosecond, 1_000_000_001).is_err());
744 assert!(get(Unit::Nanosecond, i64::MIN).is_err());
745 assert!(get(Unit::Nanosecond, i64::MAX).is_err());
746
747 assert!(get(Unit::Microsecond, 1).is_ok());
748 assert!(get(Unit::Microsecond, 500).is_ok());
749 assert!(get(Unit::Microsecond, 1_000).is_ok());
750 assert!(get(Unit::Microsecond, 2_000).is_ok());
751 assert!(get(Unit::Microsecond, -1).is_err());
752 assert!(get(Unit::Microsecond, 0).is_err());
753 assert!(get(Unit::Microsecond, 7).is_err());
754 assert!(get(Unit::Microsecond, 1_000_000_000).is_err());
755 assert!(get(Unit::Microsecond, 1_000_000_001).is_err());
756 assert!(get(Unit::Microsecond, i64::MIN).is_err());
757 assert!(get(Unit::Microsecond, i64::MAX).is_err());
758
759 assert!(get(Unit::Millisecond, 1).is_ok());
760 assert!(get(Unit::Millisecond, 500).is_ok());
761 assert!(get(Unit::Millisecond, 1_000).is_ok());
762 assert!(get(Unit::Millisecond, 2_000).is_ok());
763 assert!(get(Unit::Millisecond, 86_400_000).is_ok());
764 assert!(get(Unit::Millisecond, -1).is_err());
765 assert!(get(Unit::Millisecond, 0).is_err());
766 assert!(get(Unit::Millisecond, 7).is_err());
767 assert!(get(Unit::Millisecond, 1_000_000_000).is_err());
768 assert!(get(Unit::Millisecond, 1_000_000_001).is_err());
769 assert!(get(Unit::Millisecond, i64::MIN).is_err());
770 assert!(get(Unit::Millisecond, i64::MAX).is_err());
771
772 assert!(get(Unit::Second, 1).is_ok());
773 assert!(get(Unit::Second, 15).is_ok());
774 assert!(get(Unit::Second, 3_600).is_ok());
775 assert!(get(Unit::Second, 86_400).is_ok());
776 assert!(get(Unit::Second, -1).is_err());
777 assert!(get(Unit::Second, 0).is_err());
778 assert!(get(Unit::Second, 7).is_err());
779 assert!(get(Unit::Second, 1_000).is_err());
780 assert!(get(Unit::Second, 86_401).is_err());
781 assert!(get(Unit::Second, 172_800).is_err());
782 assert!(get(Unit::Second, 1_000_000_000).is_err());
783 assert!(get(Unit::Second, 1_000_000_001).is_err());
784 assert!(get(Unit::Second, i64::MIN).is_err());
785 assert!(get(Unit::Second, i64::MAX).is_err());
786
787 assert!(get(Unit::Minute, 1).is_ok());
788 assert!(get(Unit::Minute, 15).is_ok());
789 assert!(get(Unit::Minute, 1_440).is_ok());
790 assert!(get(Unit::Minute, -1).is_err());
791 assert!(get(Unit::Minute, 0).is_err());
792 assert!(get(Unit::Minute, 7).is_err());
793 assert!(get(Unit::Minute, 1_000).is_err());
794 assert!(get(Unit::Minute, 1_441).is_err());
795 assert!(get(Unit::Minute, 2_880).is_err());
796 assert!(get(Unit::Minute, 1_000_000_000).is_err());
797 assert!(get(Unit::Minute, 1_000_000_001).is_err());
798 assert!(get(Unit::Minute, i64::MIN).is_err());
799 assert!(get(Unit::Minute, i64::MAX).is_err());
800
801 assert!(get(Unit::Hour, 1).is_ok());
802 assert!(get(Unit::Hour, 6).is_ok());
803 assert!(get(Unit::Hour, 12).is_ok());
804 assert!(get(Unit::Hour, 24).is_ok());
805 assert!(get(Unit::Hour, -1).is_err());
806 assert!(get(Unit::Hour, 0).is_err());
807 assert!(get(Unit::Hour, 15).is_err());
808 assert!(get(Unit::Hour, 18).is_err());
809 assert!(get(Unit::Hour, 23).is_err());
810 assert!(get(Unit::Hour, 25).is_err());
811 assert!(get(Unit::Hour, 1_000_000_000).is_err());
812 assert!(get(Unit::Hour, 1_000_000_001).is_err());
813 assert!(get(Unit::Hour, i64::MIN).is_err());
814 assert!(get(Unit::Hour, i64::MAX).is_err());
815
816 assert!(get(Unit::Day, 1).is_err());
817 assert!(get(Unit::Day, -1).is_err());
818 assert!(get(Unit::Day, 0).is_err());
819 assert!(get(Unit::Day, 2).is_err());
820 assert!(get(Unit::Day, 4).is_err());
821 assert!(get(Unit::Day, 7).is_err());
822 assert!(get(Unit::Day, i64::MIN).is_err());
823 assert!(get(Unit::Day, i64::MAX).is_err());
824
825 assert!(get(Unit::Week, 1).is_err());
826 assert!(get(Unit::Week, -1).is_err());
827 assert!(get(Unit::Week, 0).is_err());
828 assert!(get(Unit::Week, 2).is_err());
829 assert!(get(Unit::Week, 4).is_err());
830 assert!(get(Unit::Week, 7).is_err());
831 assert!(get(Unit::Week, i64::MIN).is_err());
832 assert!(get(Unit::Week, i64::MAX).is_err());
833
834 assert!(get(Unit::Month, 1).is_err());
835 assert!(get(Unit::Month, -1).is_err());
836 assert!(get(Unit::Month, 0).is_err());
837 assert!(get(Unit::Month, 2).is_err());
838 assert!(get(Unit::Month, 4).is_err());
839 assert!(get(Unit::Month, 7).is_err());
840 assert!(get(Unit::Month, i64::MIN).is_err());
841 assert!(get(Unit::Month, i64::MAX).is_err());
842
843 assert!(get(Unit::Year, 1).is_err());
844 assert!(get(Unit::Year, -1).is_err());
845 assert!(get(Unit::Year, 0).is_err());
846 assert!(get(Unit::Year, 2).is_err());
847 assert!(get(Unit::Year, 4).is_err());
848 assert!(get(Unit::Year, 7).is_err());
849 assert!(get(Unit::Year, i64::MIN).is_err());
850 assert!(get(Unit::Year, i64::MAX).is_err());
851 }
852
853 #[test]
855 fn round_to_increment_half_expand_ad_hoc() {
856 let round = |quantity: i128, increment: i128| -> i128 {
857 RoundMode::HalfExpand.round_by_i128(quantity, increment)
858 };
859 assert_eq!(26, round(20, 13));
860
861 assert_eq!(0, round(29, 60));
862 assert_eq!(60, round(30, 60));
863 assert_eq!(60, round(31, 60));
864
865 assert_eq!(0, round(3, 7));
866 assert_eq!(7, round(4, 7));
867 }
868
869 #[test]
876 fn round_to_increment_temporal_table_ceil() {
877 let round = |quantity: i128, increment: i128| -> i128 {
878 RoundMode::Ceil.round_by_i128(quantity, increment)
879 };
880 assert_eq!(-10, round(-15, 10));
881 assert_eq!(0, round(-5, 10));
882 assert_eq!(10, round(4, 10));
883 assert_eq!(10, round(5, 10));
884 assert_eq!(10, round(6, 10));
885 assert_eq!(20, round(15, 10));
886
887 assert_eq!(i128::MAX, round(i128::MAX, 1));
888 assert_eq!(i128::MAX, round(i128::MAX, i128::MAX));
889
890 }
906
907 #[test]
908 fn round_to_increment_temporal_table_floor() {
909 let round = |quantity: i128, increment: i128| -> i128 {
910 RoundMode::Floor.round_by_i128(quantity, increment)
911 };
912 assert_eq!(-20, round(-15, 10));
913 assert_eq!(-10, round(-5, 10));
914 assert_eq!(0, round(4, 10));
915 assert_eq!(0, round(5, 10));
916 assert_eq!(0, round(6, 10));
917 assert_eq!(10, round(15, 10));
918 }
919
920 #[test]
921 fn round_to_increment_temporal_table_expand() {
922 let round = |quantity: i128, increment: i128| -> i128 {
923 RoundMode::Expand.round_by_i128(quantity, increment)
924 };
925 assert_eq!(-20, round(-15, 10));
926 assert_eq!(-10, round(-5, 10));
927 assert_eq!(10, round(4, 10));
928 assert_eq!(10, round(5, 10));
929 assert_eq!(10, round(6, 10));
930 assert_eq!(20, round(15, 10));
931 }
932
933 #[test]
934 fn round_to_increment_temporal_table_trunc() {
935 let round = |quantity: i128, increment: i128| -> i128 {
936 RoundMode::Trunc.round_by_i128(quantity, increment)
937 };
938 assert_eq!(-10, round(-15, 10));
939 assert_eq!(0, round(-5, 10));
940 assert_eq!(0, round(4, 10));
941 assert_eq!(0, round(5, 10));
942 assert_eq!(0, round(6, 10));
943 assert_eq!(10, round(15, 10));
944 }
945
946 #[test]
947 fn round_to_increment_temporal_table_half_ceil() {
948 let round = |quantity: i128, increment: i128| -> i128 {
949 RoundMode::HalfCeil.round_by_i128(quantity, increment)
950 };
951 assert_eq!(-10, round(-15, 10));
952 assert_eq!(0, round(-5, 10));
953 assert_eq!(0, round(4, 10));
954 assert_eq!(10, round(5, 10));
955 assert_eq!(10, round(6, 10));
956 assert_eq!(20, round(15, 10));
957 }
958
959 #[test]
960 fn round_to_increment_temporal_table_half_floor() {
961 let round = |quantity: i128, increment: i128| -> i128 {
962 RoundMode::HalfFloor.round_by_i128(quantity, increment)
963 };
964 assert_eq!(-20, round(-15, 10));
965 assert_eq!(-10, round(-5, 10));
966 assert_eq!(0, round(4, 10));
967 assert_eq!(0, round(5, 10));
968 assert_eq!(10, round(6, 10));
969 assert_eq!(10, round(15, 10));
970 }
971
972 #[test]
973 fn round_to_increment_temporal_table_half_expand() {
974 let round = |quantity: i128, increment: i128| -> i128 {
975 RoundMode::HalfExpand.round_by_i128(quantity, increment)
976 };
977 assert_eq!(-20, round(-15, 10));
978 assert_eq!(-10, round(-5, 10));
979 assert_eq!(0, round(4, 10));
980 assert_eq!(10, round(5, 10));
981 assert_eq!(10, round(6, 10));
982 assert_eq!(20, round(15, 10));
983 }
984
985 #[test]
986 fn round_to_increment_temporal_table_half_trunc() {
987 let round = |quantity: i128, increment: i128| -> i128 {
988 RoundMode::HalfTrunc.round_by_i128(quantity, increment)
989 };
990 assert_eq!(-10, round(-15, 10));
991 assert_eq!(0, round(-5, 10));
992 assert_eq!(0, round(4, 10));
993 assert_eq!(0, round(5, 10));
994 assert_eq!(10, round(6, 10));
995 assert_eq!(10, round(15, 10));
996 }
997
998 #[test]
999 fn round_to_increment_temporal_table_half_even() {
1000 let round = |quantity: i128, increment: i128| -> i128 {
1001 RoundMode::HalfEven.round_by_i128(quantity, increment)
1002 };
1003 assert_eq!(-20, round(-15, 10));
1004 assert_eq!(0, round(-5, 10));
1005 assert_eq!(0, round(4, 10));
1006 assert_eq!(0, round(5, 10));
1007 assert_eq!(10, round(6, 10));
1008 assert_eq!(20, round(15, 10));
1009 }
1010
1011 #[test]
1014 fn maximum_increment_nanos() {
1015 assert!(Increment::for_span(Unit::Week, 1_000_000_000).is_ok());
1016 assert!(Increment::for_span(Unit::Week, 1_000_000_001).is_err());
1017 assert_eq!(
1018 Unit::Week.duration() * 1_000_000_000,
1019 SignedDuration::from_secs(168_000_000_000 * 60 * 60)
1020 );
1021 }
1022
1023 #[test]
1029 fn round_by_duration_overflow() {
1030 let mode = RoundMode::Expand;
1031 let quantity = SignedDuration::MAX;
1032 let increment = SignedDuration::MAX - SignedDuration::from_secs(1);
1033 assert!(mode.round_by_duration(quantity, increment).is_err());
1034
1035 let mode = RoundMode::Expand;
1036 let quantity = SignedDuration::MIN;
1037 let increment = SignedDuration::MAX;
1038 assert!(mode.round_by_duration(quantity, increment).is_err());
1039 }
1040}