Skip to content

Commit

Permalink
Add conversion from utc to local time in windows
Browse files Browse the repository at this point in the history
  • Loading branch information
C0D3-M4513R committed Apr 4, 2022
1 parent 6f1533d commit 3efc18b
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 16 deletions.
27 changes: 26 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
[package]
name = "time"
version = "0.1.0"
edition = "2021"
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"]
2 changes: 0 additions & 2 deletions src/macros.rs

This file was deleted.

39 changes: 28 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -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<T> = std::result::Result<T, std::io::Error>;
#[cfg(target_family = "windows")]
mod windows;

fn main() -> Result<()> {
let env: Vec<String> = std::env::args().collect();
Expand All @@ -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!(
Expand All @@ -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() {
Expand All @@ -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(),
);
}
}

Expand All @@ -84,4 +101,4 @@ fn pause() {
let mut str = "".to_string();
clin.read_line(&mut str).unwrap();
println!("Resuming.");
}
}
46 changes: 46 additions & 0 deletions src/windows.rs
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit 3efc18b

Please sign in to comment.