1 // Take a look at the license at the top of the repository in the LICENSE file.
2 
3 use crate::translate::*;
4 use crate::BoolError;
5 use crate::DateDay;
6 use crate::DateMonth;
7 use crate::DateWeekday;
8 use crate::DateYear;
9 use std::cmp;
10 use std::fmt;
11 use std::hash;
12 
13 wrapper! {
14     #[doc(alias = "GDate")]
15     pub struct Date(Boxed<ffi::GDate>);
16 
17     match fn {
18         copy => |ptr| gobject_ffi::g_boxed_copy(ffi::g_date_get_type(), ptr as *const _) as *mut _,
19         free => |ptr| ffi::g_date_free(ptr),
20         init => |_ptr| (),
21         clear => |ptr| ffi::g_date_clear(ptr, 1),
22         type_ => || ffi::g_date_get_type(),
23     }
24 }
25 
26 unsafe impl Send for Date {}
27 unsafe impl Sync for Date {}
28 
29 impl Date {
30     #[doc(alias = "g_date_new_dmy")]
new_dmy(day: DateDay, month: DateMonth, year: DateYear) -> Result<Date, BoolError>31     pub fn new_dmy(day: DateDay, month: DateMonth, year: DateYear) -> Result<Date, BoolError> {
32         let month = month.into_glib();
33         unsafe {
34             let check: bool = from_glib(ffi::g_date_valid_dmy(day, month, year));
35             if !check {
36                 Err(bool_error!("Invalid date"))
37             } else {
38                 Ok(from_glib_full(ffi::g_date_new_dmy(day, month, year)))
39             }
40         }
41     }
42 
43     #[doc(alias = "g_date_new_julian")]
new_julian(julian_day: u32) -> Result<Date, BoolError>44     pub fn new_julian(julian_day: u32) -> Result<Date, BoolError> {
45         if !Self::valid_julian(julian_day) {
46             Err(bool_error!("Invalid date"))
47         } else {
48             unsafe { Ok(from_glib_full(ffi::g_date_new_julian(julian_day))) }
49         }
50     }
51 
52     #[doc(alias = "g_date_add_days")]
add_days(&mut self, n_days: u32) -> Result<(), BoolError>53     pub fn add_days(&mut self, n_days: u32) -> Result<(), BoolError> {
54         let julian_days = self.julian();
55         if julian_days == 0 || n_days > u32::MAX - julian_days {
56             Err(bool_error!("Invalid date"))
57         } else {
58             unsafe {
59                 ffi::g_date_add_days(self.to_glib_none_mut().0, n_days);
60             }
61             Ok(())
62         }
63     }
64 
65     #[doc(alias = "g_date_add_months")]
add_months(&mut self, n_months: u32) -> Result<(), BoolError>66     pub fn add_months(&mut self, n_months: u32) -> Result<(), BoolError> {
67         // The checks for this function are just a mess in the C code, allowing intermediate
68         // unknown state. So for now, nothing can be done...
69         unsafe {
70             ffi::g_date_add_months(self.to_glib_none_mut().0, n_months);
71         }
72         Ok(())
73     }
74 
75     #[doc(alias = "g_date_add_years")]
add_years(&mut self, n_years: u16) -> Result<(), BoolError>76     pub fn add_years(&mut self, n_years: u16) -> Result<(), BoolError> {
77         let year = self.year();
78         if n_years > u16::MAX - year {
79             Err(bool_error!("Invalid date"))
80         } else {
81             unsafe {
82                 ffi::g_date_add_years(self.to_glib_none_mut().0, n_years as _);
83             }
84             Ok(())
85         }
86     }
87 
88     #[doc(alias = "g_date_clamp")]
clamp(&mut self, min_date: &Date, max_date: &Date) -> Result<(), BoolError>89     pub fn clamp(&mut self, min_date: &Date, max_date: &Date) -> Result<(), BoolError> {
90         if min_date >= max_date {
91             Err(bool_error!("`min_date` must be before `max_date`"))
92         } else {
93             unsafe {
94                 ffi::g_date_clamp(
95                     self.to_glib_none_mut().0,
96                     min_date.to_glib_none().0,
97                     max_date.to_glib_none().0,
98                 );
99             }
100             Ok(())
101         }
102     }
103 
104     #[doc(alias = "g_date_compare")]
compare(&self, rhs: &Date) -> i32105     fn compare(&self, rhs: &Date) -> i32 {
106         unsafe { ffi::g_date_compare(self.to_glib_none().0, rhs.to_glib_none().0) }
107     }
108 
109     #[doc(alias = "g_date_days_between")]
days_between(&self, date2: &Date) -> i32110     pub fn days_between(&self, date2: &Date) -> i32 {
111         unsafe { ffi::g_date_days_between(self.to_glib_none().0, date2.to_glib_none().0) }
112     }
113 
114     #[doc(alias = "g_date_get_day")]
115     #[doc(alias = "get_day")]
day(&self) -> DateDay116     pub fn day(&self) -> DateDay {
117         unsafe { ffi::g_date_get_day(self.to_glib_none().0) }
118     }
119 
120     #[doc(alias = "g_date_get_day_of_year")]
121     #[doc(alias = "get_day_of_year")]
day_of_year(&self) -> u32122     pub fn day_of_year(&self) -> u32 {
123         unsafe { ffi::g_date_get_day_of_year(self.to_glib_none().0) }
124     }
125 
126     #[doc(alias = "g_date_get_iso8601_week_of_year")]
127     #[doc(alias = "get_iso8601_week_of_year")]
iso8601_week_of_year(&self) -> u32128     pub fn iso8601_week_of_year(&self) -> u32 {
129         unsafe { ffi::g_date_get_iso8601_week_of_year(self.to_glib_none().0) }
130     }
131 
132     #[doc(alias = "g_date_get_julian")]
133     #[doc(alias = "get_julian")]
julian(&self) -> u32134     pub fn julian(&self) -> u32 {
135         unsafe { ffi::g_date_get_julian(self.to_glib_none().0) }
136     }
137 
138     #[doc(alias = "g_date_get_monday_week_of_year")]
139     #[doc(alias = "get_monday_week_of_year")]
monday_week_of_year(&self) -> u32140     pub fn monday_week_of_year(&self) -> u32 {
141         unsafe { ffi::g_date_get_monday_week_of_year(self.to_glib_none().0) }
142     }
143 
144     #[doc(alias = "g_date_get_month")]
145     #[doc(alias = "get_month")]
month(&self) -> DateMonth146     pub fn month(&self) -> DateMonth {
147         unsafe { from_glib(ffi::g_date_get_month(self.to_glib_none().0)) }
148     }
149 
150     #[doc(alias = "g_date_get_sunday_week_of_year")]
151     #[doc(alias = "get_sunday_week_of_year")]
sunday_week_of_year(&self) -> u32152     pub fn sunday_week_of_year(&self) -> u32 {
153         unsafe { ffi::g_date_get_sunday_week_of_year(self.to_glib_none().0) }
154     }
155 
156     #[doc(alias = "g_date_get_weekday")]
157     #[doc(alias = "get_weekday")]
weekday(&self) -> DateWeekday158     pub fn weekday(&self) -> DateWeekday {
159         unsafe { from_glib(ffi::g_date_get_weekday(self.to_glib_none().0)) }
160     }
161 
162     #[doc(alias = "g_date_get_year")]
163     #[doc(alias = "get_year")]
year(&self) -> DateYear164     pub fn year(&self) -> DateYear {
165         unsafe { ffi::g_date_get_year(self.to_glib_none().0) }
166     }
167 
168     #[doc(alias = "g_date_is_first_of_month")]
is_first_of_month(&self) -> bool169     pub fn is_first_of_month(&self) -> bool {
170         unsafe { from_glib(ffi::g_date_is_first_of_month(self.to_glib_none().0)) }
171     }
172 
173     #[doc(alias = "g_date_is_last_of_month")]
is_last_of_month(&self) -> bool174     pub fn is_last_of_month(&self) -> bool {
175         unsafe { from_glib(ffi::g_date_is_last_of_month(self.to_glib_none().0)) }
176     }
177 
178     #[doc(alias = "g_date_order")]
order(&mut self, date2: &mut Date)179     pub fn order(&mut self, date2: &mut Date) {
180         unsafe {
181             ffi::g_date_order(self.to_glib_none_mut().0, date2.to_glib_none_mut().0);
182         }
183     }
184 
185     #[doc(alias = "g_date_set_day")]
set_day(&mut self, day: DateDay) -> Result<(), BoolError>186     pub fn set_day(&mut self, day: DateDay) -> Result<(), BoolError> {
187         if !Self::valid_dmy(day, self.month(), self.year()) {
188             Err(bool_error!("invalid day"))
189         } else {
190             unsafe {
191                 ffi::g_date_set_day(self.to_glib_none_mut().0, day);
192             }
193             Ok(())
194         }
195     }
196 
197     #[doc(alias = "g_date_set_dmy")]
set_dmy( &mut self, day: DateDay, month: DateMonth, y: DateYear, ) -> Result<(), BoolError>198     pub fn set_dmy(
199         &mut self,
200         day: DateDay,
201         month: DateMonth,
202         y: DateYear,
203     ) -> Result<(), BoolError> {
204         if !Self::valid_dmy(day, month, y) {
205             Err(bool_error!("invalid date"))
206         } else {
207             unsafe {
208                 ffi::g_date_set_dmy(self.to_glib_none_mut().0, day, month.into_glib(), y);
209             }
210             Ok(())
211         }
212     }
213 
214     #[doc(alias = "g_date_set_julian")]
set_julian(&mut self, julian_date: u32) -> Result<(), BoolError>215     pub fn set_julian(&mut self, julian_date: u32) -> Result<(), BoolError> {
216         if !Self::valid_julian(julian_date) {
217             Err(bool_error!("invalid date"))
218         } else {
219             unsafe {
220                 ffi::g_date_set_julian(self.to_glib_none_mut().0, julian_date);
221             }
222             Ok(())
223         }
224     }
225 
226     #[doc(alias = "g_date_set_month")]
set_month(&mut self, month: DateMonth) -> Result<(), BoolError>227     pub fn set_month(&mut self, month: DateMonth) -> Result<(), BoolError> {
228         if !Self::valid_dmy(self.day(), month, self.year()) {
229             Err(bool_error!("invalid month"))
230         } else {
231             unsafe {
232                 ffi::g_date_set_month(self.to_glib_none_mut().0, month.into_glib());
233             }
234             Ok(())
235         }
236     }
237 
238     #[doc(alias = "g_date_set_parse")]
set_parse(&mut self, str: &str) -> Result<(), BoolError>239     pub fn set_parse(&mut self, str: &str) -> Result<(), BoolError> {
240         let mut c = self.clone();
241         if !unsafe {
242             ffi::g_date_set_parse(c.to_glib_none_mut().0, str.to_glib_none().0);
243             ffi::g_date_valid(c.to_glib_none().0) == 0
244         } {
245             Err(bool_error!("invalid parse string"))
246         } else {
247             *self = c;
248             Ok(())
249         }
250     }
251 
252     #[doc(alias = "g_date_set_time_t")]
set_time(&mut self, time_: u32) -> Result<(), BoolError>253     pub fn set_time(&mut self, time_: u32) -> Result<(), BoolError> {
254         let mut c = self.clone();
255         unsafe {
256             ffi::g_date_set_time_t(c.to_glib_none_mut().0, time_ as _);
257         }
258         if !Self::valid_dmy(c.day(), c.month(), c.year()) {
259             Err(bool_error!("invalid time"))
260         } else {
261             *self = c;
262             Ok(())
263         }
264     }
265 
266     //pub fn set_time_val(&mut self, timeval: /*Ignored*/&mut TimeVal) {
267     //    unsafe { TODO: call ffi::g_date_set_time_val() }
268     //}
269 
270     #[doc(alias = "g_date_set_year")]
set_year(&mut self, year: DateYear) -> Result<(), BoolError>271     pub fn set_year(&mut self, year: DateYear) -> Result<(), BoolError> {
272         if !Self::valid_dmy(self.day(), self.month(), year) {
273             Err(bool_error!("invalid year"))
274         } else {
275             unsafe {
276                 ffi::g_date_set_year(self.to_glib_none_mut().0, year);
277             }
278             Ok(())
279         }
280     }
281 
282     #[doc(alias = "g_date_subtract_days")]
subtract_days(&mut self, n_days: u32) -> Result<(), BoolError>283     pub fn subtract_days(&mut self, n_days: u32) -> Result<(), BoolError> {
284         let julian = self.julian();
285         if julian > n_days {
286             Err(bool_error!("invalid number of days"))
287         } else {
288             unsafe {
289                 ffi::g_date_subtract_days(self.to_glib_none_mut().0, n_days);
290             }
291             Ok(())
292         }
293     }
294 
295     #[doc(alias = "g_date_subtract_months")]
subtract_months(&mut self, n_months: u32) -> Result<(), BoolError>296     pub fn subtract_months(&mut self, n_months: u32) -> Result<(), BoolError> {
297         // The checks for this function are just a mess in the C code, allowing intermediate
298         // unknown state. So for now, nothing can be done...
299         unsafe {
300             ffi::g_date_subtract_months(self.to_glib_none_mut().0, n_months);
301         }
302         Ok(())
303     }
304 
305     #[doc(alias = "g_date_subtract_years")]
subtract_years(&mut self, n_years: u16) -> Result<(), BoolError>306     pub fn subtract_years(&mut self, n_years: u16) -> Result<(), BoolError> {
307         if self.year() < n_years {
308             Err(bool_error!("invalid number of years"))
309         } else {
310             unsafe {
311                 ffi::g_date_subtract_years(self.to_glib_none_mut().0, n_years as _);
312             }
313             Ok(())
314         }
315     }
316 
317     //#[doc(alias="g_date_to_struct_tm")]
318     //pub fn to_struct_tm(&self, tm: /*Unimplemented*/Fundamental: Pointer) {
319     //    unsafe { TODO: call ffi::g_date_to_struct_tm() }
320     //}
321 
322     #[doc(alias = "g_date_valid")]
valid(&self) -> bool323     pub fn valid(&self) -> bool {
324         unsafe { from_glib(ffi::g_date_valid(self.to_glib_none().0)) }
325     }
326 
327     #[doc(alias = "g_date_get_days_in_month")]
328     #[doc(alias = "get_days_in_month")]
days_in_month(month: DateMonth, year: DateYear) -> u8329     pub fn days_in_month(month: DateMonth, year: DateYear) -> u8 {
330         unsafe { ffi::g_date_get_days_in_month(month.into_glib(), year) }
331     }
332 
333     #[doc(alias = "g_date_get_monday_weeks_in_year")]
334     #[doc(alias = "get_monday_weeks_in_year")]
monday_weeks_in_year(year: DateYear) -> u8335     pub fn monday_weeks_in_year(year: DateYear) -> u8 {
336         unsafe { ffi::g_date_get_monday_weeks_in_year(year) }
337     }
338 
339     #[doc(alias = "g_date_get_sunday_weeks_in_year")]
340     #[doc(alias = "get_sunday_weeks_in_year")]
sunday_weeks_in_year(year: DateYear) -> u8341     pub fn sunday_weeks_in_year(year: DateYear) -> u8 {
342         unsafe { ffi::g_date_get_sunday_weeks_in_year(year) }
343     }
344 
345     #[doc(alias = "g_date_is_leap_year")]
is_leap_year(year: DateYear) -> bool346     pub fn is_leap_year(year: DateYear) -> bool {
347         unsafe { from_glib(ffi::g_date_is_leap_year(year)) }
348     }
349 
350     #[doc(alias = "g_date_strftime")]
strftime(s: &str, format: &str, date: &Date) -> usize351     pub fn strftime(s: &str, format: &str, date: &Date) -> usize {
352         let slen = s.len() as usize;
353         unsafe {
354             ffi::g_date_strftime(
355                 s.to_glib_none().0,
356                 slen,
357                 format.to_glib_none().0,
358                 date.to_glib_none().0,
359             )
360         }
361     }
362 
363     #[doc(alias = "g_date_valid_day")]
valid_day(day: DateDay) -> bool364     pub fn valid_day(day: DateDay) -> bool {
365         unsafe { from_glib(ffi::g_date_valid_day(day)) }
366     }
367 
368     #[doc(alias = "g_date_valid_dmy")]
valid_dmy(day: DateDay, month: DateMonth, year: DateYear) -> bool369     pub fn valid_dmy(day: DateDay, month: DateMonth, year: DateYear) -> bool {
370         unsafe { from_glib(ffi::g_date_valid_dmy(day, month.into_glib(), year)) }
371     }
372 
373     #[doc(alias = "g_date_valid_julian")]
valid_julian(julian_date: u32) -> bool374     pub fn valid_julian(julian_date: u32) -> bool {
375         unsafe { from_glib(ffi::g_date_valid_julian(julian_date)) }
376     }
377 
378     #[doc(alias = "g_date_valid_month")]
valid_month(month: DateMonth) -> bool379     pub fn valid_month(month: DateMonth) -> bool {
380         unsafe { from_glib(ffi::g_date_valid_month(month.into_glib())) }
381     }
382 
383     #[doc(alias = "g_date_valid_weekday")]
valid_weekday(weekday: DateWeekday) -> bool384     pub fn valid_weekday(weekday: DateWeekday) -> bool {
385         unsafe { from_glib(ffi::g_date_valid_weekday(weekday.into_glib())) }
386     }
387 
388     #[doc(alias = "g_date_valid_year")]
valid_year(year: DateYear) -> bool389     pub fn valid_year(year: DateYear) -> bool {
390         unsafe { from_glib(ffi::g_date_valid_year(year)) }
391     }
392 }
393 
394 impl PartialEq for Date {
395     #[inline]
eq(&self, other: &Self) -> bool396     fn eq(&self, other: &Self) -> bool {
397         self.compare(other) == 0
398     }
399 }
400 
401 impl Eq for Date {}
402 
403 impl PartialOrd for Date {
404     #[inline]
partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>405     fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
406         self.compare(other).partial_cmp(&0)
407     }
408 }
409 
410 impl Ord for Date {
411     #[inline]
cmp(&self, other: &Self) -> cmp::Ordering412     fn cmp(&self, other: &Self) -> cmp::Ordering {
413         self.compare(other).cmp(&0)
414     }
415 }
416 
417 impl fmt::Debug for Date {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result418     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
419         f.debug_struct("Date")
420             .field("year", &self.year())
421             .field("month", &self.month())
422             .field("day", &self.day())
423             .finish()
424     }
425 }
426 
427 impl hash::Hash for Date {
hash<H>(&self, state: &mut H) where H: hash::Hasher,428     fn hash<H>(&self, state: &mut H)
429     where
430         H: hash::Hasher,
431     {
432         self.year().hash(state);
433         self.month().hash(state);
434         self.day().hash(state);
435     }
436 }
437