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