4 * Conversion between Windows NT timestamps and UNIX timestamps.
8 * Copyright (C) 2012, 2013, 2014 Eric Biggers
10 * This file is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU Lesser General Public License as published by the Free
12 * Software Foundation; either version 3 of the License, or (at your option) any
15 * This file is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this file; if not, see http://www.gnu.org/licenses/.
28 #include "wimlib/timestamp.h"
31 * Timestamps in WIM files are Windows NT timestamps, or FILETIMEs: 64-bit
32 * values storing the number of 100-nanosecond ticks since January 1, 1601.
35 #define NANOSECONDS_PER_TICK 100
36 #define TICKS_PER_SECOND (1000000000 / NANOSECONDS_PER_TICK)
37 #define TICKS_PER_MICROSECOND (TICKS_PER_SECOND / 1000000)
40 * EPOCH_DISTANCE is the number of 100-nanosecond ticks separating the
41 * Windows NT and UNIX epochs. This is equal to ((1970-1601)*365+89)*
42 * 24*60*60*10000000. 89 is the number of leap years between 1970 and 1601.
44 #define EPOCH_DISTANCE 116444736000000000
46 #define TO_WINNT_EPOCH(timestamp) ((timestamp) + EPOCH_DISTANCE)
47 #define TO_UNIX_EPOCH(timestamp) ((timestamp) - EPOCH_DISTANCE)
49 /* Windows NT timestamps to UNIX timestamps */
52 wim_timestamp_to_time_t(u64 timestamp)
54 timestamp = TO_UNIX_EPOCH(timestamp);
56 return timestamp / TICKS_PER_SECOND;
60 wim_timestamp_to_timeval(u64 timestamp)
62 timestamp = TO_UNIX_EPOCH(timestamp);
64 return (struct timeval) {
65 .tv_sec = timestamp / TICKS_PER_SECOND,
66 .tv_usec = (timestamp % TICKS_PER_SECOND) / TICKS_PER_MICROSECOND,
71 wim_timestamp_to_timespec(u64 timestamp)
73 timestamp = TO_UNIX_EPOCH(timestamp);
75 return (struct timespec) {
76 .tv_sec = timestamp / TICKS_PER_SECOND,
77 .tv_nsec = (timestamp % TICKS_PER_SECOND) * NANOSECONDS_PER_TICK,
81 /* UNIX timestamps to Windows NT timestamps */
84 time_t_to_wim_timestamp(time_t t)
86 u64 timestamp = (u64)t * TICKS_PER_SECOND;
88 return TO_WINNT_EPOCH(timestamp);
92 timeval_to_wim_timestamp(const struct timeval *tv)
94 u64 timestamp = (u64)tv->tv_sec * TICKS_PER_SECOND +
95 (u64)tv->tv_usec * TICKS_PER_MICROSECOND;
97 return TO_WINNT_EPOCH(timestamp);
101 timespec_to_wim_timestamp(const struct timespec *ts)
103 u64 timestamp = (u64)ts->tv_sec * TICKS_PER_SECOND +
104 (u64)ts->tv_nsec / NANOSECONDS_PER_TICK;
106 return TO_WINNT_EPOCH(timestamp);
109 /* Retrieve the current time as a WIM timestamp. */
111 now_as_wim_timestamp(void)
115 /* On Windows we rely on MinGW providing gettimeofday() for us. This
116 * could be changed to calling GetSystemTimeAsFileTime() directly, but
117 * now_as_wim_timestamp() isn't called much and it's simpler to keep the
118 * code for all platforms the same. */
119 gettimeofday(&tv, NULL);
120 return timeval_to_wim_timestamp(&tv);
123 /* Translate a WIM timestamp into a human-readable string. */
125 wim_timestamp_to_str(u64 timestamp, tchar *buf, size_t len)
128 time_t t = wim_timestamp_to_time_t(timestamp);
130 tstrftime(buf, len, T("%a %b %d %H:%M:%S %Y UTC"), &tm);