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)]
294#[cfg_attr(feature = "defmt", derive(defmt::Format))]
295pub enum RoundMode {
296 Ceil,
302 Floor,
308 Expand,
311 Trunc,
317 HalfCeil,
320 HalfFloor,
323 HalfExpand,
332 HalfTrunc,
335 HalfEven,
341}
342
343impl RoundMode {
344 pub(crate) fn round_by_duration(
358 self,
359 quantity: SignedDuration,
360 increment: SignedDuration,
361 ) -> Result<SignedDuration, Error> {
362 let quantity = quantity.as_nanos();
363 let increment = increment.as_nanos();
364 assert!(increment >= 1);
365 let rounded = self.round_by_i128(quantity, increment);
366 SignedDuration::try_from_nanos_i128(rounded)
383 .ok_or_else(|| Error::from(b::SignedDurationSeconds::error()))
384 }
385
386 fn round_by_i128(self, quantity: i128, increment: i128) -> i128 {
402 assert!(increment >= 1);
403 let mode = self;
405 let mut quotient = quantity / increment;
406 let remainder = quantity % increment;
407 if remainder == 0 {
408 return quantity;
409 }
410 let sign = if remainder < 0 { -1 } else { 1 };
411 let tiebreaker = (remainder * 2).abs();
412 let tie = tiebreaker == increment;
413 let expand_is_nearer = tiebreaker > increment;
414 match mode {
416 RoundMode::Ceil => {
417 if sign > 0 {
418 quotient += sign;
419 }
420 }
421 RoundMode::Floor => {
422 if sign < 0 {
423 quotient += sign;
424 }
425 }
426 RoundMode::Expand => {
427 quotient += sign;
428 }
429 RoundMode::Trunc => {}
430 RoundMode::HalfCeil => {
431 if expand_is_nearer || (tie && sign > 0) {
432 quotient += sign;
433 }
434 }
435 RoundMode::HalfFloor => {
436 if expand_is_nearer || (tie && sign < 0) {
437 quotient += sign;
438 }
439 }
440 RoundMode::HalfExpand => {
441 if expand_is_nearer || tie {
442 quotient += sign;
443 }
444 }
445 RoundMode::HalfTrunc => {
446 if expand_is_nearer {
447 quotient += sign;
448 }
449 }
450 RoundMode::HalfEven => {
451 if expand_is_nearer || (tie && quotient.rem_euclid(2) == 1) {
452 quotient += sign;
453 }
454 }
455 }
456 quotient.saturating_mul(increment)
462 }
463}
464
465#[cfg(test)]
466mod tests {
467 use super::*;
468
469 #[test]
470 fn for_span() {
471 let get = |unit, value| Increment::for_span(unit, value);
472
473 assert!(get(Unit::Nanosecond, 1).is_ok());
474 assert!(get(Unit::Nanosecond, 500).is_ok());
475 assert!(get(Unit::Nanosecond, -1).is_err());
476 assert!(get(Unit::Nanosecond, 0).is_err());
477 assert!(get(Unit::Nanosecond, 7).is_err());
478 assert!(get(Unit::Nanosecond, 1_000).is_err());
479 assert!(get(Unit::Nanosecond, i64::MIN).is_err());
480 assert!(get(Unit::Nanosecond, i64::MAX).is_err());
481
482 assert!(get(Unit::Microsecond, 1).is_ok());
483 assert!(get(Unit::Microsecond, 500).is_ok());
484 assert!(get(Unit::Microsecond, -1).is_err());
485 assert!(get(Unit::Microsecond, 0).is_err());
486 assert!(get(Unit::Microsecond, 7).is_err());
487 assert!(get(Unit::Microsecond, 1_000).is_err());
488 assert!(get(Unit::Microsecond, i64::MIN).is_err());
489 assert!(get(Unit::Microsecond, i64::MAX).is_err());
490
491 assert!(get(Unit::Millisecond, 1).is_ok());
492 assert!(get(Unit::Millisecond, 500).is_ok());
493 assert!(get(Unit::Millisecond, -1).is_err());
494 assert!(get(Unit::Millisecond, 0).is_err());
495 assert!(get(Unit::Millisecond, 7).is_err());
496 assert!(get(Unit::Millisecond, 1_000).is_err());
497 assert!(get(Unit::Millisecond, i64::MIN).is_err());
498 assert!(get(Unit::Millisecond, i64::MAX).is_err());
499
500 assert!(get(Unit::Second, 1).is_ok());
501 assert!(get(Unit::Second, 15).is_ok());
502 assert!(get(Unit::Second, -1).is_err());
503 assert!(get(Unit::Second, 0).is_err());
504 assert!(get(Unit::Second, 7).is_err());
505 assert!(get(Unit::Second, 1_000).is_err());
506 assert!(get(Unit::Second, i64::MIN).is_err());
507 assert!(get(Unit::Second, i64::MAX).is_err());
508
509 assert!(get(Unit::Minute, 1).is_ok());
510 assert!(get(Unit::Minute, 15).is_ok());
511 assert!(get(Unit::Minute, -1).is_err());
512 assert!(get(Unit::Minute, 0).is_err());
513 assert!(get(Unit::Minute, 7).is_err());
514 assert!(get(Unit::Minute, 1_000).is_err());
515 assert!(get(Unit::Minute, i64::MIN).is_err());
516 assert!(get(Unit::Minute, i64::MAX).is_err());
517
518 assert!(get(Unit::Hour, 1).is_ok());
519 assert!(get(Unit::Hour, 6).is_ok());
520 assert!(get(Unit::Hour, 12).is_ok());
521 assert!(get(Unit::Hour, -1).is_err());
522 assert!(get(Unit::Hour, 0).is_err());
523 assert!(get(Unit::Hour, 15).is_err());
524 assert!(get(Unit::Hour, 18).is_err());
525 assert!(get(Unit::Hour, 23).is_err());
526 assert!(get(Unit::Hour, 24).is_err());
527 assert!(get(Unit::Hour, i64::MIN).is_err());
528 assert!(get(Unit::Hour, i64::MAX).is_err());
529
530 assert!(get(Unit::Day, 1).is_ok());
531 assert!(get(Unit::Day, 6).is_ok());
532 assert!(get(Unit::Day, 7).is_ok());
533 assert!(get(Unit::Day, 12).is_ok());
534 assert!(get(Unit::Day, 30).is_ok());
535 assert!(get(Unit::Day, 31).is_ok());
536 assert!(get(Unit::Day, 100).is_ok());
537 assert!(get(Unit::Day, 10_000_000).is_ok());
538 assert!(get(Unit::Day, 1_000_000_000).is_ok());
539 assert!(get(Unit::Day, -1).is_err());
540 assert!(get(Unit::Day, 0).is_err());
541 assert!(get(Unit::Day, 1_000_000_001).is_err());
542 assert!(get(Unit::Day, i64::MIN).is_err());
543 assert!(get(Unit::Day, i64::MAX).is_err());
544
545 assert!(get(Unit::Week, 1).is_ok());
546 assert!(get(Unit::Week, 6).is_ok());
547 assert!(get(Unit::Week, 7).is_ok());
548 assert!(get(Unit::Week, 12).is_ok());
549 assert!(get(Unit::Week, 30).is_ok());
550 assert!(get(Unit::Week, 31).is_ok());
551 assert!(get(Unit::Week, 100).is_ok());
552 assert!(get(Unit::Week, 2_000_000).is_ok());
553 assert!(get(Unit::Week, 1_000_000_000).is_ok());
554 assert!(get(Unit::Week, -1).is_err());
555 assert!(get(Unit::Week, 0).is_err());
556 assert!(get(Unit::Week, 1_000_000_001).is_err());
557 assert!(get(Unit::Week, i64::MIN).is_err());
558 assert!(get(Unit::Week, i64::MAX).is_err());
559
560 assert!(get(Unit::Month, 1).is_ok());
561 assert!(get(Unit::Month, 6).is_ok());
562 assert!(get(Unit::Month, 7).is_ok());
563 assert!(get(Unit::Month, 12).is_ok());
564 assert!(get(Unit::Month, 30).is_ok());
565 assert!(get(Unit::Month, 31).is_ok());
566 assert!(get(Unit::Month, 100).is_ok());
567 assert!(get(Unit::Month, 300_000).is_ok());
568 assert!(get(Unit::Month, 1_000_000_000).is_ok());
569 assert!(get(Unit::Month, -1).is_err());
570 assert!(get(Unit::Month, 0).is_err());
571 assert!(get(Unit::Month, 1_000_000_001).is_err());
572 assert!(get(Unit::Month, i64::MIN).is_err());
573 assert!(get(Unit::Month, i64::MAX).is_err());
574
575 assert!(get(Unit::Year, 1).is_ok());
576 assert!(get(Unit::Year, 6).is_ok());
577 assert!(get(Unit::Year, 7).is_ok());
578 assert!(get(Unit::Year, 12).is_ok());
579 assert!(get(Unit::Year, 30).is_ok());
580 assert!(get(Unit::Year, 31).is_ok());
581 assert!(get(Unit::Year, 100).is_ok());
582 assert!(get(Unit::Year, 50_000).is_ok());
583 assert!(get(Unit::Year, 1_000_000_000).is_ok());
584 assert!(get(Unit::Year, -1).is_err());
585 assert!(get(Unit::Year, 0).is_err());
586 assert!(get(Unit::Year, 1_000_000_001).is_err());
587 assert!(get(Unit::Year, i64::MIN).is_err());
588 assert!(get(Unit::Year, i64::MAX).is_err());
589 }
590
591 #[test]
592 fn for_datetime() {
593 let get = |unit, value| Increment::for_datetime(unit, value);
594
595 assert!(get(Unit::Nanosecond, 1).is_ok());
596 assert!(get(Unit::Nanosecond, 500).is_ok());
597 assert!(get(Unit::Nanosecond, -1).is_err());
598 assert!(get(Unit::Nanosecond, 0).is_err());
599 assert!(get(Unit::Nanosecond, 7).is_err());
600 assert!(get(Unit::Nanosecond, 1_000).is_err());
601 assert!(get(Unit::Nanosecond, i64::MIN).is_err());
602 assert!(get(Unit::Nanosecond, i64::MAX).is_err());
603
604 assert!(get(Unit::Microsecond, 1).is_ok());
605 assert!(get(Unit::Microsecond, 500).is_ok());
606 assert!(get(Unit::Microsecond, -1).is_err());
607 assert!(get(Unit::Microsecond, 0).is_err());
608 assert!(get(Unit::Microsecond, 7).is_err());
609 assert!(get(Unit::Microsecond, 1_000).is_err());
610 assert!(get(Unit::Microsecond, i64::MIN).is_err());
611 assert!(get(Unit::Microsecond, i64::MAX).is_err());
612
613 assert!(get(Unit::Millisecond, 1).is_ok());
614 assert!(get(Unit::Millisecond, 500).is_ok());
615 assert!(get(Unit::Millisecond, -1).is_err());
616 assert!(get(Unit::Millisecond, 0).is_err());
617 assert!(get(Unit::Millisecond, 7).is_err());
618 assert!(get(Unit::Millisecond, 1_000).is_err());
619 assert!(get(Unit::Millisecond, i64::MIN).is_err());
620 assert!(get(Unit::Millisecond, i64::MAX).is_err());
621
622 assert!(get(Unit::Second, 1).is_ok());
623 assert!(get(Unit::Second, 15).is_ok());
624 assert!(get(Unit::Second, -1).is_err());
625 assert!(get(Unit::Second, 0).is_err());
626 assert!(get(Unit::Second, 7).is_err());
627 assert!(get(Unit::Second, 1_000).is_err());
628 assert!(get(Unit::Second, i64::MIN).is_err());
629 assert!(get(Unit::Second, i64::MAX).is_err());
630
631 assert!(get(Unit::Minute, 1).is_ok());
632 assert!(get(Unit::Minute, 15).is_ok());
633 assert!(get(Unit::Minute, -1).is_err());
634 assert!(get(Unit::Minute, 0).is_err());
635 assert!(get(Unit::Minute, 7).is_err());
636 assert!(get(Unit::Minute, 1_000).is_err());
637 assert!(get(Unit::Minute, i64::MIN).is_err());
638 assert!(get(Unit::Minute, i64::MAX).is_err());
639
640 assert!(get(Unit::Hour, 1).is_ok());
641 assert!(get(Unit::Hour, 6).is_ok());
642 assert!(get(Unit::Hour, 12).is_ok());
643 assert!(get(Unit::Hour, -1).is_err());
644 assert!(get(Unit::Hour, 0).is_err());
645 assert!(get(Unit::Hour, 15).is_err());
646 assert!(get(Unit::Hour, 18).is_err());
647 assert!(get(Unit::Hour, 23).is_err());
648 assert!(get(Unit::Hour, 24).is_err());
649 assert!(get(Unit::Hour, i64::MIN).is_err());
650 assert!(get(Unit::Hour, i64::MAX).is_err());
651
652 assert!(get(Unit::Day, 1).is_ok());
653 assert!(get(Unit::Day, -1).is_err());
654 assert!(get(Unit::Day, 0).is_err());
655 assert!(get(Unit::Day, 2).is_err());
656 assert!(get(Unit::Day, 4).is_err());
657 assert!(get(Unit::Day, 7).is_err());
658 assert!(get(Unit::Day, i64::MIN).is_err());
659 assert!(get(Unit::Day, i64::MAX).is_err());
660 }
661
662 #[test]
663 fn for_time() {
664 let get = |unit, value| Increment::for_time(unit, value);
665
666 assert!(get(Unit::Nanosecond, 1).is_ok());
667 assert!(get(Unit::Nanosecond, 500).is_ok());
668 assert!(get(Unit::Nanosecond, -1).is_err());
669 assert!(get(Unit::Nanosecond, 0).is_err());
670 assert!(get(Unit::Nanosecond, 7).is_err());
671 assert!(get(Unit::Nanosecond, 1_000).is_err());
672 assert!(get(Unit::Nanosecond, i64::MIN).is_err());
673 assert!(get(Unit::Nanosecond, i64::MAX).is_err());
674
675 assert!(get(Unit::Microsecond, 1).is_ok());
676 assert!(get(Unit::Microsecond, 500).is_ok());
677 assert!(get(Unit::Microsecond, -1).is_err());
678 assert!(get(Unit::Microsecond, 0).is_err());
679 assert!(get(Unit::Microsecond, 7).is_err());
680 assert!(get(Unit::Microsecond, 1_000).is_err());
681 assert!(get(Unit::Microsecond, i64::MIN).is_err());
682 assert!(get(Unit::Microsecond, i64::MAX).is_err());
683
684 assert!(get(Unit::Millisecond, 1).is_ok());
685 assert!(get(Unit::Millisecond, 500).is_ok());
686 assert!(get(Unit::Millisecond, -1).is_err());
687 assert!(get(Unit::Millisecond, 0).is_err());
688 assert!(get(Unit::Millisecond, 7).is_err());
689 assert!(get(Unit::Millisecond, 1_000).is_err());
690 assert!(get(Unit::Millisecond, i64::MIN).is_err());
691 assert!(get(Unit::Millisecond, i64::MAX).is_err());
692
693 assert!(get(Unit::Second, 1).is_ok());
694 assert!(get(Unit::Second, 15).is_ok());
695 assert!(get(Unit::Second, -1).is_err());
696 assert!(get(Unit::Second, 0).is_err());
697 assert!(get(Unit::Second, 7).is_err());
698 assert!(get(Unit::Second, 1_000).is_err());
699 assert!(get(Unit::Second, i64::MIN).is_err());
700 assert!(get(Unit::Second, i64::MAX).is_err());
701
702 assert!(get(Unit::Minute, 1).is_ok());
703 assert!(get(Unit::Minute, 15).is_ok());
704 assert!(get(Unit::Minute, -1).is_err());
705 assert!(get(Unit::Minute, 0).is_err());
706 assert!(get(Unit::Minute, 7).is_err());
707 assert!(get(Unit::Minute, 1_000).is_err());
708 assert!(get(Unit::Minute, i64::MIN).is_err());
709 assert!(get(Unit::Minute, i64::MAX).is_err());
710
711 assert!(get(Unit::Hour, 1).is_ok());
712 assert!(get(Unit::Hour, 6).is_ok());
713 assert!(get(Unit::Hour, 12).is_ok());
714 assert!(get(Unit::Hour, -1).is_err());
715 assert!(get(Unit::Hour, 0).is_err());
716 assert!(get(Unit::Hour, 15).is_err());
717 assert!(get(Unit::Hour, 18).is_err());
718 assert!(get(Unit::Hour, 23).is_err());
719 assert!(get(Unit::Hour, 24).is_err());
720 assert!(get(Unit::Hour, i64::MIN).is_err());
721 assert!(get(Unit::Hour, i64::MAX).is_err());
722
723 assert!(get(Unit::Day, 1).is_err());
724 assert!(get(Unit::Day, -1).is_err());
725 assert!(get(Unit::Day, 0).is_err());
726 assert!(get(Unit::Day, 2).is_err());
727 assert!(get(Unit::Day, 4).is_err());
728 assert!(get(Unit::Day, 7).is_err());
729 assert!(get(Unit::Day, i64::MIN).is_err());
730 assert!(get(Unit::Day, i64::MAX).is_err());
731 }
732
733 #[test]
734 fn for_timestamp() {
735 let get = |unit, value| Increment::for_timestamp(unit, value);
736
737 assert!(get(Unit::Nanosecond, 1).is_ok());
738 assert!(get(Unit::Nanosecond, 500).is_ok());
739 assert!(get(Unit::Nanosecond, 1_000).is_ok());
740 assert!(get(Unit::Nanosecond, 1_000_000_000).is_ok());
741 assert!(get(Unit::Nanosecond, -1).is_err());
742 assert!(get(Unit::Nanosecond, 0).is_err());
743 assert!(get(Unit::Nanosecond, 7).is_err());
744 assert!(get(Unit::Nanosecond, 1_000_000_001).is_err());
745 assert!(get(Unit::Nanosecond, i64::MIN).is_err());
746 assert!(get(Unit::Nanosecond, i64::MAX).is_err());
747
748 assert!(get(Unit::Microsecond, 1).is_ok());
749 assert!(get(Unit::Microsecond, 500).is_ok());
750 assert!(get(Unit::Microsecond, 1_000).is_ok());
751 assert!(get(Unit::Microsecond, 2_000).is_ok());
752 assert!(get(Unit::Microsecond, -1).is_err());
753 assert!(get(Unit::Microsecond, 0).is_err());
754 assert!(get(Unit::Microsecond, 7).is_err());
755 assert!(get(Unit::Microsecond, 1_000_000_000).is_err());
756 assert!(get(Unit::Microsecond, 1_000_000_001).is_err());
757 assert!(get(Unit::Microsecond, i64::MIN).is_err());
758 assert!(get(Unit::Microsecond, i64::MAX).is_err());
759
760 assert!(get(Unit::Millisecond, 1).is_ok());
761 assert!(get(Unit::Millisecond, 500).is_ok());
762 assert!(get(Unit::Millisecond, 1_000).is_ok());
763 assert!(get(Unit::Millisecond, 2_000).is_ok());
764 assert!(get(Unit::Millisecond, 86_400_000).is_ok());
765 assert!(get(Unit::Millisecond, -1).is_err());
766 assert!(get(Unit::Millisecond, 0).is_err());
767 assert!(get(Unit::Millisecond, 7).is_err());
768 assert!(get(Unit::Millisecond, 1_000_000_000).is_err());
769 assert!(get(Unit::Millisecond, 1_000_000_001).is_err());
770 assert!(get(Unit::Millisecond, i64::MIN).is_err());
771 assert!(get(Unit::Millisecond, i64::MAX).is_err());
772
773 assert!(get(Unit::Second, 1).is_ok());
774 assert!(get(Unit::Second, 15).is_ok());
775 assert!(get(Unit::Second, 3_600).is_ok());
776 assert!(get(Unit::Second, 86_400).is_ok());
777 assert!(get(Unit::Second, -1).is_err());
778 assert!(get(Unit::Second, 0).is_err());
779 assert!(get(Unit::Second, 7).is_err());
780 assert!(get(Unit::Second, 1_000).is_err());
781 assert!(get(Unit::Second, 86_401).is_err());
782 assert!(get(Unit::Second, 172_800).is_err());
783 assert!(get(Unit::Second, 1_000_000_000).is_err());
784 assert!(get(Unit::Second, 1_000_000_001).is_err());
785 assert!(get(Unit::Second, i64::MIN).is_err());
786 assert!(get(Unit::Second, i64::MAX).is_err());
787
788 assert!(get(Unit::Minute, 1).is_ok());
789 assert!(get(Unit::Minute, 15).is_ok());
790 assert!(get(Unit::Minute, 1_440).is_ok());
791 assert!(get(Unit::Minute, -1).is_err());
792 assert!(get(Unit::Minute, 0).is_err());
793 assert!(get(Unit::Minute, 7).is_err());
794 assert!(get(Unit::Minute, 1_000).is_err());
795 assert!(get(Unit::Minute, 1_441).is_err());
796 assert!(get(Unit::Minute, 2_880).is_err());
797 assert!(get(Unit::Minute, 1_000_000_000).is_err());
798 assert!(get(Unit::Minute, 1_000_000_001).is_err());
799 assert!(get(Unit::Minute, i64::MIN).is_err());
800 assert!(get(Unit::Minute, i64::MAX).is_err());
801
802 assert!(get(Unit::Hour, 1).is_ok());
803 assert!(get(Unit::Hour, 6).is_ok());
804 assert!(get(Unit::Hour, 12).is_ok());
805 assert!(get(Unit::Hour, 24).is_ok());
806 assert!(get(Unit::Hour, -1).is_err());
807 assert!(get(Unit::Hour, 0).is_err());
808 assert!(get(Unit::Hour, 15).is_err());
809 assert!(get(Unit::Hour, 18).is_err());
810 assert!(get(Unit::Hour, 23).is_err());
811 assert!(get(Unit::Hour, 25).is_err());
812 assert!(get(Unit::Hour, 1_000_000_000).is_err());
813 assert!(get(Unit::Hour, 1_000_000_001).is_err());
814 assert!(get(Unit::Hour, i64::MIN).is_err());
815 assert!(get(Unit::Hour, i64::MAX).is_err());
816
817 assert!(get(Unit::Day, 1).is_err());
818 assert!(get(Unit::Day, -1).is_err());
819 assert!(get(Unit::Day, 0).is_err());
820 assert!(get(Unit::Day, 2).is_err());
821 assert!(get(Unit::Day, 4).is_err());
822 assert!(get(Unit::Day, 7).is_err());
823 assert!(get(Unit::Day, i64::MIN).is_err());
824 assert!(get(Unit::Day, i64::MAX).is_err());
825
826 assert!(get(Unit::Week, 1).is_err());
827 assert!(get(Unit::Week, -1).is_err());
828 assert!(get(Unit::Week, 0).is_err());
829 assert!(get(Unit::Week, 2).is_err());
830 assert!(get(Unit::Week, 4).is_err());
831 assert!(get(Unit::Week, 7).is_err());
832 assert!(get(Unit::Week, i64::MIN).is_err());
833 assert!(get(Unit::Week, i64::MAX).is_err());
834
835 assert!(get(Unit::Month, 1).is_err());
836 assert!(get(Unit::Month, -1).is_err());
837 assert!(get(Unit::Month, 0).is_err());
838 assert!(get(Unit::Month, 2).is_err());
839 assert!(get(Unit::Month, 4).is_err());
840 assert!(get(Unit::Month, 7).is_err());
841 assert!(get(Unit::Month, i64::MIN).is_err());
842 assert!(get(Unit::Month, i64::MAX).is_err());
843
844 assert!(get(Unit::Year, 1).is_err());
845 assert!(get(Unit::Year, -1).is_err());
846 assert!(get(Unit::Year, 0).is_err());
847 assert!(get(Unit::Year, 2).is_err());
848 assert!(get(Unit::Year, 4).is_err());
849 assert!(get(Unit::Year, 7).is_err());
850 assert!(get(Unit::Year, i64::MIN).is_err());
851 assert!(get(Unit::Year, i64::MAX).is_err());
852 }
853
854 #[test]
856 fn round_to_increment_half_expand_ad_hoc() {
857 let round = |quantity: i128, increment: i128| -> i128 {
858 RoundMode::HalfExpand.round_by_i128(quantity, increment)
859 };
860 assert_eq!(26, round(20, 13));
861
862 assert_eq!(0, round(29, 60));
863 assert_eq!(60, round(30, 60));
864 assert_eq!(60, round(31, 60));
865
866 assert_eq!(0, round(3, 7));
867 assert_eq!(7, round(4, 7));
868 }
869
870 #[test]
877 fn round_to_increment_temporal_table_ceil() {
878 let round = |quantity: i128, increment: i128| -> i128 {
879 RoundMode::Ceil.round_by_i128(quantity, increment)
880 };
881 assert_eq!(-10, round(-15, 10));
882 assert_eq!(0, round(-5, 10));
883 assert_eq!(10, round(4, 10));
884 assert_eq!(10, round(5, 10));
885 assert_eq!(10, round(6, 10));
886 assert_eq!(20, round(15, 10));
887
888 assert_eq!(i128::MAX, round(i128::MAX, 1));
889 assert_eq!(i128::MAX, round(i128::MAX, i128::MAX));
890
891 }
907
908 #[test]
909 fn round_to_increment_temporal_table_floor() {
910 let round = |quantity: i128, increment: i128| -> i128 {
911 RoundMode::Floor.round_by_i128(quantity, increment)
912 };
913 assert_eq!(-20, round(-15, 10));
914 assert_eq!(-10, round(-5, 10));
915 assert_eq!(0, round(4, 10));
916 assert_eq!(0, round(5, 10));
917 assert_eq!(0, round(6, 10));
918 assert_eq!(10, round(15, 10));
919 }
920
921 #[test]
922 fn round_to_increment_temporal_table_expand() {
923 let round = |quantity: i128, increment: i128| -> i128 {
924 RoundMode::Expand.round_by_i128(quantity, increment)
925 };
926 assert_eq!(-20, round(-15, 10));
927 assert_eq!(-10, round(-5, 10));
928 assert_eq!(10, round(4, 10));
929 assert_eq!(10, round(5, 10));
930 assert_eq!(10, round(6, 10));
931 assert_eq!(20, round(15, 10));
932 }
933
934 #[test]
935 fn round_to_increment_temporal_table_trunc() {
936 let round = |quantity: i128, increment: i128| -> i128 {
937 RoundMode::Trunc.round_by_i128(quantity, increment)
938 };
939 assert_eq!(-10, round(-15, 10));
940 assert_eq!(0, round(-5, 10));
941 assert_eq!(0, round(4, 10));
942 assert_eq!(0, round(5, 10));
943 assert_eq!(0, round(6, 10));
944 assert_eq!(10, round(15, 10));
945 }
946
947 #[test]
948 fn round_to_increment_temporal_table_half_ceil() {
949 let round = |quantity: i128, increment: i128| -> i128 {
950 RoundMode::HalfCeil.round_by_i128(quantity, increment)
951 };
952 assert_eq!(-10, round(-15, 10));
953 assert_eq!(0, round(-5, 10));
954 assert_eq!(0, round(4, 10));
955 assert_eq!(10, round(5, 10));
956 assert_eq!(10, round(6, 10));
957 assert_eq!(20, round(15, 10));
958 }
959
960 #[test]
961 fn round_to_increment_temporal_table_half_floor() {
962 let round = |quantity: i128, increment: i128| -> i128 {
963 RoundMode::HalfFloor.round_by_i128(quantity, increment)
964 };
965 assert_eq!(-20, round(-15, 10));
966 assert_eq!(-10, round(-5, 10));
967 assert_eq!(0, round(4, 10));
968 assert_eq!(0, round(5, 10));
969 assert_eq!(10, round(6, 10));
970 assert_eq!(10, round(15, 10));
971 }
972
973 #[test]
974 fn round_to_increment_temporal_table_half_expand() {
975 let round = |quantity: i128, increment: i128| -> i128 {
976 RoundMode::HalfExpand.round_by_i128(quantity, increment)
977 };
978 assert_eq!(-20, round(-15, 10));
979 assert_eq!(-10, round(-5, 10));
980 assert_eq!(0, round(4, 10));
981 assert_eq!(10, round(5, 10));
982 assert_eq!(10, round(6, 10));
983 assert_eq!(20, round(15, 10));
984 }
985
986 #[test]
987 fn round_to_increment_temporal_table_half_trunc() {
988 let round = |quantity: i128, increment: i128| -> i128 {
989 RoundMode::HalfTrunc.round_by_i128(quantity, increment)
990 };
991 assert_eq!(-10, round(-15, 10));
992 assert_eq!(0, round(-5, 10));
993 assert_eq!(0, round(4, 10));
994 assert_eq!(0, round(5, 10));
995 assert_eq!(10, round(6, 10));
996 assert_eq!(10, round(15, 10));
997 }
998
999 #[test]
1000 fn round_to_increment_temporal_table_half_even() {
1001 let round = |quantity: i128, increment: i128| -> i128 {
1002 RoundMode::HalfEven.round_by_i128(quantity, increment)
1003 };
1004 assert_eq!(-20, round(-15, 10));
1005 assert_eq!(0, round(-5, 10));
1006 assert_eq!(0, round(4, 10));
1007 assert_eq!(0, round(5, 10));
1008 assert_eq!(10, round(6, 10));
1009 assert_eq!(20, round(15, 10));
1010 }
1011
1012 #[test]
1015 fn maximum_increment_nanos() {
1016 assert!(Increment::for_span(Unit::Week, 1_000_000_000).is_ok());
1017 assert!(Increment::for_span(Unit::Week, 1_000_000_001).is_err());
1018 assert_eq!(
1019 Unit::Week.duration() * 1_000_000_000,
1020 SignedDuration::from_secs(168_000_000_000 * 60 * 60)
1021 );
1022 }
1023
1024 #[test]
1030 fn round_by_duration_overflow() {
1031 let mode = RoundMode::Expand;
1032 let quantity = SignedDuration::MAX;
1033 let increment = SignedDuration::MAX - SignedDuration::from_secs(1);
1034 assert!(mode.round_by_duration(quantity, increment).is_err());
1035
1036 let mode = RoundMode::Expand;
1037 let quantity = SignedDuration::MIN;
1038 let increment = SignedDuration::MAX;
1039 assert!(mode.round_by_duration(quantity, increment).is_err());
1040 }
1041}