1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.io.file.attribute;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertNull;
22 import static org.junit.jupiter.api.Assertions.assertTrue;
23
24 import java.nio.file.attribute.FileTime;
25 import java.time.Instant;
26 import java.util.Date;
27 import java.util.concurrent.TimeUnit;
28 import java.util.stream.Stream;
29
30 import org.junit.jupiter.api.Test;
31 import org.junit.jupiter.params.ParameterizedTest;
32 import org.junit.jupiter.params.provider.Arguments;
33 import org.junit.jupiter.params.provider.MethodSource;
34
35
36
37
38 class FileTimesTest {
39
40 public static Stream<Arguments> fileTimeNanoUnitsToNtfsProvider() {
41
42 return Stream.of(
43 Arguments.of("1601-01-01T00:00:00.0000000Z", 0),
44 Arguments.of("1601-01-01T00:00:00.0000001Z", 1),
45 Arguments.of("1601-01-01T00:00:00.0000010Z", 10),
46 Arguments.of("1601-01-01T00:00:00.0000100Z", 100),
47 Arguments.of("1601-01-01T00:00:00.0001000Z", 1000),
48 Arguments.of("1600-12-31T23:59:59.9999999Z", -1),
49 Arguments.of("+30828-09-14T02:48:05.477580700Z", Long.MAX_VALUE),
50 Arguments.of("+30828-09-14T02:48:05.477580600Z", Long.MAX_VALUE - 1),
51 Arguments.of("+30828-09-14T02:48:05.477579700Z", Long.MAX_VALUE - 10),
52 Arguments.of("+30828-09-14T02:48:05.477570700Z", Long.MAX_VALUE - 100),
53 Arguments.of("+30828-09-14T02:48:05.477480700Z", Long.MAX_VALUE - 1000),
54 Arguments.of("-27627-04-19T21:11:54.522419200Z", Long.MIN_VALUE),
55 Arguments.of("-27627-04-19T21:11:54.522419300Z", Long.MIN_VALUE + 1),
56 Arguments.of("-27627-04-19T21:11:54.522420200Z", Long.MIN_VALUE + 10),
57 Arguments.of("-27627-04-19T21:11:54.522429200Z", Long.MIN_VALUE + 100),
58 Arguments.of("-27627-04-19T21:11:54.522519200Z", Long.MIN_VALUE + 1000),
59 Arguments.of("1601-01-01T00:00:00.0010000Z", FileTimes.HUNDRED_NANOS_PER_MILLISECOND),
60 Arguments.of("1601-01-01T00:00:00.0010001Z", FileTimes.HUNDRED_NANOS_PER_MILLISECOND + 1),
61 Arguments.of("1601-01-01T00:00:00.0009999Z", FileTimes.HUNDRED_NANOS_PER_MILLISECOND - 1),
62 Arguments.of("1600-12-31T23:59:59.9990000Z", -FileTimes.HUNDRED_NANOS_PER_MILLISECOND),
63 Arguments.of("1600-12-31T23:59:59.9990001Z", -FileTimes.HUNDRED_NANOS_PER_MILLISECOND + 1),
64 Arguments.of("1600-12-31T23:59:59.9989999Z", -FileTimes.HUNDRED_NANOS_PER_MILLISECOND - 1),
65 Arguments.of("1970-01-01T00:00:00.0000000Z", -FileTimes.UNIX_TO_NTFS_OFFSET),
66 Arguments.of("1970-01-01T00:00:00.0000001Z", -FileTimes.UNIX_TO_NTFS_OFFSET + 1),
67 Arguments.of("1970-01-01T00:00:00.0010000Z", -FileTimes.UNIX_TO_NTFS_OFFSET + FileTimes.HUNDRED_NANOS_PER_MILLISECOND),
68 Arguments.of("1969-12-31T23:59:59.9999999Z", -FileTimes.UNIX_TO_NTFS_OFFSET - 1),
69 Arguments.of("1969-12-31T23:59:59.9990000Z", -FileTimes.UNIX_TO_NTFS_OFFSET - FileTimes.HUNDRED_NANOS_PER_MILLISECOND));
70
71 }
72
73 public static Stream<Arguments> fileTimeToNtfsProvider() {
74
75 return Stream.of(
76 Arguments.of("1970-01-01T00:00:00Z", FileTime.from(Instant.EPOCH)),
77 Arguments.of("1969-12-31T23:59:00Z", FileTime.from(Instant.EPOCH.minusSeconds(60))),
78 Arguments.of("1970-01-01T00:01:00Z", FileTime.from(Instant.EPOCH.plusSeconds(60))));
79
80 }
81
82 public static Stream<Arguments> isUnixFileTimeProvider() {
83
84 return Stream.of(
85 Arguments.of("2022-12-27T12:45:22Z", true),
86 Arguments.of("2038-01-19T03:14:07Z", true),
87 Arguments.of("1901-12-13T23:14:08Z", true),
88 Arguments.of("1901-12-13T03:14:08Z", false),
89 Arguments.of("2038-01-19T03:14:08Z", false),
90 Arguments.of("2099-06-30T12:31:42Z", false));
91
92 }
93
94 @ParameterizedTest
95 @MethodSource("fileTimeNanoUnitsToNtfsProvider")
96 void testDateToFileTime(final String instant, final long ignored) {
97 final Instant parsedInstant = Instant.parse(instant);
98 final FileTime parsedFileTime = FileTime.from(parsedInstant);
99 final Date parsedDate = Date.from(parsedInstant);
100 assertEquals(parsedFileTime.toMillis(), FileTimes.toFileTime(parsedDate).toMillis());
101 }
102
103 @ParameterizedTest
104 @MethodSource("fileTimeNanoUnitsToNtfsProvider")
105 void testDateToNtfsTime(final String instantStr, final long ntfsTime) {
106 final long ntfsMillis = Math.floorDiv(ntfsTime, FileTimes.HUNDRED_NANOS_PER_MILLISECOND) * FileTimes.HUNDRED_NANOS_PER_MILLISECOND;
107 final Instant instant = Instant.parse(instantStr);
108 final Date parsed = Date.from(instant);
109 final long ntfsTime2 = FileTimes.toNtfsTime(parsed);
110 if (ntfsTime2 == Long.MIN_VALUE || ntfsTime2 == Long.MAX_VALUE) {
111
112 } else {
113 assertEquals(ntfsMillis, ntfsTime2);
114 assertEquals(ntfsMillis, FileTimes.toNtfsTime(parsed.getTime()));
115 assertEquals(ntfsMillis, FileTimes.toNtfsTime(FileTimes.ntfsTimeToInstant(ntfsTime).toEpochMilli()));
116 }
117 assertEquals(ntfsTime, FileTimes.toNtfsTime(FileTimes.ntfsTimeToInstant(ntfsTime)));
118 }
119
120 @Test
121 void testEpoch() {
122 assertEquals(0, FileTimes.EPOCH.toMillis());
123 }
124
125 @ParameterizedTest
126 @MethodSource("fileTimeNanoUnitsToNtfsProvider")
127 void testFileTimeToDate(final String instant, final long ignored) {
128 final Instant parsedInstant = Instant.parse(instant);
129 final FileTime parsedFileTime = FileTime.from(parsedInstant);
130 final Date parsedDate = Date.from(parsedInstant);
131 assertEquals(parsedDate, FileTimes.toDate(parsedFileTime));
132 }
133
134
135 @ParameterizedTest
136 @MethodSource("fileTimeToNtfsProvider")
137 void testFileTimeToNtfsTime(final String instantStr, final FileTime fileTime) {
138 final Instant instant = Instant.parse(instantStr);
139 final FileTime parsed = FileTime.from(instant);
140 assertEquals(instant, parsed.toInstant());
141 assertEquals(fileTime, FileTimes.ntfsTimeToFileTime(FileTimes.toNtfsTime(parsed)));
142 }
143
144 @ParameterizedTest
145 @MethodSource("fileTimeNanoUnitsToNtfsProvider")
146 void testFileTimeToNtfsTime(final String instant, final long ntfsTime) {
147 final FileTime parsed = FileTime.from(Instant.parse(instant));
148 assertEquals(ntfsTime, FileTimes.toNtfsTime(parsed));
149 }
150
151 @ParameterizedTest
152 @MethodSource("fileTimeNanoUnitsToNtfsProvider")
153 void testFromUnixTime(final String instant, final long ntfsTime) {
154 final long epochSecond = Instant.parse(instant).getEpochSecond();
155 assertEquals(epochSecond, FileTimes.fromUnixTime(epochSecond).to(TimeUnit.SECONDS));
156 }
157
158 @ParameterizedTest
159 @MethodSource("isUnixFileTimeProvider")
160 void testIsUnixTime(final String instant, final boolean isUnixTime) {
161 assertEquals(isUnixTime, FileTimes.isUnixTime(FileTime.from(Instant.parse(instant))));
162 }
163
164 void testIsUnixTimeFileTimeNull() {
165 assertTrue(FileTimes.isUnixTime(null));
166 }
167
168 @ParameterizedTest
169 @MethodSource("isUnixFileTimeProvider")
170 void testIsUnixTimeLong(final String instant, final boolean isUnixTime) {
171 assertEquals(isUnixTime, FileTimes.isUnixTime(Instant.parse(instant).getEpochSecond()));
172 }
173
174 @Test
175 void testMaxJavaTime() {
176 final long javaTime = Long.MAX_VALUE;
177 final Instant instant = Instant.ofEpochMilli(javaTime);
178 assertEquals(javaTime, instant.toEpochMilli());
179 final long ntfsTime = FileTimes.toNtfsTime(javaTime);
180 final Instant instant2 = FileTimes.ntfsTimeToInstant(ntfsTime);
181 if (ntfsTime == Long.MAX_VALUE) {
182
183 } else {
184 assertEquals(javaTime, instant2.toEpochMilli());
185 }
186 }
187
188 @ParameterizedTest
189 @MethodSource("fileTimeNanoUnitsToNtfsProvider")
190 void testMaxJavaTimeParam(final String instantStr, final long javaTime) {
191
192 final Instant instant = Instant.ofEpochMilli(javaTime);
193 assertEquals(javaTime, instant.toEpochMilli());
194 final long ntfsTime = FileTimes.toNtfsTime(javaTime);
195 final Instant instant2 = FileTimes.ntfsTimeToInstant(ntfsTime);
196 if (ntfsTime == Long.MIN_VALUE || ntfsTime == Long.MAX_VALUE) {
197
198 } else {
199 assertEquals(javaTime, instant2.toEpochMilli());
200 }
201 }
202
203 @Test
204 void testMinusMillis() {
205 final int millis = 2;
206 assertEquals(Instant.EPOCH.minusMillis(millis), FileTimes.minusMillis(FileTimes.EPOCH, millis).toInstant());
207 assertEquals(Instant.EPOCH, FileTimes.minusMillis(FileTimes.EPOCH, 0).toInstant());
208 }
209
210 @Test
211 void testMinusNanos() {
212 final int millis = 2;
213 assertEquals(Instant.EPOCH.minusNanos(millis), FileTimes.minusNanos(FileTimes.EPOCH, millis).toInstant());
214 assertEquals(Instant.EPOCH, FileTimes.minusNanos(FileTimes.EPOCH, 0).toInstant());
215 }
216
217 @Test
218 void testMinusSeconds() {
219 final int seconds = 2;
220 assertEquals(Instant.EPOCH.minusSeconds(seconds), FileTimes.minusSeconds(FileTimes.EPOCH, seconds).toInstant());
221 assertEquals(Instant.EPOCH, FileTimes.minusSeconds(FileTimes.EPOCH, 0).toInstant());
222 }
223
224 @ParameterizedTest
225 @MethodSource("fileTimeNanoUnitsToNtfsProvider")
226 void testNtfsTimeToDate(final String instant, final long ntfsTime) {
227 assertEquals(Instant.parse(instant).toEpochMilli(), FileTimes.ntfsTimeToDate(ntfsTime).toInstant().toEpochMilli());
228 }
229
230 @ParameterizedTest
231 @MethodSource("fileTimeNanoUnitsToNtfsProvider")
232 void testNtfsTimeToFileTime(final String instantStr, final long ntfsTime) {
233 final Instant instant = Instant.parse(instantStr);
234 final FileTime fileTime = FileTime.from(instant);
235 assertEquals(instant, fileTime.toInstant());
236 assertEquals(instant, FileTimes.ntfsTimeToInstant(ntfsTime));
237 assertEquals(fileTime, FileTimes.ntfsTimeToFileTime(ntfsTime));
238 }
239
240 @Test
241 void testNullDateToNullFileTime() {
242 assertNull(FileTimes.toFileTime(null));
243 }
244
245 @Test
246 void testNullFileTimeToNullDate() {
247 assertNull(FileTimes.toDate(null));
248 }
249
250 @Test
251 void testPlusMinusMillis() {
252 final int millis = 2;
253 assertEquals(Instant.EPOCH.plusMillis(millis), FileTimes.plusMillis(FileTimes.EPOCH, millis).toInstant());
254 assertEquals(Instant.EPOCH, FileTimes.plusMillis(FileTimes.EPOCH, 0).toInstant());
255 }
256
257 @Test
258 void testPlusNanos() {
259 final int millis = 2;
260 assertEquals(Instant.EPOCH.plusNanos(millis), FileTimes.plusNanos(FileTimes.EPOCH, millis).toInstant());
261 assertEquals(Instant.EPOCH, FileTimes.plusNanos(FileTimes.EPOCH, 0).toInstant());
262 }
263
264 @Test
265 void testPlusSeconds() {
266 final int seconds = 2;
267 assertEquals(Instant.EPOCH.plusSeconds(seconds), FileTimes.plusSeconds(FileTimes.EPOCH, seconds).toInstant());
268 assertEquals(Instant.EPOCH, FileTimes.plusSeconds(FileTimes.EPOCH, 0).toInstant());
269 }
270
271 @ParameterizedTest
272 @MethodSource("isUnixFileTimeProvider")
273 void testToUnixTime(final String instant, final boolean isUnixTime) {
274 assertEquals(isUnixTime, FileTimes.isUnixTime(FileTimes.toUnixTime(FileTime.from(Instant.parse(instant)))));
275 }
276 }