View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
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         // ensuring the deprecated method still works
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         // ensuring the deprecated method still works
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 }