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 java.nio.file.attribute.FileTime;
20  import java.time.Instant;
21  import java.util.Date;
22  import java.util.concurrent.TimeUnit;
23  
24  import org.apache.commons.io.file.attribute.FileTimes;
25  
26  /**
27   * Utility class for handling time-related types and conversions.
28   * <p>
29   * Understanding Unix vs NTFS timestamps:
30   * </p>
31   * <ul>
32   * <li>A <a href="https://en.wikipedia.org/wiki/Unix_time">Unix timestamp</a> is a primitive long starting at the Unix Epoch on January 1st, 1970 at Coordinated
33   * Universal Time (UTC)</li>
34   * <li>An <a href="https://learn.microsoft.com/en-us/windows/win32/sysinfo/file-times">NTFS timestamp</a> is a file time is a 64-bit value that represents the
35   * number of 100-nanosecond intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated Universal Time (UTC).</li>
36   * </ul>
37   *
38   * @since 1.23
39   */
40  public final class TimeUtils {
41  
42      /** The amount of 100-nanosecond intervals in one millisecond. */
43      static final long HUNDRED_NANOS_PER_MILLISECOND = TimeUnit.MILLISECONDS.toNanos(1) / 100;
44  
45      /**
46       * <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724290%28v=vs.85%29.aspx">Windows File Times</a>
47       * <p>
48       * A file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00 A.M. January 1, 1601 Coordinated
49       * Universal Time (UTC). This is the offset of Windows time 0 to Unix epoch in 100-nanosecond intervals.
50       * </p>
51       */
52      static final long WINDOWS_EPOCH_OFFSET = -116444736000000000L;
53  
54      /**
55       * Tests whether a FileTime can be safely represented in the standard UNIX time.
56       *
57       * <p>
58       * TODO ? If the FileTime is null, this method always returns true.
59       * </p>
60       *
61       * @param time the FileTime to evaluate, can be null.
62       * @return true if the time exceeds the minimum or maximum UNIX time, false otherwise.
63       */
64      public static boolean isUnixTime(final FileTime time) {
65          // TODO Apache Commons IO 2.16.0
66          return isUnixTime(toUnixTime(time));
67      }
68  
69      /**
70       * Tests whether a given number of seconds (since Epoch) can be safely represented in the standard UNIX time.
71       *
72       * @param seconds the number of seconds (since Epoch) to evaluate.
73       * @return true if the time can be represented in the standard UNIX time, false otherwise.
74       */
75      public static boolean isUnixTime(final long seconds) {
76          // TODO Apache Commons IO 2.16.0
77          return Integer.MIN_VALUE <= seconds && seconds <= Integer.MAX_VALUE;
78      }
79  
80      /**
81       * Converts NTFS time (100 nanosecond units since 1 January 1601) to Java time.
82       *
83       * @param ntfsTime the NTFS time in 100 nanosecond units.
84       * @return the Date.
85       * @deprecated Use {@link FileTimes#ntfsTimeToDate(long)}.
86       */
87      @Deprecated
88      public static Date ntfsTimeToDate(final long ntfsTime) {
89          return FileTimes.ntfsTimeToDate(ntfsTime);
90      }
91  
92      /**
93       * Converts NTFS time (100-nanosecond units since 1 January 1601) to a FileTime.
94       *
95       * @param ntfsTime the NTFS time in 100-nanosecond units.
96       * @return the FileTime.
97       * @see FileTimes#toNtfsTime(FileTime)
98       * @deprecated Use {@link FileTimes#ntfsTimeToFileTime(long)}.
99       */
100     @Deprecated
101     public static FileTime ntfsTimeToFileTime(final long ntfsTime) {
102         return FileTimes.ntfsTimeToFileTime(ntfsTime);
103     }
104 
105     /**
106      * Converts {@link FileTime} to a {@link Date}. If the provided FileTime is {@code null}, the returned Date is also {@code null}.
107      *
108      * @param fileTime the file time to be converted.
109      * @return a {@link Date} which corresponds to the supplied time, or {@code null} if the time is {@code null}.
110      * @see FileTimes#toFileTime(Date)
111      * @deprecated Use {@link FileTimes#toDate(FileTime)}.
112      */
113     @Deprecated
114     public static Date toDate(final FileTime fileTime) {
115         return FileTimes.toDate(fileTime);
116     }
117 
118     /**
119      * Converts {@link Date} to a {@link FileTime}. If the provided Date is {@code null}, the returned FileTime is also {@code null}.
120      *
121      * @param date the date to be converted.
122      * @return a {@link FileTime} which corresponds to the supplied date, or {@code null} if the date is {@code null}.
123      * @see FileTimes#toDate(FileTime)
124      * @deprecated Use {@link FileTimes#toFileTime(Date)}.
125      */
126     @Deprecated
127     public static FileTime toFileTime(final Date date) {
128         return FileTimes.toFileTime(date);
129     }
130 
131     /**
132      * Converts a {@link Date} to NTFS time.
133      *
134      * @param date the Date.
135      * @return the NTFS time.
136      * @deprecated Use {@link FileTimes#toNtfsTime(Date)}.
137      */
138     @Deprecated
139     public static long toNtfsTime(final Date date) {
140         return FileTimes.toNtfsTime(date);
141     }
142 
143     /**
144      * Converts a {@link FileTime} to NTFS time (100-nanosecond units since 1 January 1601).
145      *
146      * @param fileTime the FileTime.
147      * @return the NTFS time in 100-nanosecond units.
148      * @see FileTimes#ntfsTimeToFileTime(long)
149      * @deprecated Use {@link FileTimes#toNtfsTime(FileTime)}.
150      */
151     @Deprecated
152     public static long toNtfsTime(final FileTime fileTime) {
153         return FileTimes.toNtfsTime(fileTime);
154     }
155 
156     /**
157      * Converts Java time (milliseconds since Epoch) to NTFS time.
158      *
159      * @param javaTime the Java time.
160      * @return the NTFS time.
161      */
162     public static long toNtfsTime(final long javaTime) {
163         // TODO Apache Commons IO 2.16.0
164         final long javaHundredNanos = javaTime * HUNDRED_NANOS_PER_MILLISECOND;
165         return Math.subtractExact(javaHundredNanos, WINDOWS_EPOCH_OFFSET);
166     }
167 
168     /**
169      * Converts {@link FileTime} to standard UNIX time.
170      *
171      * @param fileTime the original FileTime.
172      * @return the UNIX timestamp.
173      */
174     public static long toUnixTime(final FileTime fileTime) {
175         // TODO Apache Commons IO 2.16.0
176         return fileTime != null ? fileTime.to(TimeUnit.SECONDS) : 0;
177     }
178 
179     /**
180      * Truncates a FileTime to 100-nanosecond precision.
181      *
182      * @param fileTime the FileTime to be truncated.
183      * @return the truncated FileTime.
184      */
185     public static FileTime truncateToHundredNanos(final FileTime fileTime) {
186         final Instant instant = fileTime.toInstant();
187         return FileTime.from(Instant.ofEpochSecond(instant.getEpochSecond(), instant.getNano() / 100 * 100));
188     }
189 
190     /**
191      * Converts standard UNIX time (in seconds, UTC/GMT) to {@link FileTime}.
192      *
193      * @param time UNIX timestamp (in seconds, UTC/GMT).
194      * @return the corresponding FileTime.
195      */
196     public static FileTime unixTimeToFileTime(final long time) {
197         // TODO Apache Commons IO 2.16.0 FileTimes.fromUnixTime(long)
198         return FileTime.from(time, TimeUnit.SECONDS);
199     }
200 
201     /** Private constructor to prevent instantiation of this utility class. */
202     private TimeUtils() {
203     }
204 }