3 pub use self::inner
::*;
6 all(target_arch
= "wasm32", not(target_os
= "emscripten")),
13 pub fn time_to_tm(ts
: i64, tm
: &mut Tm
) {
14 let leapyear
= |year
| -> bool
{
15 year
% 4 == 0 && (year
% 100 != 0 || year
% 400 == 0)
18 static _ytab
: [[i64; 12]; 2] = [
19 [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ],
20 [ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ]
25 let dayclock
= ts
% 86400;
26 let mut dayno
= ts
/ 86400;
28 tm
.tm_sec
= (dayclock
% 60) as i32;
29 tm
.tm_min
= ((dayclock
% 3600) / 60) as i32;
30 tm
.tm_hour
= (dayclock
/ 3600) as i32;
31 tm
.tm_wday
= ((dayno
+ 4) % 7) as i32;
33 let yearsize
= if leapyear(year
) {
38 if dayno
>= yearsize
{
45 tm
.tm_year
= (year
- 1900) as i32;
46 tm
.tm_yday
= dayno
as i32;
48 while dayno
>= _ytab
[if leapyear(year
) { 1 }
else { 0 }
][mon
] {
49 dayno
-= _ytab
[if leapyear(year
) { 1 }
else { 0 }
][mon
];
52 tm
.tm_mon
= mon
as i32;
53 tm
.tm_mday
= dayno
as i32 + 1;
57 pub fn tm_to_time(tm
: &Tm
) -> i64 {
58 let mut y
= tm
.tm_year
as i64 + 1900;
59 let mut m
= tm
.tm_mon
as i64 + 1;
64 let d
= tm
.tm_mday
as i64;
65 let h
= tm
.tm_hour
as i64;
66 let mi
= tm
.tm_min
as i64;
67 let s
= tm
.tm_sec
as i64;
68 (365*y
+ y
/4 - y
/100 + y
/400 + 3*(m
+1)/5 + 30*m
+ d
- 719561)
69 * 86400 + 3600 * h
+ 60 * mi
+ s
73 #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
75 use std
::ops
::{Add, Sub}
;
78 use super::common
::{time_to_tm, tm_to_time}
;
80 #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
81 pub struct SteadyTime
;
83 pub fn time_to_utc_tm(sec
: i64, tm
: &mut Tm
) {
87 pub fn time_to_local_tm(sec
: i64, tm
: &mut Tm
) {
88 // FIXME: Add timezone logic
92 pub fn utc_tm_to_time(tm
: &Tm
) -> i64 {
96 pub fn local_tm_to_time(tm
: &Tm
) -> i64 {
97 // FIXME: Add timezone logic
101 pub fn get_time() -> (i64, i32) {
105 pub fn get_precise_ns() -> u64 {
110 pub fn now() -> SteadyTime
{
115 impl Sub
for SteadyTime
{
116 type Output
= Duration
;
117 fn sub(self, _other
: SteadyTime
) -> Duration
{
122 impl Sub
<Duration
> for SteadyTime
{
123 type Output
= SteadyTime
;
124 fn sub(self, _other
: Duration
) -> SteadyTime
{
129 impl Add
<Duration
> for SteadyTime
{
130 type Output
= SteadyTime
;
131 fn add(self, _other
: Duration
) -> SteadyTime
{
137 #[cfg(target_os = "redox")]
140 use std
::cmp
::Ordering
;
141 use std
::ops
::{Add, Sub}
;
143 use super::common
::{time_to_tm, tm_to_time}
;
148 pub fn time_to_utc_tm(sec
: i64, tm
: &mut Tm
) {
152 pub fn time_to_local_tm(sec
: i64, tm
: &mut Tm
) {
153 // FIXME: Add timezone logic
157 pub fn utc_tm_to_time(tm
: &Tm
) -> i64 {
161 pub fn local_tm_to_time(tm
: &Tm
) -> i64 {
162 // FIXME: Add timezone logic
166 pub fn get_time() -> (i64, i32) {
167 let mut tv
= syscall
::TimeSpec { tv_sec: 0, tv_nsec: 0 }
;
168 syscall
::clock_gettime(syscall
::CLOCK_REALTIME
, &mut tv
).unwrap();
169 (tv
.tv_sec
as i64, tv
.tv_nsec
as i32)
172 pub fn get_precise_ns() -> u64 {
173 let mut ts
= syscall
::TimeSpec { tv_sec: 0, tv_nsec: 0 }
;
174 syscall
::clock_gettime(syscall
::CLOCK_MONOTONIC
, &mut ts
).unwrap();
175 (ts
.tv_sec
as u64) * 1000000000 + (ts
.tv_nsec
as u64)
179 pub struct SteadyTime
{
180 t
: syscall
::TimeSpec
,
183 impl fmt
::Debug
for SteadyTime
{
184 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
185 write
!(fmt
, "SteadyTime {{ tv_sec: {:?}, tv_nsec: {:?} }}",
186 self.t
.tv_sec
, self.t
.tv_nsec
)
190 impl Clone
for SteadyTime
{
191 fn clone(&self) -> SteadyTime
{
192 SteadyTime { t: self.t }
197 pub fn now() -> SteadyTime
{
198 let mut t
= SteadyTime
{
199 t
: syscall
::TimeSpec
{
204 syscall
::clock_gettime(syscall
::CLOCK_MONOTONIC
, &mut t
.t
).unwrap();
209 impl Sub
for SteadyTime
{
210 type Output
= Duration
;
211 fn sub(self, other
: SteadyTime
) -> Duration
{
212 if self.t
.tv_nsec
>= other
.t
.tv_nsec
{
213 Duration
::seconds(self.t
.tv_sec
as i64 - other
.t
.tv_sec
as i64) +
214 Duration
::nanoseconds(self.t
.tv_nsec
as i64 - other
.t
.tv_nsec
as i64)
216 Duration
::seconds(self.t
.tv_sec
as i64 - 1 - other
.t
.tv_sec
as i64) +
217 Duration
::nanoseconds(self.t
.tv_nsec
as i64 + ::NSEC_PER_SEC
as i64 -
218 other
.t
.tv_nsec
as i64)
223 impl Sub
<Duration
> for SteadyTime
{
224 type Output
= SteadyTime
;
225 fn sub(self, other
: Duration
) -> SteadyTime
{
230 impl Add
<Duration
> for SteadyTime
{
231 type Output
= SteadyTime
;
232 fn add(mut self, other
: Duration
) -> SteadyTime
{
233 let seconds
= other
.num_seconds();
234 let nanoseconds
= other
- Duration
::seconds(seconds
);
235 let nanoseconds
= nanoseconds
.num_nanoseconds().unwrap();
236 self.t
.tv_sec
+= seconds
;
237 self.t
.tv_nsec
+= nanoseconds
as i32;
238 if self.t
.tv_nsec
>= ::NSEC_PER_SEC
{
239 self.t
.tv_nsec
-= ::NSEC_PER_SEC
;
241 } else if self.t
.tv_nsec
< 0 {
243 self.t
.tv_nsec
+= ::NSEC_PER_SEC
;
249 impl PartialOrd
for SteadyTime
{
250 fn partial_cmp(&self, other
: &SteadyTime
) -> Option
<Ordering
> {
251 Some(self.cmp(other
))
255 impl Ord
for SteadyTime
{
256 fn cmp(&self, other
: &SteadyTime
) -> Ordering
{
257 match self.t
.tv_sec
.cmp(&other
.t
.tv_sec
) {
258 Ordering
::Equal
=> self.t
.tv_nsec
.cmp(&other
.t
.tv_nsec
),
264 impl PartialEq
for SteadyTime
{
265 fn eq(&self, other
: &SteadyTime
) -> bool
{
266 self.t
.tv_sec
== other
.t
.tv_sec
&&
267 self.t
.tv_nsec
== other
.t
.tv_nsec
271 impl Eq
for SteadyTime {}
274 #[cfg(target_env = "sgx")]
276 use std
::ops
::{Add, Sub}
;
279 use super::common
::{time_to_tm, tm_to_time}
;
280 use std
::time
::SystemTime
;
282 /// The number of nanoseconds in seconds.
283 const NANOS_PER_SEC
: u64 = 1_000_000_000;
285 #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
286 pub struct SteadyTime
{
290 pub fn time_to_utc_tm(sec
: i64, tm
: &mut Tm
) {
294 pub fn time_to_local_tm(sec
: i64, tm
: &mut Tm
) {
295 // FIXME: Add timezone logic
299 pub fn utc_tm_to_time(tm
: &Tm
) -> i64 {
303 pub fn local_tm_to_time(tm
: &Tm
) -> i64 {
304 // FIXME: Add timezone logic
308 pub fn get_time() -> (i64, i32) {
309 SteadyTime
::now().t
.raw()
312 pub fn get_precise_ns() -> u64 {
313 // This unwrap is safe because current time is well ahead of UNIX_EPOCH, unless system clock is adjusted backward.
314 let std_duration
= SystemTime
::now().duration_since(SystemTime
::UNIX_EPOCH
).unwrap();
315 std_duration
.as_secs() * NANOS_PER_SEC
+ std_duration
.subsec_nanos() as u64
319 pub fn now() -> SteadyTime
{
320 // This unwrap is safe because current time is well ahead of UNIX_EPOCH, unless system clock is adjusted backward.
321 let std_duration
= SystemTime
::now().duration_since(SystemTime
::UNIX_EPOCH
).unwrap();
322 // This unwrap is safe because duration is well within the limits of i64.
323 let duration
= Duration
::from_std(std_duration
).unwrap();
324 SteadyTime { t: duration }
328 impl Sub
for SteadyTime
{
329 type Output
= Duration
;
330 fn sub(self, other
: SteadyTime
) -> Duration
{
335 impl Sub
<Duration
> for SteadyTime
{
336 type Output
= SteadyTime
;
337 fn sub(self, other
: Duration
) -> SteadyTime
{
338 SteadyTime { t: self.t - other }
342 impl Add
<Duration
> for SteadyTime
{
343 type Output
= SteadyTime
;
344 fn add(self, other
: Duration
) -> SteadyTime
{
345 SteadyTime { t: self.t + other }
352 use libc
::{self, time_t}
;
357 #[cfg(any(target_os = "macos", target_os = "ios"))]
358 pub use self::mac
::*;
359 #[cfg(all(not(target_os = "macos"), not(target_os = "ios")))]
360 pub use self::unix
::*;
362 #[cfg(target_os = "solaris")]
364 static timezone
: time_t
;
365 static altzone
: time_t
;
368 fn rust_tm_to_tm(rust_tm
: &Tm
, tm
: &mut libc
::tm
) {
369 tm
.tm_sec
= rust_tm
.tm_sec
;
370 tm
.tm_min
= rust_tm
.tm_min
;
371 tm
.tm_hour
= rust_tm
.tm_hour
;
372 tm
.tm_mday
= rust_tm
.tm_mday
;
373 tm
.tm_mon
= rust_tm
.tm_mon
;
374 tm
.tm_year
= rust_tm
.tm_year
;
375 tm
.tm_wday
= rust_tm
.tm_wday
;
376 tm
.tm_yday
= rust_tm
.tm_yday
;
377 tm
.tm_isdst
= rust_tm
.tm_isdst
;
380 fn tm_to_rust_tm(tm
: &libc
::tm
, utcoff
: i32, rust_tm
: &mut Tm
) {
381 rust_tm
.tm_sec
= tm
.tm_sec
;
382 rust_tm
.tm_min
= tm
.tm_min
;
383 rust_tm
.tm_hour
= tm
.tm_hour
;
384 rust_tm
.tm_mday
= tm
.tm_mday
;
385 rust_tm
.tm_mon
= tm
.tm_mon
;
386 rust_tm
.tm_year
= tm
.tm_year
;
387 rust_tm
.tm_wday
= tm
.tm_wday
;
388 rust_tm
.tm_yday
= tm
.tm_yday
;
389 rust_tm
.tm_isdst
= tm
.tm_isdst
;
390 rust_tm
.tm_utcoff
= utcoff
;
393 #[cfg(any(target_os = "nacl", target_os = "solaris"))]
394 unsafe fn timegm(tm
: *mut libc
::tm
) -> time_t
{
395 use std
::env
::{set_var, var_os, remove_var}
;
402 let current_tz
= var_os("TZ");
403 set_var("TZ", "UTC");
406 ret
= libc
::mktime(tm
);
408 if let Some(tz
) = current_tz
{
418 pub fn time_to_utc_tm(sec
: i64, tm
: &mut Tm
) {
420 let sec
= sec
as time_t
;
421 let mut out
= mem
::zeroed();
422 if libc
::gmtime_r(&sec
, &mut out
).is_null() {
423 panic
!("gmtime_r failed: {}", io
::Error
::last_os_error());
425 tm_to_rust_tm(&out
, 0, tm
);
429 pub fn time_to_local_tm(sec
: i64, tm
: &mut Tm
) {
431 let sec
= sec
as time_t
;
432 let mut out
= mem
::zeroed();
433 if libc
::localtime_r(&sec
, &mut out
).is_null() {
434 panic
!("localtime_r failed: {}", io
::Error
::last_os_error());
436 #[cfg(target_os = "solaris")]
439 // < 0 means we don't know; assume we're not in DST.
440 if out
.tm_isdst
== 0 {
441 // timezone is seconds west of UTC, tm_gmtoff is seconds east
443 } else if out
.tm_isdst
> 0 {
449 #[cfg(not(target_os = "solaris"))]
450 let gmtoff
= out
.tm_gmtoff
;
451 tm_to_rust_tm(&out
, gmtoff
as i32, tm
);
455 pub fn utc_tm_to_time(rust_tm
: &Tm
) -> i64 {
456 #[cfg(all(target_os = "android", target_pointer_width = "32"))]
457 use libc
::timegm64
as timegm
;
458 #[cfg(not(any(all(target_os = "android", target_pointer_width = "32"), target_os = "nacl", target_os = "solaris")))]
461 let mut tm
= unsafe { mem::zeroed() }
;
462 rust_tm_to_tm(rust_tm
, &mut tm
);
463 unsafe { timegm(&mut tm) as i64 }
466 pub fn local_tm_to_time(rust_tm
: &Tm
) -> i64 {
467 let mut tm
= unsafe { mem::zeroed() }
;
468 rust_tm_to_tm(rust_tm
, &mut tm
);
469 unsafe { libc::mktime(&mut tm) as i64 }
472 #[cfg(any(target_os = "macos", target_os = "ios"))]
474 use libc
::{self, timeval, mach_timebase_info}
;
475 use std
::sync
::{Once, ONCE_INIT}
;
476 use std
::ops
::{Add, Sub}
;
479 fn info() -> &'
static mach_timebase_info
{
480 static mut INFO
: mach_timebase_info
= mach_timebase_info
{
484 static ONCE
: Once
= ONCE_INIT
;
488 mach_timebase_info(&mut INFO
);
494 pub fn get_time() -> (i64, i32) {
496 let mut tv
= timeval { tv_sec: 0, tv_usec: 0 }
;
497 unsafe { libc::gettimeofday(&mut tv, ptr::null_mut()); }
498 (tv
.tv_sec
as i64, tv
.tv_usec
* 1000)
502 pub fn get_precise_ns() -> u64 {
504 let time
= libc
::mach_absolute_time();
506 time
* info
.numer
as u64 / info
.denom
as u64
510 #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug)]
511 pub struct SteadyTime { t: u64 }
514 pub fn now() -> SteadyTime
{
515 SteadyTime { t: get_precise_ns() }
518 impl Sub
for SteadyTime
{
519 type Output
= Duration
;
520 fn sub(self, other
: SteadyTime
) -> Duration
{
521 Duration
::nanoseconds(self.t
as i64 - other
.t
as i64)
524 impl Sub
<Duration
> for SteadyTime
{
525 type Output
= SteadyTime
;
526 fn sub(self, other
: Duration
) -> SteadyTime
{
530 impl Add
<Duration
> for SteadyTime
{
531 type Output
= SteadyTime
;
532 fn add(self, other
: Duration
) -> SteadyTime
{
533 let delta
= other
.num_nanoseconds().unwrap();
535 t
: (self.t
as i64 + delta
) as u64
545 pub fn set_los_angeles_time_zone() -> TzReset
{
547 env
::set_var("TZ", "America/Los_Angeles");
553 pub fn set_london_with_dst_time_zone() -> TzReset
{
555 env
::set_var("TZ", "Europe/London");
560 #[cfg(all(not(target_os = "macos"), not(target_os = "ios")))]
563 use std
::cmp
::Ordering
;
564 use std
::ops
::{Add, Sub}
;
569 pub fn get_time() -> (i64, i32) {
570 let mut tv
= libc
::timespec { tv_sec: 0, tv_nsec: 0 }
;
571 unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, &mut tv); }
572 (tv
.tv_sec
as i64, tv
.tv_nsec
as i32)
575 pub fn get_precise_ns() -> u64 {
576 let mut ts
= libc
::timespec { tv_sec: 0, tv_nsec: 0 }
;
578 libc
::clock_gettime(libc
::CLOCK_MONOTONIC
, &mut ts
);
580 (ts
.tv_sec
as u64) * 1000000000 + (ts
.tv_nsec
as u64)
584 pub struct SteadyTime
{
588 impl fmt
::Debug
for SteadyTime
{
589 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
590 write
!(fmt
, "SteadyTime {{ tv_sec: {:?}, tv_nsec: {:?} }}",
591 self.t
.tv_sec
, self.t
.tv_nsec
)
595 impl Clone
for SteadyTime
{
596 fn clone(&self) -> SteadyTime
{
597 SteadyTime { t: self.t }
602 pub fn now() -> SteadyTime
{
603 let mut t
= SteadyTime
{
610 assert_eq
!(0, libc
::clock_gettime(libc
::CLOCK_MONOTONIC
,
617 impl Sub
for SteadyTime
{
618 type Output
= Duration
;
619 fn sub(self, other
: SteadyTime
) -> Duration
{
620 if self.t
.tv_nsec
>= other
.t
.tv_nsec
{
621 Duration
::seconds(self.t
.tv_sec
as i64 - other
.t
.tv_sec
as i64) +
622 Duration
::nanoseconds(self.t
.tv_nsec
as i64 - other
.t
.tv_nsec
as i64)
624 Duration
::seconds(self.t
.tv_sec
as i64 - 1 - other
.t
.tv_sec
as i64) +
625 Duration
::nanoseconds(self.t
.tv_nsec
as i64 + ::NSEC_PER_SEC
as i64 -
626 other
.t
.tv_nsec
as i64)
631 impl Sub
<Duration
> for SteadyTime
{
632 type Output
= SteadyTime
;
633 fn sub(self, other
: Duration
) -> SteadyTime
{
638 impl Add
<Duration
> for SteadyTime
{
639 type Output
= SteadyTime
;
640 fn add(mut self, other
: Duration
) -> SteadyTime
{
641 let seconds
= other
.num_seconds();
642 let nanoseconds
= other
- Duration
::seconds(seconds
);
643 let nanoseconds
= nanoseconds
.num_nanoseconds().unwrap();
645 #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
647 #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
648 type nsec
= libc
::c_long
;
650 self.t
.tv_sec
+= seconds
as libc
::time_t
;
651 self.t
.tv_nsec
+= nanoseconds
as nsec
;
652 if self.t
.tv_nsec
>= ::NSEC_PER_SEC
as nsec
{
653 self.t
.tv_nsec
-= ::NSEC_PER_SEC
as nsec
;
655 } else if self.t
.tv_nsec
< 0 {
657 self.t
.tv_nsec
+= ::NSEC_PER_SEC
as nsec
;
663 impl PartialOrd
for SteadyTime
{
664 fn partial_cmp(&self, other
: &SteadyTime
) -> Option
<Ordering
> {
665 Some(self.cmp(other
))
669 impl Ord
for SteadyTime
{
670 fn cmp(&self, other
: &SteadyTime
) -> Ordering
{
671 match self.t
.tv_sec
.cmp(&other
.t
.tv_sec
) {
672 Ordering
::Equal
=> self.t
.tv_nsec
.cmp(&other
.t
.tv_nsec
),
678 impl PartialEq
for SteadyTime
{
679 fn eq(&self, other
: &SteadyTime
) -> bool
{
680 self.t
.tv_sec
== other
.t
.tv_sec
&&
681 self.t
.tv_nsec
== other
.t
.tv_nsec
685 impl Eq
for SteadyTime {}
691 #[allow(non_snake_case)]
695 use std
::sync
::{Once, ONCE_INIT}
;
696 use std
::ops
::{Add, Sub}
;
699 use winapi
::um
::winnt
::*;
700 use winapi
::shared
::minwindef
::*;
701 use winapi
::um
::minwinbase
::SYSTEMTIME
;
702 use winapi
::um
::profileapi
::*;
703 use winapi
::um
::timezoneapi
::*;
704 use winapi
::um
::sysinfoapi
::GetSystemTimeAsFileTime
;
706 fn frequency() -> i64 {
707 static mut FREQUENCY
: i64 = 0;
708 static ONCE
: Once
= ONCE_INIT
;
712 let mut l
= i64_to_large_integer(0);
713 QueryPerformanceFrequency(&mut l
);
714 FREQUENCY
= large_integer_to_i64(l
);
720 fn i64_to_large_integer(i
: i64) -> LARGE_INTEGER
{
722 let mut large_integer
: LARGE_INTEGER
= mem
::zeroed();
723 *large_integer
.QuadPart_mut() = i
;
728 fn large_integer_to_i64(l
: LARGE_INTEGER
) -> i64 {
734 const HECTONANOSECS_IN_SEC
: i64 = 10_000_000;
735 const HECTONANOSEC_TO_UNIX_EPOCH
: i64 = 11_644_473_600 * HECTONANOSECS_IN_SEC
;
737 fn time_to_file_time(sec
: i64) -> FILETIME
{
738 let t
= (((sec
* HECTONANOSECS_IN_SEC
) + HECTONANOSEC_TO_UNIX_EPOCH
)) as u64;
740 dwLowDateTime
: t
as DWORD
,
741 dwHighDateTime
: (t
>> 32) as DWORD
745 fn file_time_as_u64(ft
: &FILETIME
) -> u64 {
746 ((ft
.dwHighDateTime
as u64) << 32) | (ft
.dwLowDateTime
as u64)
749 fn file_time_to_nsec(ft
: &FILETIME
) -> i32 {
750 let t
= file_time_as_u64(ft
) as i64;
751 ((t
% HECTONANOSECS_IN_SEC
) * 100) as i32
754 fn file_time_to_unix_seconds(ft
: &FILETIME
) -> i64 {
755 let t
= file_time_as_u64(ft
) as i64;
756 ((t
- HECTONANOSEC_TO_UNIX_EPOCH
) / HECTONANOSECS_IN_SEC
) as i64
759 fn system_time_to_file_time(sys
: &SYSTEMTIME
) -> FILETIME
{
761 let mut ft
= mem
::zeroed();
762 SystemTimeToFileTime(sys
, &mut ft
);
767 fn tm_to_system_time(tm
: &Tm
) -> SYSTEMTIME
{
768 let mut sys
: SYSTEMTIME
= unsafe { mem::zeroed() }
;
769 sys
.wSecond
= tm
.tm_sec
as WORD
;
770 sys
.wMinute
= tm
.tm_min
as WORD
;
771 sys
.wHour
= tm
.tm_hour
as WORD
;
772 sys
.wDay
= tm
.tm_mday
as WORD
;
773 sys
.wDayOfWeek
= tm
.tm_wday
as WORD
;
774 sys
.wMonth
= (tm
.tm_mon
+ 1) as WORD
;
775 sys
.wYear
= (tm
.tm_year
+ 1900) as WORD
;
779 fn system_time_to_tm(sys
: &SYSTEMTIME
, tm
: &mut Tm
) {
780 tm
.tm_sec
= sys
.wSecond
as i32;
781 tm
.tm_min
= sys
.wMinute
as i32;
782 tm
.tm_hour
= sys
.wHour
as i32;
783 tm
.tm_mday
= sys
.wDay
as i32;
784 tm
.tm_wday
= sys
.wDayOfWeek
as i32;
785 tm
.tm_mon
= (sys
.wMonth
- 1) as i32;
786 tm
.tm_year
= (sys
.wYear
- 1900) as i32;
787 tm
.tm_yday
= yday(tm
.tm_year
, tm
.tm_mon
+ 1, tm
.tm_mday
);
789 fn yday(year
: i32, month
: i32, day
: i32) -> i32 {
790 let leap
= if month
> 2 {
791 if year
% 4 == 0 { 1 }
else { 2 }
795 let july
= if month
> 7 { 1 }
else { 0 }
;
797 (month
- 1) * 30 + month
/ 2 + (day
- 1) - leap
+ july
802 ($name
:ident($
($arg
:expr
),*)) => {
803 if $
name($
($arg
),*) == 0 {
804 panic
!(concat
!(stringify
!($name
), " failed with: {}"),
805 io
::Error
::last_os_error());
810 pub fn time_to_utc_tm(sec
: i64, tm
: &mut Tm
) {
811 let mut out
= unsafe { mem::zeroed() }
;
812 let ft
= time_to_file_time(sec
);
814 call
!(FileTimeToSystemTime(&ft
, &mut out
));
816 system_time_to_tm(&out
, tm
);
820 pub fn time_to_local_tm(sec
: i64, tm
: &mut Tm
) {
821 let ft
= time_to_file_time(sec
);
823 let mut utc
= mem
::zeroed();
824 let mut local
= mem
::zeroed();
825 call
!(FileTimeToSystemTime(&ft
, &mut utc
));
826 call
!(SystemTimeToTzSpecificLocalTime(0 as *const _
,
827 &mut utc
, &mut local
));
828 system_time_to_tm(&local
, tm
);
830 let local
= system_time_to_file_time(&local
);
831 let local_sec
= file_time_to_unix_seconds(&local
);
833 let mut tz
= mem
::zeroed();
834 GetTimeZoneInformation(&mut tz
);
836 // SystemTimeToTzSpecificLocalTime already applied the biases so
837 // check if it non standard
838 tm
.tm_utcoff
= (local_sec
- sec
) as i32;
839 tm
.tm_isdst
= if tm
.tm_utcoff
== -60 * (tz
.Bias
+ tz
.StandardBias
) {
847 pub fn utc_tm_to_time(tm
: &Tm
) -> i64 {
849 let mut ft
= mem
::zeroed();
850 let sys_time
= tm_to_system_time(tm
);
851 call
!(SystemTimeToFileTime(&sys_time
, &mut ft
));
852 file_time_to_unix_seconds(&ft
)
856 pub fn local_tm_to_time(tm
: &Tm
) -> i64 {
858 let mut ft
= mem
::zeroed();
859 let mut utc
= mem
::zeroed();
860 let mut sys_time
= tm_to_system_time(tm
);
861 call
!(TzSpecificLocalTimeToSystemTime(0 as *mut _
,
862 &mut sys_time
, &mut utc
));
863 call
!(SystemTimeToFileTime(&utc
, &mut ft
));
864 file_time_to_unix_seconds(&ft
)
868 pub fn get_time() -> (i64, i32) {
870 let mut ft
= mem
::zeroed();
871 GetSystemTimeAsFileTime(&mut ft
);
872 (file_time_to_unix_seconds(&ft
), file_time_to_nsec(&ft
))
876 pub fn get_precise_ns() -> u64 {
877 let mut ticks
= i64_to_large_integer(0);
879 assert
!(QueryPerformanceCounter(&mut ticks
) == 1);
881 mul_div_i64(large_integer_to_i64(ticks
), 1000000000, frequency()) as u64
885 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
886 pub struct SteadyTime
{
891 pub fn now() -> SteadyTime
{
892 let mut l
= i64_to_large_integer(0);
893 unsafe { QueryPerformanceCounter(&mut l); }
894 SteadyTime { t : large_integer_to_i64(l) }
898 impl Sub
for SteadyTime
{
899 type Output
= Duration
;
900 fn sub(self, other
: SteadyTime
) -> Duration
{
901 let diff
= self.t
as i64 - other
.t
as i64;
902 Duration
::nanoseconds(mul_div_i64(diff
, 1000000000,
907 impl Sub
<Duration
> for SteadyTime
{
908 type Output
= SteadyTime
;
909 fn sub(self, other
: Duration
) -> SteadyTime
{
914 impl Add
<Duration
> for SteadyTime
{
915 type Output
= SteadyTime
;
916 fn add(mut self, other
: Duration
) -> SteadyTime
{
917 self.t
+= (other
.num_microseconds().unwrap() * frequency() /
925 old
: TIME_ZONE_INFORMATION
,
929 impl Drop
for TzReset
{
932 call
!(SetTimeZoneInformation(&self.old
));
938 pub fn set_los_angeles_time_zone() -> TzReset
{
939 acquire_privileges();
942 let mut tz
= mem
::zeroed
::<TIME_ZONE_INFORMATION
>();
943 GetTimeZoneInformation(&mut tz
);
944 let ret
= TzReset { old: tz }
;
946 call
!(SetTimeZoneInformation(&tz
));
952 pub fn set_london_with_dst_time_zone() -> TzReset
{
953 acquire_privileges();
956 let mut tz
= mem
::zeroed
::<TIME_ZONE_INFORMATION
>();
957 GetTimeZoneInformation(&mut tz
);
958 let ret
= TzReset { old: tz }
;
959 // Since date set precisely this is 2015's dates
961 tz
.DaylightBias
= -60;
962 tz
.DaylightDate
.wYear
= 0;
963 tz
.DaylightDate
.wMonth
= 3;
964 tz
.DaylightDate
.wDayOfWeek
= 0;
965 tz
.DaylightDate
.wDay
= 5;
966 tz
.DaylightDate
.wHour
= 2;
968 tz
.StandardDate
.wYear
= 0;
969 tz
.StandardDate
.wMonth
= 10;
970 tz
.StandardDate
.wDayOfWeek
= 0;
971 tz
.StandardDate
.wDay
= 5;
972 tz
.StandardDate
.wHour
= 2;
973 call
!(SetTimeZoneInformation(&tz
));
978 // Ensures that this process has the necessary privileges to set a new time
979 // zone, and this is all transcribed from:
980 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724944%28v=vs.85%29.aspx
982 fn acquire_privileges() {
983 use std
::sync
::{ONCE_INIT, Once}
;
984 use winapi
::um
::processthreadsapi
::*;
985 use winapi
::um
::winbase
::LookupPrivilegeValueA
;
986 const SE_PRIVILEGE_ENABLED
: DWORD
= 2;
987 static INIT
: Once
= ONCE_INIT
;
991 fn AdjustTokenPrivileges(
992 TokenHandle
: HANDLE
, DisableAllPrivileges
: BOOL
, NewState
: PTOKEN_PRIVILEGES
,
993 BufferLength
: DWORD
, PreviousState
: PTOKEN_PRIVILEGES
, ReturnLength
: PDWORD
,
999 tkp
: TOKEN_PRIVILEGES
,
1000 laa
: LUID_AND_ATTRIBUTES
,
1003 INIT
.call_once(|| unsafe {
1004 let mut hToken
= 0 as *mut _
;
1005 call
!(OpenProcessToken(GetCurrentProcess(),
1006 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
1009 let mut tkp
= mem
::zeroed
::<TKP
>();
1010 assert_eq
!(tkp
.tkp
.Privileges
.len(), 0);
1011 let c
= ::std
::ffi
::CString
::new("SeTimeZonePrivilege").unwrap();
1012 call
!(LookupPrivilegeValueA(0 as *const _
, c
.as_ptr(),
1013 &mut tkp
.laa
.Luid
));
1014 tkp
.tkp
.PrivilegeCount
= 1;
1015 tkp
.laa
.Attributes
= SE_PRIVILEGE_ENABLED
;
1016 call
!(AdjustTokenPrivileges(hToken
, FALSE
, &mut tkp
.tkp
, 0,
1017 0 as *mut _
, 0 as *mut _
));
1023 // Computes (value*numer)/denom without overflow, as long as both
1024 // (numer*denom) and the overall result fit into i64 (which is the case
1025 // for our time conversions).
1026 fn mul_div_i64(value
: i64, numer
: i64, denom
: i64) -> i64 {
1027 let q
= value
/ denom
;
1028 let r
= value
% denom
;
1029 // Decompose value as (value/denom*denom + value%denom),
1030 // substitute into (value*numer)/denom and simplify.
1031 // r < denom, so (denom*numer) is the upper bound of (r*numer)
1032 q
* numer
+ r
* numer
/ denom
1037 assert_eq
!(mul_div_i64( 1_000_000_000_001, 1_000_000_000, 1_000_000),
1038 1_000_000_000_001_000);
1039 assert_eq
!(mul_div_i64(-1_000_000_000_001, 1_000_000_000, 1_000_000),
1040 -1_000_000_000_001_000);
1041 assert_eq
!(mul_div_i64(-1_000_000_000_001,-1_000_000_000, 1_000_000),
1042 1_000_000_000_001_000);
1043 assert_eq
!(mul_div_i64( 1_000_000_000_001, 1_000_000_000,-1_000_000),
1044 -1_000_000_000_001_000);
1045 assert_eq
!(mul_div_i64( 1_000_000_000_001,-1_000_000_000,-1_000_000),
1046 1_000_000_000_001_000);