3 pub use self::inner
::*;
6 all(target_arch
= "wasm32", not(target_os
= "emscripten")),
12 pub fn time_to_tm(ts
: i64, tm
: &mut Tm
) {
13 let leapyear
= |year
| -> bool
{
14 year
% 4 == 0 && (year
% 100 != 0 || year
% 400 == 0)
17 static _ytab
: [[i64; 12]; 2] = [
18 [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ],
19 [ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]
24 let dayclock
= ts
% 86400;
25 let mut dayno
= ts
/ 86400;
27 tm
.tm_sec
= (dayclock
% 60) as i32;
28 tm
.tm_min
= ((dayclock
% 3600) / 60) as i32;
29 tm
.tm_hour
= (dayclock
/ 3600) as i32;
30 tm
.tm_wday
= ((dayno
+ 4) % 7) as i32;
32 let yearsize
= if leapyear(year
) {
37 if dayno
>= yearsize
{
44 tm
.tm_year
= (year
- 1900) as i32;
45 tm
.tm_yday
= dayno
as i32;
47 while dayno
>= _ytab
[if leapyear(year
) { 1 }
else { 0 }
][mon
] {
48 dayno
-= _ytab
[if leapyear(year
) { 1 }
else { 0 }
][mon
];
51 tm
.tm_mon
= mon
as i32;
52 tm
.tm_mday
= dayno
as i32 + 1;
56 pub fn tm_to_time(tm
: &Tm
) -> i64 {
57 let mut y
= tm
.tm_year
as i64 + 1900;
58 let mut m
= tm
.tm_mon
as i64 + 1;
63 let d
= tm
.tm_mday
as i64;
64 let h
= tm
.tm_hour
as i64;
65 let mi
= tm
.tm_min
as i64;
66 let s
= tm
.tm_sec
as i64;
67 (365*y
+ y
/4 - y
/100 + y
/400 + 3*(m
+1)/5 + 30*m
+ d
- 719561)
68 * 86400 + 3600 * h
+ 60 * mi
+ s
72 #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
74 use std
::ops
::{Add, Sub}
;
77 use super::common
::{time_to_tm, tm_to_time}
;
79 #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
80 pub struct SteadyTime
;
82 pub fn time_to_utc_tm(sec
: i64, tm
: &mut Tm
) {
86 pub fn time_to_local_tm(sec
: i64, tm
: &mut Tm
) {
87 // FIXME: Add timezone logic
91 pub fn utc_tm_to_time(tm
: &Tm
) -> i64 {
95 pub fn local_tm_to_time(tm
: &Tm
) -> i64 {
96 // FIXME: Add timezone logic
100 pub fn get_time() -> (i64, i32) {
104 pub fn get_precise_ns() -> u64 {
109 pub fn now() -> SteadyTime
{
114 impl Sub
for SteadyTime
{
115 type Output
= Duration
;
116 fn sub(self, _other
: SteadyTime
) -> Duration
{
121 impl Sub
<Duration
> for SteadyTime
{
122 type Output
= SteadyTime
;
123 fn sub(self, _other
: Duration
) -> SteadyTime
{
128 impl Add
<Duration
> for SteadyTime
{
129 type Output
= SteadyTime
;
130 fn add(self, _other
: Duration
) -> SteadyTime
{
136 #[cfg(target_env = "sgx")]
138 use std
::ops
::{Add, Sub}
;
141 use super::common
::{time_to_tm, tm_to_time}
;
142 use std
::time
::SystemTime
;
144 /// The number of nanoseconds in seconds.
145 const NANOS_PER_SEC
: u64 = 1_000_000_000;
147 #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
148 pub struct SteadyTime
{
152 pub fn time_to_utc_tm(sec
: i64, tm
: &mut Tm
) {
156 pub fn time_to_local_tm(sec
: i64, tm
: &mut Tm
) {
157 // FIXME: Add timezone logic
161 pub fn utc_tm_to_time(tm
: &Tm
) -> i64 {
165 pub fn local_tm_to_time(tm
: &Tm
) -> i64 {
166 // FIXME: Add timezone logic
170 pub fn get_time() -> (i64, i32) {
171 SteadyTime
::now().t
.raw()
174 pub fn get_precise_ns() -> u64 {
175 // This unwrap is safe because current time is well ahead of UNIX_EPOCH, unless system
176 // clock is adjusted backward.
177 let std_duration
= SystemTime
::now().duration_since(SystemTime
::UNIX_EPOCH
).unwrap();
178 std_duration
.as_secs() * NANOS_PER_SEC
+ std_duration
.subsec_nanos() as u64
182 pub fn now() -> SteadyTime
{
183 // This unwrap is safe because current time is well ahead of UNIX_EPOCH, unless system
184 // clock is adjusted backward.
185 let std_duration
= SystemTime
::now().duration_since(SystemTime
::UNIX_EPOCH
).unwrap();
186 // This unwrap is safe because duration is well within the limits of i64.
187 let duration
= Duration
::from_std(std_duration
).unwrap();
188 SteadyTime { t: duration }
192 impl Sub
for SteadyTime
{
193 type Output
= Duration
;
194 fn sub(self, other
: SteadyTime
) -> Duration
{
199 impl Sub
<Duration
> for SteadyTime
{
200 type Output
= SteadyTime
;
201 fn sub(self, other
: Duration
) -> SteadyTime
{
202 SteadyTime { t: self.t - other }
206 impl Add
<Duration
> for SteadyTime
{
207 type Output
= SteadyTime
;
208 fn add(self, other
: Duration
) -> SteadyTime
{
209 SteadyTime { t: self.t + other }
216 use libc
::{self, time_t}
;
221 #[cfg(any(target_os = "macos", target_os = "ios"))]
222 pub use self::mac
::*;
223 #[cfg(all(not(target_os = "macos"), not(target_os = "ios")))]
224 pub use self::unix
::*;
226 #[cfg(any(target_os = "solaris", target_os = "illumos"))]
228 static timezone
: time_t
;
229 static altzone
: time_t
;
232 fn rust_tm_to_tm(rust_tm
: &Tm
, tm
: &mut libc
::tm
) {
233 tm
.tm_sec
= rust_tm
.tm_sec
;
234 tm
.tm_min
= rust_tm
.tm_min
;
235 tm
.tm_hour
= rust_tm
.tm_hour
;
236 tm
.tm_mday
= rust_tm
.tm_mday
;
237 tm
.tm_mon
= rust_tm
.tm_mon
;
238 tm
.tm_year
= rust_tm
.tm_year
;
239 tm
.tm_wday
= rust_tm
.tm_wday
;
240 tm
.tm_yday
= rust_tm
.tm_yday
;
241 tm
.tm_isdst
= rust_tm
.tm_isdst
;
244 fn tm_to_rust_tm(tm
: &libc
::tm
, utcoff
: i32, rust_tm
: &mut Tm
) {
245 rust_tm
.tm_sec
= tm
.tm_sec
;
246 rust_tm
.tm_min
= tm
.tm_min
;
247 rust_tm
.tm_hour
= tm
.tm_hour
;
248 rust_tm
.tm_mday
= tm
.tm_mday
;
249 rust_tm
.tm_mon
= tm
.tm_mon
;
250 rust_tm
.tm_year
= tm
.tm_year
;
251 rust_tm
.tm_wday
= tm
.tm_wday
;
252 rust_tm
.tm_yday
= tm
.tm_yday
;
253 rust_tm
.tm_isdst
= tm
.tm_isdst
;
254 rust_tm
.tm_utcoff
= utcoff
;
257 #[cfg(any(target_os = "nacl", target_os = "solaris", target_os = "illumos"))]
258 unsafe fn timegm(tm
: *mut libc
::tm
) -> time_t
{
259 use std
::env
::{set_var, var_os, remove_var}
;
266 let current_tz
= var_os("TZ");
267 set_var("TZ", "UTC");
270 ret
= libc
::mktime(tm
);
272 if let Some(tz
) = current_tz
{
282 pub fn time_to_utc_tm(sec
: i64, tm
: &mut Tm
) {
284 let sec
= sec
as time_t
;
285 let mut out
= mem
::zeroed();
286 if libc
::gmtime_r(&sec
, &mut out
).is_null() {
287 panic
!("gmtime_r failed: {}", io
::Error
::last_os_error());
289 tm_to_rust_tm(&out
, 0, tm
);
293 pub fn time_to_local_tm(sec
: i64, tm
: &mut Tm
) {
295 let sec
= sec
as time_t
;
296 let mut out
= mem
::zeroed();
297 if libc
::localtime_r(&sec
, &mut out
).is_null() {
298 panic
!("localtime_r failed: {}", io
::Error
::last_os_error());
300 #[cfg(any(target_os = "solaris", target_os = "illumos"))]
303 // < 0 means we don't know; assume we're not in DST.
304 if out
.tm_isdst
== 0 {
305 // timezone is seconds west of UTC, tm_gmtoff is seconds east
307 } else if out
.tm_isdst
> 0 {
313 #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
314 let gmtoff
= out
.tm_gmtoff
;
315 tm_to_rust_tm(&out
, gmtoff
as i32, tm
);
319 pub fn utc_tm_to_time(rust_tm
: &Tm
) -> i64 {
320 #[cfg(all(target_os = "android", target_pointer_width = "32"))]
321 use libc
::timegm64
as timegm
;
323 all(target_os
= "android", target_pointer_width
= "32"),
325 target_os
= "solaris",
326 target_os
= "illumos"
330 let mut tm
= unsafe { mem::zeroed() }
;
331 rust_tm_to_tm(rust_tm
, &mut tm
);
332 unsafe { timegm(&mut tm) as i64 }
335 pub fn local_tm_to_time(rust_tm
: &Tm
) -> i64 {
336 let mut tm
= unsafe { mem::zeroed() }
;
337 rust_tm_to_tm(rust_tm
, &mut tm
);
338 unsafe { libc::mktime(&mut tm) as i64 }
341 #[cfg(any(target_os = "macos", target_os = "ios"))]
344 use libc
::{self, timeval, mach_timebase_info}
;
346 use std
::sync
::{Once, ONCE_INIT}
;
347 use std
::ops
::{Add, Sub}
;
351 fn info() -> &'
static mach_timebase_info
{
352 static mut INFO
: mach_timebase_info
= mach_timebase_info
{
356 static ONCE
: Once
= ONCE_INIT
;
360 mach_timebase_info(&mut INFO
);
366 pub fn get_time() -> (i64, i32) {
368 let mut tv
= timeval { tv_sec: 0, tv_usec: 0 }
;
369 unsafe { libc::gettimeofday(&mut tv, ptr::null_mut()); }
370 (tv
.tv_sec
as i64, tv
.tv_usec
* 1000)
375 pub fn get_precise_ns() -> u64 {
377 let time
= libc
::mach_absolute_time();
379 time
* info
.numer
as u64 / info
.denom
as u64
383 #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug)]
384 pub struct SteadyTime { t: u64 }
387 pub fn now() -> SteadyTime
{
388 SteadyTime { t: get_precise_ns() }
391 impl Sub
for SteadyTime
{
392 type Output
= Duration
;
393 fn sub(self, other
: SteadyTime
) -> Duration
{
394 Duration
::nanoseconds(self.t
as i64 - other
.t
as i64)
397 impl Sub
<Duration
> for SteadyTime
{
398 type Output
= SteadyTime
;
399 fn sub(self, other
: Duration
) -> SteadyTime
{
403 impl Add
<Duration
> for SteadyTime
{
404 type Output
= SteadyTime
;
405 fn add(self, other
: Duration
) -> SteadyTime
{
406 let delta
= other
.num_nanoseconds().unwrap();
408 t
: (self.t
as i64 + delta
) as u64
418 pub fn set_los_angeles_time_zone() -> TzReset
{
420 env
::set_var("TZ", "America/Los_Angeles");
426 pub fn set_london_with_dst_time_zone() -> TzReset
{
428 env
::set_var("TZ", "Europe/London");
433 #[cfg(all(not(target_os = "macos"), not(target_os = "ios")))]
436 use std
::cmp
::Ordering
;
437 use std
::ops
::{Add, Sub}
;
442 pub fn get_time() -> (i64, i32) {
443 let mut tv
= libc
::timespec { tv_sec: 0, tv_nsec: 0 }
;
444 unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, &mut tv); }
445 (tv
.tv_sec
as i64, tv
.tv_nsec
as i32)
448 pub fn get_precise_ns() -> u64 {
449 let mut ts
= libc
::timespec { tv_sec: 0, tv_nsec: 0 }
;
451 libc
::clock_gettime(libc
::CLOCK_MONOTONIC
, &mut ts
);
453 (ts
.tv_sec
as u64) * 1000000000 + (ts
.tv_nsec
as u64)
457 pub struct SteadyTime
{
461 impl fmt
::Debug
for SteadyTime
{
462 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
463 write
!(fmt
, "SteadyTime {{ tv_sec: {:?}, tv_nsec: {:?} }}",
464 self.t
.tv_sec
, self.t
.tv_nsec
)
468 impl Clone
for SteadyTime
{
469 fn clone(&self) -> SteadyTime
{
470 SteadyTime { t: self.t }
475 pub fn now() -> SteadyTime
{
476 let mut t
= SteadyTime
{
483 assert_eq
!(0, libc
::clock_gettime(libc
::CLOCK_MONOTONIC
,
490 impl Sub
for SteadyTime
{
491 type Output
= Duration
;
492 fn sub(self, other
: SteadyTime
) -> Duration
{
493 if self.t
.tv_nsec
>= other
.t
.tv_nsec
{
494 Duration
::seconds(self.t
.tv_sec
as i64 - other
.t
.tv_sec
as i64) +
495 Duration
::nanoseconds(self.t
.tv_nsec
as i64 - other
.t
.tv_nsec
as i64)
497 Duration
::seconds(self.t
.tv_sec
as i64 - 1 - other
.t
.tv_sec
as i64) +
498 Duration
::nanoseconds(self.t
.tv_nsec
as i64 + ::NSEC_PER_SEC
as i64 -
499 other
.t
.tv_nsec
as i64)
504 impl Sub
<Duration
> for SteadyTime
{
505 type Output
= SteadyTime
;
506 fn sub(self, other
: Duration
) -> SteadyTime
{
511 impl Add
<Duration
> for SteadyTime
{
512 type Output
= SteadyTime
;
513 fn add(mut self, other
: Duration
) -> SteadyTime
{
514 let seconds
= other
.num_seconds();
515 let nanoseconds
= other
- Duration
::seconds(seconds
);
516 let nanoseconds
= nanoseconds
.num_nanoseconds().unwrap();
518 #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
520 #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
521 type nsec
= libc
::c_long
;
523 self.t
.tv_sec
+= seconds
as libc
::time_t
;
524 self.t
.tv_nsec
+= nanoseconds
as nsec
;
525 if self.t
.tv_nsec
>= ::NSEC_PER_SEC
as nsec
{
526 self.t
.tv_nsec
-= ::NSEC_PER_SEC
as nsec
;
528 } else if self.t
.tv_nsec
< 0 {
530 self.t
.tv_nsec
+= ::NSEC_PER_SEC
as nsec
;
536 impl PartialOrd
for SteadyTime
{
537 fn partial_cmp(&self, other
: &SteadyTime
) -> Option
<Ordering
> {
538 Some(self.cmp(other
))
542 impl Ord
for SteadyTime
{
543 fn cmp(&self, other
: &SteadyTime
) -> Ordering
{
544 match self.t
.tv_sec
.cmp(&other
.t
.tv_sec
) {
545 Ordering
::Equal
=> self.t
.tv_nsec
.cmp(&other
.t
.tv_nsec
),
551 impl PartialEq
for SteadyTime
{
552 fn eq(&self, other
: &SteadyTime
) -> bool
{
553 self.t
.tv_sec
== other
.t
.tv_sec
&&
554 self.t
.tv_nsec
== other
.t
.tv_nsec
558 impl Eq
for SteadyTime {}
564 #[allow(non_snake_case)]
569 use std
::sync
::{Once, ONCE_INIT}
;
570 use std
::ops
::{Add, Sub}
;
573 use winapi
::um
::winnt
::*;
574 use winapi
::shared
::minwindef
::*;
575 use winapi
::um
::minwinbase
::SYSTEMTIME
;
576 use winapi
::um
::profileapi
::*;
577 use winapi
::um
::timezoneapi
::*;
578 use winapi
::um
::sysinfoapi
::GetSystemTimeAsFileTime
;
580 fn frequency() -> i64 {
581 static mut FREQUENCY
: i64 = 0;
583 static ONCE
: Once
= ONCE_INIT
;
587 let mut l
= i64_to_large_integer(0);
588 QueryPerformanceFrequency(&mut l
);
589 FREQUENCY
= large_integer_to_i64(l
);
595 fn i64_to_large_integer(i
: i64) -> LARGE_INTEGER
{
597 let mut large_integer
: LARGE_INTEGER
= mem
::zeroed();
598 *large_integer
.QuadPart_mut() = i
;
603 fn large_integer_to_i64(l
: LARGE_INTEGER
) -> i64 {
609 const HECTONANOSECS_IN_SEC
: i64 = 10_000_000;
610 const HECTONANOSEC_TO_UNIX_EPOCH
: i64 = 11_644_473_600 * HECTONANOSECS_IN_SEC
;
612 fn time_to_file_time(sec
: i64) -> FILETIME
{
613 let t
= (((sec
* HECTONANOSECS_IN_SEC
) + HECTONANOSEC_TO_UNIX_EPOCH
)) as u64;
615 dwLowDateTime
: t
as DWORD
,
616 dwHighDateTime
: (t
>> 32) as DWORD
620 fn file_time_as_u64(ft
: &FILETIME
) -> u64 {
621 ((ft
.dwHighDateTime
as u64) << 32) | (ft
.dwLowDateTime
as u64)
624 fn file_time_to_nsec(ft
: &FILETIME
) -> i32 {
625 let t
= file_time_as_u64(ft
) as i64;
626 ((t
% HECTONANOSECS_IN_SEC
) * 100) as i32
629 fn file_time_to_unix_seconds(ft
: &FILETIME
) -> i64 {
630 let t
= file_time_as_u64(ft
) as i64;
631 ((t
- HECTONANOSEC_TO_UNIX_EPOCH
) / HECTONANOSECS_IN_SEC
) as i64
634 fn system_time_to_file_time(sys
: &SYSTEMTIME
) -> FILETIME
{
636 let mut ft
= mem
::zeroed();
637 SystemTimeToFileTime(sys
, &mut ft
);
642 fn tm_to_system_time(tm
: &Tm
) -> SYSTEMTIME
{
643 let mut sys
: SYSTEMTIME
= unsafe { mem::zeroed() }
;
644 sys
.wSecond
= tm
.tm_sec
as WORD
;
645 sys
.wMinute
= tm
.tm_min
as WORD
;
646 sys
.wHour
= tm
.tm_hour
as WORD
;
647 sys
.wDay
= tm
.tm_mday
as WORD
;
648 sys
.wDayOfWeek
= tm
.tm_wday
as WORD
;
649 sys
.wMonth
= (tm
.tm_mon
+ 1) as WORD
;
650 sys
.wYear
= (tm
.tm_year
+ 1900) as WORD
;
654 fn system_time_to_tm(sys
: &SYSTEMTIME
, tm
: &mut Tm
) {
655 tm
.tm_sec
= sys
.wSecond
as i32;
656 tm
.tm_min
= sys
.wMinute
as i32;
657 tm
.tm_hour
= sys
.wHour
as i32;
658 tm
.tm_mday
= sys
.wDay
as i32;
659 tm
.tm_wday
= sys
.wDayOfWeek
as i32;
660 tm
.tm_mon
= (sys
.wMonth
- 1) as i32;
661 tm
.tm_year
= (sys
.wYear
- 1900) as i32;
662 tm
.tm_yday
= yday(tm
.tm_year
, tm
.tm_mon
+ 1, tm
.tm_mday
);
664 fn yday(year
: i32, month
: i32, day
: i32) -> i32 {
665 let leap
= if month
> 2 {
666 if year
% 4 == 0 { 1 }
else { 2 }
670 let july
= if month
> 7 { 1 }
else { 0 }
;
672 (month
- 1) * 30 + month
/ 2 + (day
- 1) - leap
+ july
677 ($name
:ident($
($arg
:expr
),*)) => {
678 if $
name($
($arg
),*) == 0 {
679 panic
!(concat
!(stringify
!($name
), " failed with: {}"),
680 io
::Error
::last_os_error());
685 pub fn time_to_utc_tm(sec
: i64, tm
: &mut Tm
) {
686 let mut out
= unsafe { mem::zeroed() }
;
687 let ft
= time_to_file_time(sec
);
689 call
!(FileTimeToSystemTime(&ft
, &mut out
));
691 system_time_to_tm(&out
, tm
);
695 pub fn time_to_local_tm(sec
: i64, tm
: &mut Tm
) {
696 let ft
= time_to_file_time(sec
);
698 let mut utc
= mem
::zeroed();
699 let mut local
= mem
::zeroed();
700 call
!(FileTimeToSystemTime(&ft
, &mut utc
));
701 call
!(SystemTimeToTzSpecificLocalTime(0 as *const _
,
702 &mut utc
, &mut local
));
703 system_time_to_tm(&local
, tm
);
705 let local
= system_time_to_file_time(&local
);
706 let local_sec
= file_time_to_unix_seconds(&local
);
708 let mut tz
= mem
::zeroed();
709 GetTimeZoneInformation(&mut tz
);
711 // SystemTimeToTzSpecificLocalTime already applied the biases so
712 // check if it non standard
713 tm
.tm_utcoff
= (local_sec
- sec
) as i32;
714 tm
.tm_isdst
= if tm
.tm_utcoff
== -60 * (tz
.Bias
+ tz
.StandardBias
) {
722 pub fn utc_tm_to_time(tm
: &Tm
) -> i64 {
724 let mut ft
= mem
::zeroed();
725 let sys_time
= tm_to_system_time(tm
);
726 call
!(SystemTimeToFileTime(&sys_time
, &mut ft
));
727 file_time_to_unix_seconds(&ft
)
731 pub fn local_tm_to_time(tm
: &Tm
) -> i64 {
733 let mut ft
= mem
::zeroed();
734 let mut utc
= mem
::zeroed();
735 let mut sys_time
= tm_to_system_time(tm
);
736 call
!(TzSpecificLocalTimeToSystemTime(0 as *mut _
,
737 &mut sys_time
, &mut utc
));
738 call
!(SystemTimeToFileTime(&utc
, &mut ft
));
739 file_time_to_unix_seconds(&ft
)
743 pub fn get_time() -> (i64, i32) {
745 let mut ft
= mem
::zeroed();
746 GetSystemTimeAsFileTime(&mut ft
);
747 (file_time_to_unix_seconds(&ft
), file_time_to_nsec(&ft
))
751 pub fn get_precise_ns() -> u64 {
752 let mut ticks
= i64_to_large_integer(0);
754 assert
!(QueryPerformanceCounter(&mut ticks
) == 1);
756 mul_div_i64(large_integer_to_i64(ticks
), 1000000000, frequency()) as u64
760 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
761 pub struct SteadyTime
{
766 pub fn now() -> SteadyTime
{
767 let mut l
= i64_to_large_integer(0);
768 unsafe { QueryPerformanceCounter(&mut l); }
769 SteadyTime { t : large_integer_to_i64(l) }
773 impl Sub
for SteadyTime
{
774 type Output
= Duration
;
775 fn sub(self, other
: SteadyTime
) -> Duration
{
776 let diff
= self.t
as i64 - other
.t
as i64;
777 Duration
::nanoseconds(mul_div_i64(diff
, 1000000000,
782 impl Sub
<Duration
> for SteadyTime
{
783 type Output
= SteadyTime
;
784 fn sub(self, other
: Duration
) -> SteadyTime
{
789 impl Add
<Duration
> for SteadyTime
{
790 type Output
= SteadyTime
;
791 fn add(mut self, other
: Duration
) -> SteadyTime
{
792 self.t
+= (other
.num_microseconds().unwrap() * frequency() /
800 old
: TIME_ZONE_INFORMATION
,
804 impl Drop
for TzReset
{
807 call
!(SetTimeZoneInformation(&self.old
));
813 pub fn set_los_angeles_time_zone() -> TzReset
{
814 acquire_privileges();
817 let mut tz
= mem
::zeroed
::<TIME_ZONE_INFORMATION
>();
818 GetTimeZoneInformation(&mut tz
);
819 let ret
= TzReset { old: tz }
;
821 call
!(SetTimeZoneInformation(&tz
));
827 pub fn set_london_with_dst_time_zone() -> TzReset
{
828 acquire_privileges();
831 let mut tz
= mem
::zeroed
::<TIME_ZONE_INFORMATION
>();
832 GetTimeZoneInformation(&mut tz
);
833 let ret
= TzReset { old: tz }
;
834 // Since date set precisely this is 2015's dates
836 tz
.DaylightBias
= -60;
837 tz
.DaylightDate
.wYear
= 0;
838 tz
.DaylightDate
.wMonth
= 3;
839 tz
.DaylightDate
.wDayOfWeek
= 0;
840 tz
.DaylightDate
.wDay
= 5;
841 tz
.DaylightDate
.wHour
= 2;
843 tz
.StandardDate
.wYear
= 0;
844 tz
.StandardDate
.wMonth
= 10;
845 tz
.StandardDate
.wDayOfWeek
= 0;
846 tz
.StandardDate
.wDay
= 5;
847 tz
.StandardDate
.wHour
= 2;
848 call
!(SetTimeZoneInformation(&tz
));
853 // Ensures that this process has the necessary privileges to set a new time
854 // zone, and this is all transcribed from:
855 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724944%28v=vs.85%29.aspx
857 fn acquire_privileges() {
858 use winapi
::um
::processthreadsapi
::*;
859 use winapi
::um
::winbase
::LookupPrivilegeValueA
;
860 const SE_PRIVILEGE_ENABLED
: DWORD
= 2;
862 static INIT
: Once
= ONCE_INIT
;
866 fn AdjustTokenPrivileges(
867 TokenHandle
: HANDLE
, DisableAllPrivileges
: BOOL
, NewState
: PTOKEN_PRIVILEGES
,
868 BufferLength
: DWORD
, PreviousState
: PTOKEN_PRIVILEGES
, ReturnLength
: PDWORD
,
872 INIT
.call_once(|| unsafe {
873 let mut hToken
= 0 as *mut _
;
874 call
!(OpenProcessToken(GetCurrentProcess(),
875 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
878 let mut tkp
= mem
::zeroed
::<TOKEN_PRIVILEGES
>();
879 assert_eq
!(tkp
.Privileges
.len(), 1);
880 let c
= ::std
::ffi
::CString
::new("SeTimeZonePrivilege").unwrap();
881 call
!(LookupPrivilegeValueA(0 as *const _
, c
.as_ptr(),
882 &mut tkp
.Privileges
[0].Luid
));
883 tkp
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
884 tkp
.PrivilegeCount
= 1;
885 call
!(AdjustTokenPrivileges(hToken
, FALSE
, &mut tkp
, 0,
886 0 as *mut _
, 0 as *mut _
));
892 // Computes (value*numer)/denom without overflow, as long as both
893 // (numer*denom) and the overall result fit into i64 (which is the case
894 // for our time conversions).
895 fn mul_div_i64(value
: i64, numer
: i64, denom
: i64) -> i64 {
896 let q
= value
/ denom
;
897 let r
= value
% denom
;
898 // Decompose value as (value/denom*denom + value%denom),
899 // substitute into (value*numer)/denom and simplify.
900 // r < denom, so (denom*numer) is the upper bound of (r*numer)
901 q
* numer
+ r
* numer
/ denom
906 assert_eq
!(mul_div_i64( 1_000_000_000_001, 1_000_000_000, 1_000_000),
907 1_000_000_000_001_000);
908 assert_eq
!(mul_div_i64(-1_000_000_000_001, 1_000_000_000, 1_000_000),
909 -1_000_000_000_001_000);
910 assert_eq
!(mul_div_i64(-1_000_000_000_001,-1_000_000_000, 1_000_000),
911 1_000_000_000_001_000);
912 assert_eq
!(mul_div_i64( 1_000_000_000_001, 1_000_000_000,-1_000_000),
913 -1_000_000_000_001_000);
914 assert_eq
!(mul_div_i64( 1_000_000_000_001,-1_000_000_000,-1_000_000),
915 1_000_000_000_001_000);