sqldatetime/lib.rs
1//! This crate provides SQL date/time types.
2//!
3//! # Feature Flags
4//!
5//!- `serde`: Enable `serde`-based serialization and deserialization. Not enabled by default.
6//!- `oracle`: Enable Oracle oriented datetime type: `OracleDate`. Not enabled by default.
7
8#![cfg_attr(docsrs, feature(doc_cfg))]
9
10#[macro_use]
11mod util;
12
13mod common;
14mod date;
15mod error;
16mod format;
17mod interval;
18mod time;
19mod timestamp;
20
21mod local;
22#[cfg(feature = "oracle")]
23mod oracle;
24#[cfg(feature = "serde")]
25mod serialize;
26
27pub use crate::date::{Date, Month, WeekDay};
28pub use crate::error::Error;
29pub use crate::format::Formatter;
30pub use crate::interval::{IntervalDT, IntervalYM, Sign};
31pub use crate::time::Time;
32pub use crate::timestamp::Timestamp;
33
34#[cfg(feature = "oracle")]
35pub use crate::oracle::Date as OracleDate;
36
37/// General trait for all date time types.
38pub trait DateTime {
39 /// Extracts year from date time.
40 fn year(&self) -> Option<i32>;
41 /// Extracts month from date time.
42 fn month(&self) -> Option<i32>;
43 /// Extracts day from date time.
44 fn day(&self) -> Option<i32>;
45 /// Extracts hour from date time.
46 fn hour(&self) -> Option<i32>;
47 /// Extracts minute from date time.
48 fn minute(&self) -> Option<i32>;
49 /// Extracts second from date time.
50 fn second(&self) -> Option<f64>;
51 /// Extracts second from date time.
52 fn date(&self) -> Option<Date>;
53}
54
55/// Trunc trait for Timestamp/Date/OracleDate
56pub trait Trunc: Sized {
57 /// Truncates to the first day of the century.
58 ///
59 /// ## Example
60 ///
61 /// ```
62 /// use sqldatetime::{Timestamp, Date, Time, Trunc};
63 ///
64 /// let timestamp = Date::try_from_ymd(2021, 10, 1).unwrap().and_time(Time::ZERO);
65 /// let result = Date::try_from_ymd(2001, 1, 1).unwrap().and_time(Time::ZERO);
66 /// assert_eq!(timestamp.trunc_century().unwrap(), result);
67 /// ```
68 fn trunc_century(self) -> Result<Self, Error>;
69
70 /// Truncates to the first day of the year.
71 ///
72 /// ## Example
73 ///
74 /// ```
75 /// use sqldatetime::{Timestamp, Date, Time, Trunc};
76 ///
77 /// let timestamp = Date::try_from_ymd(2021, 10, 1).unwrap().and_time(Time::ZERO);
78 /// let result = Date::try_from_ymd(2021, 1, 1).unwrap().and_time(Time::ZERO);
79 /// assert_eq!(timestamp.trunc_year().unwrap(), result);
80 /// ```
81 fn trunc_year(self) -> Result<Self, Error>;
82
83 /// Truncates to the first day of the first week in the year.
84 ///
85 /// ## Example
86 ///
87 /// ```
88 /// use sqldatetime::{Timestamp, Date, Time, Trunc};
89 ///
90 /// let timestamp = Date::try_from_ymd(2021, 10, 1).unwrap().and_time(Time::ZERO);
91 /// let result = Date::try_from_ymd(2021, 1, 4).unwrap().and_time(Time::ZERO);
92 /// assert_eq!(timestamp.trunc_iso_year().unwrap(), result);
93 /// ```
94 fn trunc_iso_year(self) -> Result<Self, Error>;
95
96 /// Truncates to the first day of the quarter.
97 ///
98 /// ## Example
99 ///
100 /// ```
101 /// use sqldatetime::{Timestamp, Date, Time, Trunc};
102 ///
103 /// let timestamp = Date::try_from_ymd(2021, 11, 1).unwrap().and_time(Time::ZERO);
104 /// let result = Date::try_from_ymd(2021, 10, 1).unwrap().and_time(Time::ZERO);
105 /// assert_eq!(timestamp.trunc_quarter().unwrap(), result);
106 /// ```
107 fn trunc_quarter(self) -> Result<Self, Error>;
108
109 /// Truncates to the first day of the month.
110 ///
111 /// ## Example
112 ///
113 /// ```
114 /// use sqldatetime::{Timestamp, Date, Time, Trunc};
115 ///
116 /// let timestamp = Date::try_from_ymd(2021, 10, 24).unwrap().and_time(Time::ZERO);
117 /// let result = Date::try_from_ymd(2021, 10, 1).unwrap().and_time(Time::ZERO);
118 /// assert_eq!(timestamp.trunc_month().unwrap(), result);
119 /// ```
120 fn trunc_month(self) -> Result<Self, Error>;
121
122 /// Truncates to the same day of the week as the first day of the year.
123 ///
124 /// ## Example
125 ///
126 /// ```
127 /// use sqldatetime::{Timestamp, Date, Time, Trunc};
128 ///
129 /// let timestamp = Date::try_from_ymd(2021, 1, 7).unwrap().and_time(Time::ZERO);
130 /// let result = Date::try_from_ymd(2021, 1, 1).unwrap().and_time(Time::ZERO);
131 /// assert_eq!(timestamp.trunc_week().unwrap(), result);
132 /// ```
133 fn trunc_week(self) -> Result<Self, Error>;
134
135 /// Truncates to the monday of the week.
136 ///
137 /// ## Example
138 ///
139 /// ```
140 /// use sqldatetime::{Timestamp, Date, Time, Trunc};
141 ///
142 /// let timestamp = Date::try_from_ymd(2021, 1, 7).unwrap().and_time(Time::ZERO);
143 /// let result = Date::try_from_ymd(2021, 1, 4).unwrap().and_time(Time::ZERO);
144 /// assert_eq!(timestamp.trunc_iso_week().unwrap(), result);
145 /// ```
146 fn trunc_iso_week(self) -> Result<Self, Error>;
147
148 /// Truncates to the same day of the week as the first day of the month.
149 ///
150 /// ## Example
151 ///
152 /// ```
153 /// use sqldatetime::{Timestamp, Date, Time, Trunc};
154 ///
155 /// let timestamp = Date::try_from_ymd(2021, 10, 7).unwrap().and_time(Time::ZERO);
156 /// let result = Date::try_from_ymd(2021, 10, 1).unwrap().and_time(Time::ZERO);
157 /// assert_eq!(timestamp.trunc_month_start_week().unwrap(), result);
158 /// ```
159 fn trunc_month_start_week(self) -> Result<Self, Error>;
160
161 /// Truncates to the day.
162 ///
163 /// ## Example
164 ///
165 /// ```
166 /// use sqldatetime::{Timestamp, Date, Time, Trunc};
167 ///
168 /// let timestamp = Date::try_from_ymd(2021, 10, 1).unwrap().and_time(Time::MAX);
169 /// let result = Date::try_from_ymd(2021, 10, 1).unwrap().and_time(Time::ZERO);
170 /// assert_eq!(timestamp.trunc_day().unwrap(), result);
171 /// ```
172 fn trunc_day(self) -> Result<Self, Error>;
173
174 /// Truncates to the sunday of the week.
175 ///
176 /// ## Example
177 ///
178 /// ```
179 /// use sqldatetime::{Timestamp, Date, Time, Trunc};
180 ///
181 /// let timestamp = Date::try_from_ymd(2021, 1, 7).unwrap().and_time(Time::ZERO);
182 /// let result = Date::try_from_ymd(2021, 1, 3).unwrap().and_time(Time::ZERO);
183 /// assert_eq!(timestamp.trunc_sunday_start_week().unwrap(), result);
184 /// ```
185 fn trunc_sunday_start_week(self) -> Result<Self, Error>;
186
187 /// Truncates to the hour.
188 ///
189 /// ## Example
190 ///
191 /// ```
192 /// use sqldatetime::{Timestamp, Date, Time, Trunc};
193 ///
194 /// let timestamp = Timestamp::new( Date::try_from_ymd(2021, 1, 1).unwrap(), Time::try_from_hms(9, 59, 59, 59).unwrap());
195 /// let result = Timestamp::new( Date::try_from_ymd(2021, 1, 1).unwrap(), Time::try_from_hms(9, 0, 0, 0).unwrap());
196 /// assert_eq!(timestamp.trunc_hour().unwrap(), result);
197 /// ```
198 fn trunc_hour(self) -> Result<Self, Error>;
199
200 /// Truncates to the minute.
201 ///
202 /// ## Example
203 ///
204 /// ```
205 /// use sqldatetime::{Timestamp, Date, Time, Trunc};
206 ///
207 /// let timestamp = Timestamp::new( Date::try_from_ymd(2021, 1, 1).unwrap(), Time::try_from_hms(9, 30, 59, 59).unwrap());
208 /// let result = Timestamp::new( Date::try_from_ymd(2021, 1, 1).unwrap(), Time::try_from_hms(9, 30, 0, 0).unwrap());
209 /// assert_eq!(timestamp.trunc_minute().unwrap(), result);
210 /// ```
211 fn trunc_minute(self) -> Result<Self, Error>;
212}
213
214/// Round trait for Timestamp/Date/OracleDate
215pub trait Round: Sized {
216 /// If year is more than half of century, rounds to the first day of next century, else truncates.
217 ///
218 /// ## Example
219 ///
220 /// ```
221 /// use sqldatetime::{Timestamp, Date, Time, Round};
222 ///
223 /// let timestamp = Date::try_from_ymd(2051, 1, 1).unwrap().and_time(Time::ZERO);
224 /// let result = Date::try_from_ymd(2101, 1, 1).unwrap().and_time(Time::ZERO);
225 /// assert_eq!(timestamp.round_century().unwrap(), result);
226 /// ```
227 fn round_century(self) -> Result<Self, Error>;
228
229 /// If month is bigger than June, rounds to the first day of next year, else truncates.
230 ///
231 /// ## Example
232 ///
233 /// ```
234 /// use sqldatetime::{Timestamp, Date, Time, Round};
235 ///
236 /// let timestamp = Date::try_from_ymd(2021, 7, 1).unwrap().and_time(Time::ZERO);
237 /// let result = Date::try_from_ymd(2022, 1, 1).unwrap().and_time(Time::ZERO);
238 /// assert_eq!(timestamp.round_year().unwrap(), result);
239 /// ```
240 fn round_year(self) -> Result<Self, Error>;
241
242 /// If month is bigger than June, rounds to the first day of week in next year, else truncates.
243 ///
244 /// ## Example
245 ///
246 /// ```
247 /// use sqldatetime::{Timestamp, Date, Time, Round};
248 ///
249 /// let timestamp = Date::try_from_ymd(2000, 12, 31).unwrap().and_time(Time::ZERO);
250 /// let result = Date::try_from_ymd(2001, 1, 1).unwrap().and_time(Time::ZERO);
251 /// assert_eq!(timestamp.round_iso_year().unwrap(), result);
252 /// ```
253 fn round_iso_year(self) -> Result<Self, Error>;
254
255 /// Rounds up on the sixteenth day of the second month of the quarter, else truncates.
256 ///
257 /// ## Example
258 ///
259 /// ```
260 /// use sqldatetime::{Timestamp, Date, Time, Round};
261 ///
262 /// let timestamp = Date::try_from_ymd(2021, 11, 16).unwrap().and_time(Time::ZERO);
263 /// let result = Date::try_from_ymd(2022, 1, 1).unwrap().and_time(Time::ZERO);
264 /// assert_eq!(timestamp.round_quarter().unwrap(), result);
265 /// ```
266 fn round_quarter(self) -> Result<Self, Error>;
267
268 /// Rounds up on the sixteenth day of each month, else truncates.
269 ///
270 /// ## Example
271 ///
272 /// ```
273 /// use sqldatetime::{Timestamp, Date, Time, Round};
274 ///
275 /// let timestamp = Date::try_from_ymd(2021, 12, 16).unwrap().and_time(Time::ZERO);
276 /// let result = Date::try_from_ymd(2022, 1, 1).unwrap().and_time(Time::ZERO);
277 /// assert_eq!(timestamp.round_month().unwrap(), result);
278 /// ```
279 fn round_month(self) -> Result<Self, Error>;
280
281 /// Rounds up on the fifth day of each week, the same day of the week as the first day of the year, else truncates.
282 ///
283 /// ## Example
284 ///
285 /// ```
286 /// use sqldatetime::{Timestamp, Date, Time, Round};
287 ///
288 /// let timestamp = Date::try_from_ymd(2021, 1, 5).unwrap().and_time(Time::ZERO);
289 /// let result = Date::try_from_ymd(2021, 1, 8).unwrap().and_time(Time::ZERO);
290 /// assert_eq!(timestamp.round_week().unwrap(), result);
291 /// ```
292 fn round_week(self) -> Result<Self, Error>;
293
294 /// Rounds up on the fifth day of each week, Monday be the first day of week, else truncates.
295 ///
296 /// ## Example
297 ///
298 /// ```
299 /// use sqldatetime::{Timestamp, Date, Time, Round};
300 ///
301 /// let timestamp = Date::try_from_ymd(2021, 1, 8).unwrap().and_time(Time::ZERO);
302 /// let result = Date::try_from_ymd(2021, 1, 11).unwrap().and_time(Time::ZERO);
303 /// assert_eq!(timestamp.round_iso_week().unwrap(), result);
304 /// ```
305 fn round_iso_week(self) -> Result<Self, Error>;
306
307 /// Rounds up on the fifth day of each week, the same day of the week as the first day of the month, else truncates.
308 ///
309 /// ## Example
310 ///
311 /// ```
312 /// use sqldatetime::{Timestamp, Date, Time, Round};
313 ///
314 /// let timestamp = Date::try_from_ymd(2021, 1, 5).unwrap().and_time(Time::ZERO);
315 /// let result = Date::try_from_ymd(2021, 1, 8).unwrap().and_time(Time::ZERO);
316 /// assert_eq!(timestamp.round_month_start_week().unwrap(), result);
317 /// ```
318 fn round_month_start_week(self) -> Result<Self, Error>;
319
320 /// Rounds up at 12:00 of each day, else truncates.
321 ///
322 /// ## Example
323 ///
324 /// ```
325 /// use sqldatetime::{Timestamp, Date, Time, Round};
326 ///
327 /// let timestamp = Timestamp::new( Date::try_from_ymd(2021, 12, 31).unwrap(), Time::try_from_hms(12, 0, 0, 0).unwrap());
328 /// let result = Date::try_from_ymd(2022, 1, 1).unwrap().and_time(Time::ZERO);
329 /// assert_eq!(timestamp.round_day().unwrap(), result);
330 /// ```
331 fn round_day(self) -> Result<Self, Error>;
332
333 /// Rounds up on the fifth day of each week, Sunday be the first day of week, else truncates.
334 ///
335 /// ## Example
336 ///
337 /// ```
338 /// use sqldatetime::{Timestamp, Date, Time, Round};
339 ///
340 /// let timestamp = Date::try_from_ymd(2021, 1, 8).unwrap().and_time(Time::ZERO);
341 /// let result = Date::try_from_ymd(2021, 1, 10).unwrap().and_time(Time::ZERO);
342 /// assert_eq!(timestamp.round_sunday_start_week().unwrap(), result);
343 /// ```
344 fn round_sunday_start_week(self) -> Result<Self, Error>;
345
346 /// Rounds up at half of each hour, else truncates.
347 ///
348 /// ## Example
349 ///
350 /// ```
351 /// use sqldatetime::{Timestamp, Date, Time, Round};
352 ///
353 /// let timestamp = Timestamp::new( Date::try_from_ymd(2021, 12, 31).unwrap(), Time::try_from_hms(23, 30, 0, 0).unwrap());
354 /// let result = Date::try_from_ymd(2022, 1, 1).unwrap().and_time(Time::ZERO);
355 /// assert_eq!(timestamp.round_hour().unwrap(), result);
356 /// ```
357 fn round_hour(self) -> Result<Self, Error>;
358
359 /// Rounds up at half of each minute, else truncates.
360 ///
361 /// ## Example
362 ///
363 /// ```
364 /// use sqldatetime::{Timestamp, Date, Time, Round};
365 ///
366 /// let timestamp = Timestamp::new( Date::try_from_ymd(2021, 12, 31).unwrap(), Time::try_from_hms(23, 59, 30, 0).unwrap());
367 /// let result = Date::try_from_ymd(2022, 1, 1).unwrap().and_time(Time::ZERO);
368 /// assert_eq!(timestamp.round_minute().unwrap(), result);
369 /// ```
370 fn round_minute(self) -> Result<Self, Error>;
371}