1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
//! 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);
	}
}