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