+/*
+ * Timestamps in WIM files are Windows NT timestamps, or FILETIMEs: 64-bit
+ * values storing the number of 100-nanosecond ticks since January 1, 1601.
+ */
+
+#define NANOSECONDS_PER_TICK 100
+#define TICKS_PER_SECOND (1000000000 / NANOSECONDS_PER_TICK)
+#define TICKS_PER_MICROSECOND (TICKS_PER_SECOND / 1000000)
+
+/*
+ * EPOCH_DISTANCE is the number of 100-nanosecond ticks separating the
+ * Windows NT and UNIX epochs. This is equal to ((1970-1601)*365+89)*
+ * 24*60*60*10000000. 89 is the number of leap years between 1970 and 1601.
+ */
+#define EPOCH_DISTANCE 116444736000000000
+
+#define TO_WINNT_EPOCH(timestamp) ((timestamp) + EPOCH_DISTANCE)
+#define TO_UNIX_EPOCH(timestamp) ((timestamp) - EPOCH_DISTANCE)
+
+/* Windows NT timestamps to UNIX timestamps */
+
+time_t
+wim_timestamp_to_time_t(u64 timestamp)
+{
+ timestamp = TO_UNIX_EPOCH(timestamp);
+
+ return timestamp / TICKS_PER_SECOND;
+}
+
+struct timeval
+wim_timestamp_to_timeval(u64 timestamp)
+{
+ timestamp = TO_UNIX_EPOCH(timestamp);
+
+ return (struct timeval) {
+ .tv_sec = timestamp / TICKS_PER_SECOND,
+ .tv_usec = (timestamp % TICKS_PER_SECOND) / TICKS_PER_MICROSECOND,
+ };
+}
+
+struct timespec
+wim_timestamp_to_timespec(u64 timestamp)
+{
+ timestamp = TO_UNIX_EPOCH(timestamp);
+
+ return (struct timespec) {
+ .tv_sec = timestamp / TICKS_PER_SECOND,
+ .tv_nsec = (timestamp % TICKS_PER_SECOND) * NANOSECONDS_PER_TICK,
+ };
+}
+
+/* UNIX timestamps to Windows NT timestamps */
+
+u64
+time_t_to_wim_timestamp(time_t t)
+{
+ u64 timestamp = (u64)t * TICKS_PER_SECOND;
+
+ return TO_WINNT_EPOCH(timestamp);
+}