win32_filetime_utils 0.2.1

Conversion utils from, and to Windows's FILETIME, SYSTEMTIME, etc ...
//! Conversion utils for Windows' FILETIME, SYSTEMTIME types

#![allow(dead_code)]
use self::chrono::NaiveTime;
use self::chrono::naive::date::NaiveDate;
use self::chrono::naive::datetime::NaiveDateTime;
use self::native::*;

pub use self::constants::*;
// pub use self::native::*;

// Created to prevent polluting this and user's namespace
//
pub mod chrono
{
	extern crate chrono;
	pub use self::chrono::*;
}


#[allow(dead_code)]
mod constants
{
	pub const TICKS_PER_MILISECOND: i64 = 10_000;
	pub const TICKS_PER_SECOND: i64 = TICKS_PER_MILISECOND * 1_000;
	pub const TICKS_PER_MINUTE: i64 = TICKS_PER_SECOND * 60;
	pub const TICKS_PER_HOUR: i64 = TICKS_PER_MINUTE * 60;
}

#[allow(non_snake_case)]
#[allow(dead_code)]
pub mod native
{
	#[derive(Debug)]
	#[repr(C)]
	pub struct SYSTEMTIME
	{
	    pub wYear: u16,
	    pub wMonth: u16,
	    pub wDayOfWeek: u16,
	    pub wDay: u16,
	    pub wHour: u16,
	    pub wMinute: u16,
	    pub wSecond: u16,
	    pub wMilliseconds: u16
	}

	impl Default for SYSTEMTIME
	{
	    fn default() -> Self
	    {
	        SYSTEMTIME
	        {
	            wYear: 0, wMonth: 0, wDayOfWeek: 0, wDay: 0
	            , wHour: 0, wMinute: 0
	            , wSecond: 0, wMilliseconds: 0
	        }
	    }
	}

	#[derive(Debug, Clone, Copy)]
	#[repr(C)]
	pub struct FILETIME
	{
		pub dwLowDateTime: u32,
  		pub dwHighDateTime: u32
	}

	impl Default for FILETIME
	{
		fn default() -> Self
		{
			FILETIME
			{
				dwLowDateTime: 0, dwHighDateTime: 0
			}
		}
	}

	#[link(name = "kernel32")]
	extern "system"
	{
	    pub fn FileTimeToSystemTime(
	        lpFileTime: *const i64, lpSystemTime: *mut SYSTEMTIME
	    ) -> i32;

	    pub fn FileTimeToLocalFileTime(
	        lpFileTime: *const i64, lpLocalFileTime: *mut i64
	    ) -> i32;

	}
}


/// Converts FILETIME to ticks
pub fn filetime_to_ticks(f: FILETIME) -> i64
{
	// Expand to 64bit
	//
	let low = f.dwLowDateTime as i64;
	let high = f.dwHighDateTime as i64;

	(high << 32) + low
}


/// Converts ticks to FILETIME
pub fn ticks_to_filetime(ticks: i64) -> FILETIME
{
	let high = ticks >> 32;
	let low = ticks & 0xffffffff;
	FILETIME { dwLowDateTime: low as u32, dwHighDateTime: high as u32}
}


/// Converts ticks to NaiveTime
///
/// # Examples
///
/// ```
/// let naive_time = ticks_to_naive_time(2101715244);
/// println!(naive_time);
/// ```
pub fn ticks_to_naive_time(ticks: i64) -> NaiveTime
{
    let milli = (ticks / TICKS_PER_MILISECOND) % 1000;
    let seconds = (ticks / TICKS_PER_SECOND) % 60;
    let minutes = (ticks / TICKS_PER_MINUTE) % 60;
    let hours = (ticks / TICKS_PER_HOUR) % 24;
    let naive_time = NaiveTime::from_hms_milli(
        hours as u32
        , minutes as u32
        , seconds as u32
        , milli as u32);
    naive_time
}


/// Converts native FILETIME to NaiveTime
///
/// # Examples
///
/// ```
/// let filetime = FILETIME { dwLowDateTime: 3818346658, dwHighDateTime: 2 };
/// println!(filetime);
/// ```
pub fn filetime_to_naive_time(filetime: FILETIME) -> NaiveTime
{
	let ticks = filetime_to_ticks(filetime);
	ticks_to_naive_time(ticks)
}

/// Converts SYSTEMTIME to chrono's NaiveDateTime
pub fn systemtime_to_naive_date_time(nat_sys_time: &SYSTEMTIME) -> NaiveDateTime
{
    let naive_date = NaiveDate::from_ymd(
        nat_sys_time.wYear as i32, nat_sys_time.wMonth as u32, nat_sys_time.wDay as u32);
    let naive_time = NaiveTime::from_hms(
        nat_sys_time.wHour as u32, nat_sys_time.wMinute as u32, nat_sys_time.wSecond as u32);
    let naive_date_time = NaiveDateTime::new(naive_date, naive_time);
    naive_date_time
}


/// Converts ticks to local time SYSTEMTIME
#[allow(unused_variables)]
pub fn ticks_to_local_systemtime(filetime: i64) -> SYSTEMTIME
{
    let ref mut filetime = filetime.clone();
    let mut nat_sys_time = SYSTEMTIME::default();
    let r = unsafe { FileTimeToLocalFileTime(filetime as *const i64, filetime as *mut i64) };
    unsafe { FileTimeToSystemTime(filetime as *const i64, &mut nat_sys_time as *mut SYSTEMTIME) };
    nat_sys_time
}


/// Converts native FILETIME to local time SYSTEMTIME
pub fn filetime_to_local_systemtime(filetime: FILETIME) -> SYSTEMTIME
{
	let ticks = filetime_to_ticks(filetime);
	ticks_to_local_systemtime(ticks)
}


#[cfg(test)]
#[allow(unused_variables)]
mod test
{
	extern crate chrono;
	use self::chrono::Timelike;
	use super::native::*;
	use super::*;

	fn assert_naive_time(naive_time: &NaiveTime)
	{
		let hours = 20;
		let seconds = 40;
		assert_eq!(hours, naive_time.minute());
		assert_eq!(seconds, naive_time.second());
	}

	#[test]
	fn filetime_to_ticks_test()
	{
		let f = FILETIME { dwLowDateTime: 2101715244, dwHighDateTime: 30457047 };

		let high_ex = f.dwHighDateTime as i64;
		let low_ex = f.dwLowDateTime as i64;

		let ticks = 130812022899450156;
		let candidate = filetime_to_ticks(f);

		assert_eq!(ticks, candidate);
	}

	#[test]
	fn ticks_to_naive_time_test()
	{

		let ticks = 12408281250;
		let naive_time = ticks_to_naive_time(ticks);
		assert_naive_time(&naive_time);
	}

	#[test]
	fn filetime_to_naive_time_test()
	{
		let filetime = FILETIME { dwLowDateTime: 3818346658, dwHighDateTime: 2 };
		let naive_time = filetime_to_naive_time(filetime);
		assert_naive_time(&naive_time);
	}
}