1 // Copyright 2013 The Servo Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9 
10 //! Core Foundation time zone objects.
11 
12 pub use core_foundation_sys::timezone::*;
13 use core_foundation_sys::base::kCFAllocatorDefault;
14 
15 use base::TCFType;
16 use date::{CFDate, CFTimeInterval};
17 use string::CFString;
18 
19 #[cfg(feature = "with-chrono")]
20 use chrono::{FixedOffset, NaiveDateTime};
21 
22 
23 declare_TCFType!{
24     /// A time zone.
25     CFTimeZone, CFTimeZoneRef
26 }
27 impl_TCFType!(CFTimeZone, CFTimeZoneRef, CFTimeZoneGetTypeID);
28 impl_CFTypeDescription!(CFTimeZone);
29 
30 impl Default for CFTimeZone {
default() -> CFTimeZone31     fn default() -> CFTimeZone {
32         unsafe {
33             let tz_ref = CFTimeZoneCopyDefault();
34             TCFType::wrap_under_create_rule(tz_ref)
35         }
36     }
37 }
38 
39 impl CFTimeZone {
40     #[inline]
new(interval: CFTimeInterval) -> CFTimeZone41     pub fn new(interval: CFTimeInterval) -> CFTimeZone {
42         unsafe {
43             let tz_ref = CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorDefault, interval);
44             TCFType::wrap_under_create_rule(tz_ref)
45         }
46     }
47 
48     #[inline]
system() -> CFTimeZone49     pub fn system() -> CFTimeZone {
50         unsafe {
51             let tz_ref = CFTimeZoneCopySystem();
52             TCFType::wrap_under_create_rule(tz_ref)
53         }
54     }
55 
seconds_from_gmt(&self, date: CFDate) -> CFTimeInterval56     pub fn seconds_from_gmt(&self, date: CFDate) -> CFTimeInterval {
57         unsafe {
58             CFTimeZoneGetSecondsFromGMT(self.0, date.abs_time())
59         }
60     }
61 
62     #[cfg(feature = "with-chrono")]
offset_at_date(&self, date: NaiveDateTime) -> FixedOffset63     pub fn offset_at_date(&self, date: NaiveDateTime) -> FixedOffset {
64         let date = CFDate::from_naive_utc(date);
65         FixedOffset::east(self.seconds_from_gmt(date) as i32)
66     }
67 
68     #[cfg(feature = "with-chrono")]
from_offset(offset: FixedOffset) -> CFTimeZone69     pub fn from_offset(offset: FixedOffset) -> CFTimeZone {
70         CFTimeZone::new(offset.local_minus_utc() as f64)
71     }
72 
73     /// The timezone database ID that identifies the time zone. E.g. "America/Los_Angeles" or
74     /// "Europe/Paris".
name(&self) -> CFString75     pub fn name(&self) -> CFString {
76         unsafe {
77             CFString::wrap_under_get_rule(CFTimeZoneGetName(self.0))
78         }
79     }
80 }
81 
82 #[cfg(test)]
83 mod test {
84     use super::CFTimeZone;
85 
86     #[cfg(feature = "with-chrono")]
87     use chrono::{NaiveDateTime, FixedOffset};
88 
89     #[test]
timezone_comparison()90     fn timezone_comparison() {
91         let system = CFTimeZone::system();
92         let default = CFTimeZone::default();
93         assert_eq!(system, default);
94     }
95 
96     #[test]
97     #[cfg(feature = "with-chrono")]
timezone_chrono_conversion()98     fn timezone_chrono_conversion() {
99         let offset = FixedOffset::west(28800);
100         let tz = CFTimeZone::from_offset(offset);
101         let converted = tz.offset_at_date(NaiveDateTime::from_timestamp(0, 0));
102         assert_eq!(offset, converted);
103     }
104 }
105