1use crate::{error, tz::Offset, util::escape};
2
3#[derive(Clone, Debug)]
4pub(crate) enum Error {
5 #[cfg(not(feature = "alloc"))]
6 AllocPosixTimeZone,
7 AmbiguousTimeMonthDay,
8 AmbiguousTimeYearMonth,
9 CivilDateTimeZulu,
10 ConvertDateTimeToTimestamp {
11 offset: Offset,
12 },
13 EmptyTimeZone,
14 ExpectedDateDesignatorFoundByte {
15 byte: u8,
16 },
17 ExpectedDateDesignatorFoundEndOfInput,
18 ExpectedDurationDesignatorFoundByte {
19 byte: u8,
20 },
21 ExpectedDurationDesignatorFoundEndOfInput,
22 ExpectedFourDigitYear,
23 ExpectedNoSeparator,
24 ExpectedOneDigitWeekday,
25 ExpectedSeparatorFoundByte {
26 byte: u8,
27 },
28 ExpectedSeparatorFoundEndOfInput,
29 ExpectedSixDigitYear,
30 ExpectedTimeDesignator,
31 ExpectedTimeDesignatorFoundByte {
32 byte: u8,
33 },
34 ExpectedTimeDesignatorFoundEndOfInput,
35 ExpectedTimeUnits,
36 ExpectedTwoDigitDay,
37 ExpectedTwoDigitHour,
38 ExpectedTwoDigitMinute,
39 ExpectedTwoDigitMonth,
40 ExpectedTwoDigitSecond,
41 ExpectedTwoDigitWeekNumber,
42 ExpectedWeekPrefixFoundByte {
43 byte: u8,
44 },
45 ExpectedWeekPrefixFoundEndOfInput,
46 FailedDayInDate,
47 FailedDayInMonthDay,
48 FailedFractionalSecondInTime,
49 FailedHourInTime,
50 FailedMinuteInTime,
51 FailedMonthInDate,
52 FailedMonthInMonthDay,
53 FailedMonthInYearMonth,
54 FailedOffsetNumeric,
55 FailedSecondInTime,
56 FailedSeparatorAfterMonth,
57 FailedSeparatorAfterWeekNumber,
58 FailedSeparatorAfterYear,
59 FailedTzdbLookup,
60 FailedWeekNumberInDate,
61 FailedWeekNumberPrefixInDate,
62 FailedWeekdayInDate,
63 FailedYearInDate,
64 FailedYearInYearMonth,
65 InvalidDate,
66 InvalidMonthDay,
67 InvalidTimeZoneUtf8,
68 InvalidWeekDate,
69 InvalidYearMonth,
70 InvalidYearZero,
71 MissingOffsetInTimestamp,
72 MissingTimeInDate,
73 MissingTimeInTimestamp,
74 MissingTimeZoneAnnotation,
75 ParseDayTwoDigit,
76 ParseHourTwoDigit,
77 ParseMinuteTwoDigit,
78 ParseMonthTwoDigit,
79 ParseSecondTwoDigit,
80 ParseWeekNumberTwoDigit,
81 ParseWeekdayOneDigit,
82 ParseYearFourDigit,
83 ParseYearSixDigit,
84 PrintTimeZoneFailure,
88}
89
90impl error::IntoError for Error {
91 fn into_error(self) -> error::Error {
92 self.into()
93 }
94}
95
96impl From<Error> for error::Error {
97 #[cold]
98 #[inline(never)]
99 fn from(err: Error) -> error::Error {
100 error::ErrorKind::FmtTemporal(err).into()
101 }
102}
103
104impl core::fmt::Display for Error {
105 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
106 use self::Error::*;
107
108 match *self {
109 #[cfg(not(feature = "alloc"))]
110 AllocPosixTimeZone => f.write_str(
111 "cannot parsed time zones other than IANA time zone \
112 identifiers or fixed offsets \
113 without the `alloc` crate feature enabled for `jiff`",
114 ),
115 AmbiguousTimeMonthDay => {
116 f.write_str("parsed time is ambiguous with a month-day date")
117 }
118 AmbiguousTimeYearMonth => {
119 f.write_str("parsed time is ambiguous with a year-month date")
120 }
121 CivilDateTimeZulu => f.write_str(
122 "cannot parse civil date/time from string with a Zulu \
123 offset, parse as a `jiff::Timestamp` first \
124 and convert to a civil date/time instead",
125 ),
126 ConvertDateTimeToTimestamp { offset } => write!(
127 f,
128 "failed to convert civil datetime to timestamp \
129 with offset {offset}",
130 ),
131 EmptyTimeZone => {
132 f.write_str("an empty string is not a valid time zone")
133 }
134 ExpectedDateDesignatorFoundByte { byte } => write!(
135 f,
136 "expected to find date unit designator suffix \
137 (`Y`, `M`, `W` or `D`), but found `{byte}` instead",
138 byte = escape::Byte(byte),
139 ),
140 ExpectedDateDesignatorFoundEndOfInput => f.write_str(
141 "expected to find date unit designator suffix \
142 (`Y`, `M`, `W` or `D`), but found end of input",
143 ),
144 ExpectedDurationDesignatorFoundByte { byte } => write!(
145 f,
146 "expected to find duration beginning with `P` or `p`, \
147 but found `{byte}` instead",
148 byte = escape::Byte(byte),
149 ),
150 ExpectedDurationDesignatorFoundEndOfInput => f.write_str(
151 "expected to find duration beginning with `P` or `p`, \
152 but found end of input",
153 ),
154 ExpectedFourDigitYear => f.write_str(
155 "expected four digit year (or leading sign for \
156 six digit year), but found end of input",
157 ),
158 ExpectedNoSeparator => f.write_str(
159 "expected no separator since none was \
160 found after the year, but found a `-` separator",
161 ),
162 ExpectedOneDigitWeekday => f.write_str(
163 "expected one digit weekday, but found end of input",
164 ),
165 ExpectedSeparatorFoundByte { byte } => write!(
166 f,
167 "expected `-` separator, but found `{byte}`",
168 byte = escape::Byte(byte),
169 ),
170 ExpectedSeparatorFoundEndOfInput => {
171 f.write_str("expected `-` separator, but found end of input")
172 }
173 ExpectedSixDigitYear => f.write_str(
174 "expected six digit year (because of a leading sign), \
175 but found end of input",
176 ),
177 ExpectedTimeDesignator => f.write_str(
178 "parsing ISO 8601 duration in this context requires \
179 that the duration contain a time component and no \
180 components of days or greater",
181 ),
182 ExpectedTimeDesignatorFoundByte { byte } => write!(
183 f,
184 "expected to find time unit designator suffix \
185 (`H`, `M` or `S`), but found `{byte}` instead",
186 byte = escape::Byte(byte),
187 ),
188 ExpectedTimeDesignatorFoundEndOfInput => f.write_str(
189 "expected to find time unit designator suffix \
190 (`H`, `M` or `S`), but found end of input",
191 ),
192 ExpectedTimeUnits => f.write_str(
193 "found a time designator (`T` or `t`) in an ISO 8601 \
194 duration string, but did not find any time units",
195 ),
196 ExpectedTwoDigitDay => {
197 f.write_str("expected two digit day, but found end of input")
198 }
199 ExpectedTwoDigitHour => {
200 f.write_str("expected two digit hour, but found end of input")
201 }
202 ExpectedTwoDigitMinute => f.write_str(
203 "expected two digit minute, but found end of input",
204 ),
205 ExpectedTwoDigitMonth => {
206 f.write_str("expected two digit month, but found end of input")
207 }
208 ExpectedTwoDigitSecond => f.write_str(
209 "expected two digit second, but found end of input",
210 ),
211 ExpectedTwoDigitWeekNumber => f.write_str(
212 "expected two digit week number, but found end of input",
213 ),
214 ExpectedWeekPrefixFoundByte { byte } => write!(
215 f,
216 "expected `W` or `w`, but found `{byte}` instead",
217 byte = escape::Byte(byte),
218 ),
219 ExpectedWeekPrefixFoundEndOfInput => {
220 f.write_str("expected `W` or `w`, but found end of input")
221 }
222 FailedDayInDate => f.write_str("failed to parse day in date"),
223 FailedDayInMonthDay => {
224 f.write_str("failed to payse day in month-day")
225 }
226 FailedFractionalSecondInTime => {
227 f.write_str("failed to parse fractional seconds in time")
228 }
229 FailedHourInTime => f.write_str("failed to parse hour in time"),
230 FailedMinuteInTime => {
231 f.write_str("failed to parse minute in time")
232 }
233 FailedMonthInDate => f.write_str("failed to parse month in date"),
234 FailedMonthInMonthDay => {
235 f.write_str("failed to parse month in month-day")
236 }
237 FailedMonthInYearMonth => {
238 f.write_str("failed to parse month in year-month")
239 }
240 FailedOffsetNumeric => f.write_str(
241 "offset successfully parsed, \
242 but failed to convert to numeric `jiff::tz::Offset`",
243 ),
244 FailedSecondInTime => {
245 f.write_str("failed to parse second in time")
246 }
247 FailedSeparatorAfterMonth => {
248 f.write_str("failed to parse separator after month")
249 }
250 FailedSeparatorAfterWeekNumber => {
251 f.write_str("failed to parse separator after week number")
252 }
253 FailedSeparatorAfterYear => {
254 f.write_str("failed to parse separator after year")
255 }
256 FailedTzdbLookup => f.write_str(
257 "parsed apparent IANA time zone identifier, \
258 but the tzdb lookup failed",
259 ),
260 FailedWeekNumberInDate => {
261 f.write_str("failed to parse week number in date")
262 }
263 FailedWeekNumberPrefixInDate => {
264 f.write_str("failed to parse week number prefix in date")
265 }
266 FailedWeekdayInDate => {
267 f.write_str("failed to parse weekday in date")
268 }
269 FailedYearInDate => f.write_str("failed to parse year in date"),
270 FailedYearInYearMonth => {
271 f.write_str("failed to parse year in year-month")
272 }
273 InvalidDate => f.write_str("parsed date is not valid"),
274 InvalidMonthDay => f.write_str("parsed month-day is not valid"),
275 InvalidTimeZoneUtf8 => f.write_str(
276 "found plausible IANA time zone identifier, \
277 but it is not valid UTF-8",
278 ),
279 InvalidWeekDate => f.write_str("parsed week date is not valid"),
280 InvalidYearMonth => f.write_str("parsed year-month is not valid"),
281 InvalidYearZero => f.write_str(
282 "year zero must be written without a sign or a \
283 positive sign, but not a negative sign",
284 ),
285 MissingOffsetInTimestamp => f.write_str(
286 "failed to find offset component, \
287 which is required for parsing a timestamp",
288 ),
289 MissingTimeInDate => f.write_str(
290 "successfully parsed date, but no time component was found",
291 ),
292 MissingTimeInTimestamp => f.write_str(
293 "failed to find time component, \
294 which is required for parsing a timestamp",
295 ),
296 MissingTimeZoneAnnotation => f.write_str(
297 "failed to find time zone annotation in square brackets, \
298 which is required for parsing a zoned datetime",
299 ),
300 ParseDayTwoDigit => {
301 f.write_str("failed to parse two digit integer as day")
302 }
303 ParseHourTwoDigit => {
304 f.write_str("failed to parse two digit integer as hour")
305 }
306 ParseMinuteTwoDigit => {
307 f.write_str("failed to parse two digit integer as minute")
308 }
309 ParseMonthTwoDigit => {
310 f.write_str("failed to parse two digit integer as month")
311 }
312 ParseSecondTwoDigit => {
313 f.write_str("failed to parse two digit integer as second")
314 }
315 ParseWeekNumberTwoDigit => {
316 f.write_str("failed to parse two digit integer as week number")
317 }
318 ParseWeekdayOneDigit => {
319 f.write_str("failed to parse one digit integer as weekday")
320 }
321 ParseYearFourDigit => {
322 f.write_str("failed to parse four digit integer as year")
323 }
324 ParseYearSixDigit => {
325 f.write_str("failed to parse six digit integer as year")
326 }
327 PrintTimeZoneFailure => f.write_str(
328 "time zones without IANA identifiers that aren't either \
329 fixed offsets or a POSIX time zone can't be serialized \
330 (this typically occurs when this is a system time zone \
331 derived from `/etc/localtime` on Unix systems that \
332 isn't symlinked to an entry in `/usr/share/zoneinfo`)",
333 ),
334 }
335 }
336}