1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.compress.utils;
18
19 import static org.apache.commons.compress.utils.TimeUtils.HUNDRED_NANOS_PER_MILLISECOND;
20 import static org.apache.commons.compress.utils.TimeUtils.WINDOWS_EPOCH_OFFSET;
21 import static org.apache.commons.compress.utils.TimeUtils.ntfsTimeToDate;
22 import static org.apache.commons.compress.utils.TimeUtils.ntfsTimeToFileTime;
23 import static org.apache.commons.compress.utils.TimeUtils.toDate;
24 import static org.apache.commons.compress.utils.TimeUtils.toFileTime;
25 import static org.apache.commons.compress.utils.TimeUtils.toNtfsTime;
26 import static org.junit.jupiter.api.Assertions.assertEquals;
27 import static org.junit.jupiter.api.Assertions.assertFalse;
28 import static org.junit.jupiter.api.Assertions.assertNull;
29 import static org.junit.jupiter.api.Assertions.assertTrue;
30
31 import java.nio.file.attribute.FileTime;
32 import java.time.Instant;
33 import java.util.Date;
34 import java.util.stream.Stream;
35
36 import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
37 import org.junit.jupiter.api.Test;
38 import org.junit.jupiter.params.ParameterizedTest;
39 import org.junit.jupiter.params.provider.Arguments;
40 import org.junit.jupiter.params.provider.MethodSource;
41
42 public class TimeUtilsTest {
43
44 public static Stream<Arguments> dateToNtfsProvider() {
45 return Stream.of(Arguments.of("1601-01-01T00:00:00.000Z", 0), Arguments.of("1601-01-01T00:00:00.000Z", 1), Arguments.of("1600-12-31T23:59:59.999Z", -1),
46 Arguments.of("1601-01-01T00:00:00.001Z", HUNDRED_NANOS_PER_MILLISECOND),
47 Arguments.of("1601-01-01T00:00:00.001Z", HUNDRED_NANOS_PER_MILLISECOND + 1),
48 Arguments.of("1601-01-01T00:00:00.000Z", HUNDRED_NANOS_PER_MILLISECOND - 1),
49 Arguments.of("1600-12-31T23:59:59.999Z", -HUNDRED_NANOS_PER_MILLISECOND),
50 Arguments.of("1600-12-31T23:59:59.999Z", -HUNDRED_NANOS_PER_MILLISECOND + 1),
51 Arguments.of("1600-12-31T23:59:59.998Z", -HUNDRED_NANOS_PER_MILLISECOND - 1), Arguments.of("1970-01-01T00:00:00.000Z", -WINDOWS_EPOCH_OFFSET),
52 Arguments.of("1970-01-01T00:00:00.000Z", -WINDOWS_EPOCH_OFFSET + 1),
53 Arguments.of("1970-01-01T00:00:00.001Z", -WINDOWS_EPOCH_OFFSET + HUNDRED_NANOS_PER_MILLISECOND),
54 Arguments.of("1969-12-31T23:59:59.999Z", -WINDOWS_EPOCH_OFFSET - 1),
55 Arguments.of("1969-12-31T23:59:59.999Z", -WINDOWS_EPOCH_OFFSET - HUNDRED_NANOS_PER_MILLISECOND));
56 }
57
58 public static Stream<Arguments> fileTimeToNtfsProvider() {
59 return Stream.of(Arguments.of("1601-01-01T00:00:00.0000000Z", 0), Arguments.of("1601-01-01T00:00:00.0000001Z", 1),
60 Arguments.of("1600-12-31T23:59:59.9999999Z", -1), Arguments.of("1601-01-01T00:00:00.0010000Z", HUNDRED_NANOS_PER_MILLISECOND),
61 Arguments.of("1601-01-01T00:00:00.0010001Z", HUNDRED_NANOS_PER_MILLISECOND + 1),
62 Arguments.of("1601-01-01T00:00:00.0009999Z", HUNDRED_NANOS_PER_MILLISECOND - 1),
63 Arguments.of("1600-12-31T23:59:59.9990000Z", -HUNDRED_NANOS_PER_MILLISECOND),
64 Arguments.of("1600-12-31T23:59:59.9990001Z", -HUNDRED_NANOS_PER_MILLISECOND + 1),
65 Arguments.of("1600-12-31T23:59:59.9989999Z", -HUNDRED_NANOS_PER_MILLISECOND - 1),
66 Arguments.of("1970-01-01T00:00:00.0000000Z", -WINDOWS_EPOCH_OFFSET), Arguments.of("1970-01-01T00:00:00.0000001Z", -WINDOWS_EPOCH_OFFSET + 1),
67 Arguments.of("1970-01-01T00:00:00.0010000Z", -WINDOWS_EPOCH_OFFSET + HUNDRED_NANOS_PER_MILLISECOND),
68 Arguments.of("1969-12-31T23:59:59.9999999Z", -WINDOWS_EPOCH_OFFSET - 1),
69 Arguments.of("1969-12-31T23:59:59.9990000Z", -WINDOWS_EPOCH_OFFSET - HUNDRED_NANOS_PER_MILLISECOND));
70 }
71
72 public static Stream<Arguments> fileTimeToUnixTimeArguments() {
73 return Stream.of(Arguments.of(0L, "1970-01-01T00:00:00Z"), Arguments.of(1672141989L, "2022-12-27T11:53:09Z"),
74 Arguments.of(Integer.MAX_VALUE, "2038-01-19T03:14:07Z"));
75 }
76
77 public static Stream<Arguments> truncateFileTimeProvider() {
78 return Stream.of(Arguments.of("2022-05-10T18:25:33.123456789Z", "2022-05-10T18:25:33.1234567Z"),
79 Arguments.of("1970-01-01T00:00:00.000000001Z", "1970-01-01T00:00:00.0000000Z"),
80 Arguments.of("1970-01-01T00:00:00.000000010Z", "1970-01-01T00:00:00.0000000Z"),
81 Arguments.of("1970-01-01T00:00:00.000000199Z", "1970-01-01T00:00:00.0000001Z"),
82 Arguments.of("1969-12-31T23:59:59.999999999Z", "1969-12-31T23:59:59.9999999Z"),
83 Arguments.of("1969-12-31T23:59:59.000000001Z", "1969-12-31T23:59:59.0000000Z"),
84 Arguments.of("1969-12-31T23:59:59.000000010Z", "1969-12-31T23:59:59.0000000Z"),
85 Arguments.of("1969-12-31T23:59:59.000000199Z", "1969-12-31T23:59:59.0000001Z"));
86 }
87
88 @Test
89 public void testIsUnixTime() {
90 assertTrue(TimeUtils.isUnixTime(null));
91 assertTrue(TimeUtils.isUnixTime(FileTime.from(Instant.parse("2022-12-27T12:45:22Z"))));
92 assertTrue(TimeUtils.isUnixTime(FileTime.from(Instant.parse("2038-01-19T03:14:07Z"))));
93 assertTrue(TimeUtils.isUnixTime(FileTime.from(Instant.parse("1901-12-13T23:14:08Z"))));
94 assertFalse(TimeUtils.isUnixTime(FileTime.from(Instant.parse("1901-12-13T03:14:08Z"))));
95 assertFalse(TimeUtils.isUnixTime(FileTime.from(Instant.parse("2038-01-19T03:14:08Z"))));
96 assertFalse(TimeUtils.isUnixTime(FileTime.from(Instant.parse("2099-06-30T12:31:42Z"))));
97 }
98
99 @ParameterizedTest
100 @MethodSource("dateToNtfsProvider")
101 public void testJavaTimeToNtfsTime(final String instant, final long ntfsTime) {
102 final long ntfsMillis = Math.floorDiv(ntfsTime, HUNDRED_NANOS_PER_MILLISECOND) * HUNDRED_NANOS_PER_MILLISECOND;
103 final Date parsed = Date.from(Instant.parse(instant));
104 final long converted = toNtfsTime(parsed);
105 assertEquals(ntfsMillis, converted);
106
107 assertEquals(converted, SevenZArchiveEntry.javaTimeToNtfsTime(parsed));
108 }
109
110 @ParameterizedTest
111 @MethodSource("fileTimeToNtfsProvider")
112 public void testNtfsTimeToFileTime(final String instant, final long ntfsTime) {
113 final FileTime parsed = FileTime.from(Instant.parse(instant));
114 assertEquals(parsed, ntfsTimeToFileTime(ntfsTime));
115 }
116
117 @ParameterizedTest
118 @MethodSource("dateToNtfsProvider")
119 public void testNtfsTimeToJavaTime(final String instant, final long ntfsTime) {
120 final Date converted = ntfsTimeToDate(ntfsTime);
121 assertEquals(Instant.parse(instant), converted.toInstant());
122
123 assertEquals(converted, SevenZArchiveEntry.ntfsTimeToJavaTime(ntfsTime));
124 }
125
126 @ParameterizedTest
127 @MethodSource("fileTimeToNtfsProvider")
128 public void testToDate(final String instant, final long ignored) {
129 final Instant parsedInstant = Instant.parse(instant);
130 final FileTime parsedFileTime = FileTime.from(parsedInstant);
131 final Date parsedDate = Date.from(parsedInstant);
132 assertEquals(parsedDate, toDate(parsedFileTime));
133 }
134
135 @Test
136 public void testToDateNull() {
137 assertNull(toDate(null));
138 }
139
140 @ParameterizedTest
141 @MethodSource("dateToNtfsProvider")
142 public void testToFileTime(final String instant, final long ignored) {
143 final Instant parsedInstant = Instant.parse(instant);
144 final FileTime parsedFileTime = FileTime.from(parsedInstant);
145 final Date parsedDate = Date.from(parsedInstant);
146 assertEquals(parsedFileTime, toFileTime(parsedDate));
147 }
148
149 @Test
150 public void testToFileTimeNull() {
151 assertNull(toFileTime(null));
152 }
153
154 @ParameterizedTest
155 @MethodSource("fileTimeToNtfsProvider")
156 public void testToNtfsTime(final String instant, final long ntfsTime) {
157 final FileTime parsed = FileTime.from(Instant.parse(instant));
158 assertEquals(ntfsTime, toNtfsTime(parsed));
159 }
160
161 @ParameterizedTest
162 @MethodSource("fileTimeToUnixTimeArguments")
163 public void testToUnixTime(final long expectedUnixTime, final String instant) {
164 assertEquals(expectedUnixTime, TimeUtils.toUnixTime(FileTime.from(Instant.parse(instant))));
165 }
166
167 @ParameterizedTest
168 @MethodSource("truncateFileTimeProvider")
169 public void testTruncateToHundredNanos(final String original, final String truncated) {
170 final FileTime originalTime = FileTime.from(Instant.parse(original));
171 final FileTime truncatedTime = FileTime.from(Instant.parse(truncated));
172 assertEquals(truncatedTime, TimeUtils.truncateToHundredNanos(originalTime));
173 }
174
175 @ParameterizedTest
176 @MethodSource("fileTimeToUnixTimeArguments")
177 public void testUnixTimeToFileTime(final long unixTime, final String expectedInstant) {
178 assertEquals(Instant.parse(expectedInstant), TimeUtils.unixTimeToFileTime(unixTime).toInstant());
179 }
180 }