diff --git a/Cargo.lock b/Cargo.lock index a936630..a0eadc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,4 +4,29 @@ version = 3 [[package]] name = "time" -version = "0.1.0" +version = "0.1.1" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index f0f0ee5..ae46ba6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,9 @@ [package] name = "time" -version = "0.1.0" -edition = "2021" \ No newline at end of file +version = "0.1.1" +edition = "2021" +publish = false + +[target.'cfg(target_family="windows")'.dependencies.winapi] +version = "0.3" +features = ["timezoneapi","impl-default","impl-debug","errhandlingapi"] \ No newline at end of file diff --git a/src/macros.rs b/src/macros.rs deleted file mode 100644 index ef5ec09..0000000 --- a/src/macros.rs +++ /dev/null @@ -1,2 +0,0 @@ - -use test; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index dbf3af2..68840ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,13 @@ -use std::arch::x86_64::_mm_pause; +#[allow(unused_imports)] use std::fs::{File, OpenOptions}; use std::io::{Seek, SeekFrom, Write}; use std::os::windows::fs::FileExt; -use std::thread::{sleep, yield_now}; +use std::thread::sleep; use std::time::{Duration, Instant}; type Result = std::result::Result; +#[cfg(target_family = "windows")] +mod windows; fn main() -> Result<()> { let env: Vec = std::env::args().collect(); @@ -16,6 +18,16 @@ fn main() -> Result<()> { ); return Ok(()); } + let timezone; + #[cfg(target_family = "windows")] + { + timezone = windows::get_convert_utc_to_local() + }; + #[cfg(not(target_family = "windows"))] + { + //todo: not implemented. + timezone = |x| x + }; let filepath = unsafe { env.get_unchecked(1) }; //Safety: Checked above println!( @@ -37,9 +49,10 @@ It will be used for this program, to write the current system time to. let dur = time .duration_since(std::time::UNIX_EPOCH) .expect("The clock was set to before 1970-01-01 00:00:00. Please set your clock."); - let seconds = dur.as_secs() % 60; - let minutes = dur.as_secs() / 60 % 60; - let hours = dur.as_secs() / 60 / 60 % 24; + let local = timezone(dur); //Convert to Local time, if possible. + let seconds = local.as_secs() % 60; + let minutes = local.as_secs() / 60 % 60; + let hours = local.as_secs() / 60 / 60 % 24; let time = format!("{:02}:{:02}:{:02}", hours, minutes, seconds); let r = test.seek(SeekFrom::Start(0)); if r.is_err() { @@ -62,19 +75,23 @@ It will be used for this program, to write the current system time to. } } times += 1; - let dur_no_sec = dur - Duration::from_secs(dur.as_secs()); - if (dur_no_sec + s.elapsed()).as_millis() > 100 && times > 10 { + let dur_subsec_millis = local.subsec_millis(); + if dur_subsec_millis as u128 + s.elapsed().as_millis() > 100 && times > 10 { panic!( "Something went wrong. We wrote {}ms after the second changed.", - (dur_no_sec + s.elapsed()).as_millis() + dur_subsec_millis as u128 + s.elapsed().as_millis() ); } println!( "{}ms slow, processing & writing took {}ns", - dur_no_sec.as_millis(), + dur_subsec_millis, s.elapsed().as_nanos() ); - sleep(Duration::from_millis(1000) - dur_no_sec - s.elapsed()); + sleep( + Duration::from_millis(1000) + - Duration::from_millis(dur_subsec_millis as u64) + - s.elapsed(), + ); } } @@ -84,4 +101,4 @@ fn pause() { let mut str = "".to_string(); clin.read_line(&mut str).unwrap(); println!("Resuming."); -} \ No newline at end of file +} diff --git a/src/windows.rs b/src/windows.rs new file mode 100644 index 0000000..7475652 --- /dev/null +++ b/src/windows.rs @@ -0,0 +1,46 @@ +#![cfg(target_family = "windows")] + +use std::ffi::{OsStr, OsString}; +use std::ops::{Add, Sub}; +use std::os::windows::ffi::OsStringExt; +use std::time::Duration; +use winapi::um::errhandlingapi::GetLastError; +use winapi::um::timezoneapi::{ + GetDynamicTimeZoneInformation, DYNAMIC_TIME_ZONE_INFORMATION, PDYNAMIC_TIME_ZONE_INFORMATION, + TIME_ZONE_ID_INVALID, +}; + +pub fn get_convert_utc_to_local() -> impl Fn(Duration) -> Duration { + let mut total_bias; + //Get Bias + { + let mut info = DYNAMIC_TIME_ZONE_INFORMATION::default(); + let r = + unsafe { GetDynamicTimeZoneInformation(&mut info as PDYNAMIC_TIME_ZONE_INFORMATION) }; + if r == TIME_ZONE_ID_INVALID { + eprintln!("Error Occurred whilst getting information on UTC to timezone conversion information.\n\ + System error code is:{}. For meaning of the code go here: https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes",unsafe{GetLastError()}); + eprintln!("Will continue, but the time will now be in UTC instead of the local time."); + info = DYNAMIC_TIME_ZONE_INFORMATION::default(); + } + + //We should have a bias here in every case, because even if the syscall fails, we reinitialise info. + total_bias = info.Bias; + match r { + 1 => total_bias += info.StandardBias, //No DST + 2 => total_bias += info.DaylightBias, //DST + _ => {} + } + } + //Make a fn, to apply bias + let op = if total_bias < 0 { + total_bias *= -1; + Duration::add + } else { + Duration::sub + }; + let total_bias = total_bias as u64; + //we now know, that total_bias>=0. So we can create a Duration. + let correction = Duration::from_secs(total_bias * 60); + move |x| op(x, correction) +}