1use crate::{error, util::b, Unit};
2
3#[derive(Clone, Debug)]
4pub(crate) enum UnitConfigError {
5 CalendarUnitsNotAllowed { unit: Unit },
6 CivilDate { given: Unit },
7 CivilTime { given: Unit },
8 IncrementDivide { unit: Unit, must_divide: MustDivide },
9 LargestSmallerThanSmallest { smallest: Unit, largest: Unit },
10 RelativeWeekOrDay { unit: Unit },
11 RelativeYearOrMonth { unit: Unit },
12 RelativeYearOrMonthGivenDaysAre24Hours { unit: Unit },
13 RoundToUnitUnsupported { unit: Unit },
14 SignedDurationCalendarUnit { smallest: Unit },
15 TimeZoneOffset { given: Unit },
16}
17
18impl From<UnitConfigError> for error::Error {
19 #[cold]
20 #[inline(never)]
21 fn from(err: UnitConfigError) -> error::Error {
22 error::ErrorKind::UnitConfig(err).into()
23 }
24}
25
26impl error::IntoError for UnitConfigError {
27 fn into_error(self) -> error::Error {
28 self.into()
29 }
30}
31
32impl core::fmt::Display for UnitConfigError {
33 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
34 use self::UnitConfigError::*;
35
36 match *self {
37 CalendarUnitsNotAllowed { unit } => write!(
38 f,
39 "operation can only be performed with units of hours \
40 or smaller, but found non-zero '{unit}' units \
41 (operations on `jiff::Timestamp`, `jiff::tz::Offset` \
42 and `jiff::civil::Time` don't support calendar \
43 units in a `jiff::Span`)",
44 unit = unit.singular(),
45 ),
46 CivilDate { given } => write!(
47 f,
48 "'{unit}' not allowed as a date unit for rounding span",
49 unit = given.singular()
50 ),
51 CivilTime { given } => write!(
52 f,
53 "'{unit}' not allowed as a time unit for rounding span",
54 unit = given.singular()
55 ),
56 IncrementDivide { unit, must_divide: MustDivide::Days } => write!(
57 f,
58 "increment for rounding to '{unit}' \
59 must be equal to `1`",
60 unit = unit.plural(),
61 ),
62 IncrementDivide { unit, must_divide } => write!(
63 f,
64 "increment for rounding to '{unit}' \
65 must divide into `{must_divide}` evenly",
66 unit = unit.plural(),
67 must_divide = must_divide.as_i64(),
68 ),
69 LargestSmallerThanSmallest { smallest, largest } => {
70 write!(
71 f,
72 "largest unit ('{largest}') cannot be smaller than \
73 smallest unit ('{smallest}')",
74 largest = largest.singular(),
75 smallest = smallest.singular(),
76 )
77 }
78 RelativeWeekOrDay { unit } => write!(
79 f,
80 "using unit '{unit}' in a span or configuration \
81 requires that either a relative reference time be given \
82 or `jiff::SpanRelativeTo::days_are_24_hours()` is used to \
83 indicate invariant 24-hour days, \
84 but neither were provided",
85 unit = unit.singular(),
86 ),
87 RelativeYearOrMonth { unit } => write!(
88 f,
89 "using unit '{unit}' in a span or configuration \
90 requires that a relative reference time be given, \
91 but none was provided",
92 unit = unit.singular(),
93 ),
94 RelativeYearOrMonthGivenDaysAre24Hours { unit } => write!(
95 f,
96 "using unit '{unit}' in span or configuration \
97 requires that a relative reference time be given \
98 (`jiff::SpanRelativeTo::days_are_24_hours()` was given \
99 but this only permits using days and weeks \
100 without a relative reference time)",
101 unit = unit.singular(),
102 ),
103 RoundToUnitUnsupported { unit } => write!(
104 f,
105 "rounding to '{unit}' is not supported",
106 unit = unit.plural(),
107 ),
108 SignedDurationCalendarUnit { smallest } => write!(
109 f,
110 "rounding `jiff::SignedDuration` failed because \
111 the smallest unit provided, '{plural}', is a calendar unit \
112 (to round by calendar units, you must use a `jiff::Span`)",
113 plural = smallest.plural(),
114 ),
115 TimeZoneOffset { given } => write!(
116 f,
117 "'{unit}' not allowed when rounding time zone offset \
118 (must use hours, minutes or seconds)",
119 unit = given.singular(),
120 ),
121 }
122 }
123}
124
125#[derive(Clone, Copy, Debug)]
126pub(crate) enum MustDivide {
127 NanosPerCivilDay,
128 MicrosPerCivilDay,
129 MillisPerCivilDay,
130 SecsPerCivilDay,
131 MinsPerCivilDay,
132 HoursPerCivilDay,
133 NanosPerMicro,
134 MicrosPerMilli,
135 MillisPerSec,
136 SecsPerMin,
137 MinsPerHour,
138 Days,
141}
142
143impl MustDivide {
144 pub(crate) fn as_i64(&self) -> i64 {
145 use self::MustDivide::*;
146
147 match *self {
148 NanosPerCivilDay => b::NANOS_PER_CIVIL_DAY,
149 MicrosPerCivilDay => b::MICROS_PER_CIVIL_DAY,
150 MillisPerCivilDay => b::MILLIS_PER_CIVIL_DAY,
151 SecsPerCivilDay => b::SECS_PER_CIVIL_DAY,
152 MinsPerCivilDay => b::MINS_PER_CIVIL_DAY,
153 HoursPerCivilDay => b::HOURS_PER_CIVIL_DAY,
154 NanosPerMicro => b::NANOS_PER_MICRO,
155 MicrosPerMilli => b::MICROS_PER_MILLI,
156 MillisPerSec => b::MILLIS_PER_SEC,
157 SecsPerMin => b::SECS_PER_MIN,
158 MinsPerHour => b::MINS_PER_HOUR,
159 Days => 2,
160 }
161 }
162}