• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 package org.apache.commons.io.file.attribute;
19 
20 import java.io.IOException;
21 import java.nio.file.Files;
22 import java.nio.file.Path;
23 import java.nio.file.attribute.FileTime;
24 import java.time.Instant;
25 import java.util.Date;
26 import java.util.concurrent.TimeUnit;
27 
28 /**
29  * Helps use {@link FileTime} and interoperate Date and NTFS times.
30  *
31  * @since 2.12.0
32  */
33 public class FileTimes {
34 
35     /**
36      * Constant for the {@code 1970-01-01T00:00:00Z} {@link Instant#EPOCH epoch} as a time stamp attribute.
37      *
38      * @see Instant#EPOCH
39      */
40     public static final FileTime EPOCH = FileTime.from(Instant.EPOCH);
41 
42     /**
43      * The offset of Windows time 0 to Unix epoch in 100-nanosecond intervals.
44      *
45      * <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724290%28v=vs.85%29.aspx">Windows File Times</a>
46      * <p>
47      * A file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00
48      * A.M. January 1, 1601 Coordinated Universal Time (UTC). This is the offset of Windows time 0 to Unix epoch in
49      * 100-nanosecond intervals.
50      * </p>
51      */
52     static final long WINDOWS_EPOCH_OFFSET = -116444736000000000L;
53 
54     /**
55      * The amount of 100-nanosecond intervals in one second.
56      */
57     private static final long HUNDRED_NANOS_PER_SECOND = TimeUnit.SECONDS.toNanos(1) / 100;
58 
59     /**
60      * The amount of 100-nanosecond intervals in one millisecond.
61      */
62     static final long HUNDRED_NANOS_PER_MILLISECOND = TimeUnit.MILLISECONDS.toNanos(1) / 100;
63 
64     /**
65      * Subtracts milliseconds from a source FileTime.
66      *
67      * @param fileTime The source FileTime.
68      * @param millisToSubtract The milliseconds to subtract.
69      * @return The resulting FileTime.
70      */
minusMillis(final FileTime fileTime, final long millisToSubtract)71     public static FileTime minusMillis(final FileTime fileTime, final long millisToSubtract) {
72         return FileTime.from(fileTime.toInstant().minusMillis(millisToSubtract));
73     }
74 
75     /**
76      * Subtracts nanoseconds from a source FileTime.
77      *
78      * @param fileTime The source FileTime.
79      * @param nanosToSubtract The nanoseconds to subtract.
80      * @return The resulting FileTime.
81      */
minusNanos(final FileTime fileTime, final long nanosToSubtract)82     public static FileTime minusNanos(final FileTime fileTime, final long nanosToSubtract) {
83         return FileTime.from(fileTime.toInstant().minusNanos(nanosToSubtract));
84     }
85 
86     /**
87      * Subtracts seconds from a source FileTime.
88      *
89      * @param fileTime The source FileTime.
90      * @param secondsToSubtract The seconds to subtract.
91      * @return The resulting FileTime.
92      */
minusSeconds(final FileTime fileTime, final long secondsToSubtract)93     public static FileTime minusSeconds(final FileTime fileTime, final long secondsToSubtract) {
94         return FileTime.from(fileTime.toInstant().minusSeconds(secondsToSubtract));
95     }
96 
97     /**
98      * Obtains the current instant FileTime from the system clock.
99      *
100      * @return the current instant FileTime from the system clock.
101      */
now()102     public static FileTime now() {
103         return FileTime.from(Instant.now());
104     }
105 
106     /**
107      * Converts NTFS time (100 nanosecond units since 1 January 1601) to Java time.
108      *
109      * @param ntfsTime the NTFS time in 100 nanosecond units
110      * @return the Date
111      */
ntfsTimeToDate(final long ntfsTime)112     public static Date ntfsTimeToDate(final long ntfsTime) {
113         final long javaHundredNanos = Math.addExact(ntfsTime, WINDOWS_EPOCH_OFFSET);
114         final long javaMillis = Math.floorDiv(javaHundredNanos, HUNDRED_NANOS_PER_MILLISECOND);
115         return new Date(javaMillis);
116     }
117 
118     /**
119      * Converts NTFS time (100-nanosecond units since 1 January 1601) to a FileTime.
120      *
121      * @param ntfsTime the NTFS time in 100-nanosecond units
122      * @return the FileTime
123      *
124      * @see #toNtfsTime(FileTime)
125      */
ntfsTimeToFileTime(final long ntfsTime)126     public static FileTime ntfsTimeToFileTime(final long ntfsTime) {
127         final long javaHundredsNanos = Math.addExact(ntfsTime, WINDOWS_EPOCH_OFFSET);
128         final long javaSeconds = Math.floorDiv(javaHundredsNanos, HUNDRED_NANOS_PER_SECOND);
129         final long javaNanos = Math.floorMod(javaHundredsNanos, HUNDRED_NANOS_PER_SECOND) * 100;
130         return FileTime.from(Instant.ofEpochSecond(javaSeconds, javaNanos));
131     }
132 
133     /**
134      * Adds milliseconds to a source FileTime.
135      *
136      * @param fileTime The source FileTime.
137      * @param millisToAdd The milliseconds to add.
138      * @return The resulting FileTime.
139      */
plusMillis(final FileTime fileTime, final long millisToAdd)140     public static FileTime plusMillis(final FileTime fileTime, final long millisToAdd) {
141         return FileTime.from(fileTime.toInstant().plusMillis(millisToAdd));
142     }
143 
144     /**
145      * Adds nanoseconds from a source FileTime.
146      *
147      * @param fileTime The source FileTime.
148      * @param nanosToSubtract The nanoseconds to subtract.
149      * @return The resulting FileTime.
150      */
plusNanos(final FileTime fileTime, final long nanosToSubtract)151     public static FileTime plusNanos(final FileTime fileTime, final long nanosToSubtract) {
152         return FileTime.from(fileTime.toInstant().plusNanos(nanosToSubtract));
153     }
154 
155     /**
156      * Adds seconds to a source FileTime.
157      *
158      * @param fileTime The source FileTime.
159      * @param secondsToAdd The seconds to add.
160      * @return The resulting FileTime.
161      */
plusSeconds(final FileTime fileTime, final long secondsToAdd)162     public static FileTime plusSeconds(final FileTime fileTime, final long secondsToAdd) {
163         return FileTime.from(fileTime.toInstant().plusSeconds(secondsToAdd));
164     }
165 
166     /**
167      * Sets the last modified time of the given file path to now.
168      *
169      * @param path The file path to set.
170      * @throws IOException if an I/O error occurs.
171      */
setLastModifiedTime(final Path path)172     public static void setLastModifiedTime(final Path path) throws IOException {
173         Files.setLastModifiedTime(path, now());
174     }
175 
176     /**
177      * Converts {@link FileTime} to a {@link Date}. If the provided FileTime is {@code null}, the returned Date is also
178      * {@code null}.
179      *
180      * @param fileTime the file time to be converted.
181      * @return a {@link Date} which corresponds to the supplied time, or {@code null} if the time is {@code null}.
182      * @see #toFileTime(Date)
183      */
toDate(final FileTime fileTime)184     public static Date toDate(final FileTime fileTime) {
185         return fileTime != null ? new Date(fileTime.toMillis()) : null;
186     }
187 
188     /**
189      * Converts {@link Date} to a {@link FileTime}. If the provided Date is {@code null}, the returned FileTime is also
190      * {@code null}.
191      *
192      * @param date the date to be converted.
193      * @return a {@link FileTime} which corresponds to the supplied date, or {@code null} if the date is {@code null}.
194      * @see #toDate(FileTime)
195      */
toFileTime(final Date date)196     public static FileTime toFileTime(final Date date) {
197         return date != null ? FileTime.fromMillis(date.getTime()) : null;
198     }
199 
200     /**
201      * Converts a {@link Date} to NTFS time.
202      *
203      * @param date the Date
204      * @return the NTFS time
205      */
toNtfsTime(final Date date)206     public static long toNtfsTime(final Date date) {
207         final long javaHundredNanos = date.getTime() * HUNDRED_NANOS_PER_MILLISECOND;
208         return Math.subtractExact(javaHundredNanos, WINDOWS_EPOCH_OFFSET);
209     }
210 
211     /**
212      * Converts a {@link FileTime} to NTFS time (100-nanosecond units since 1 January 1601).
213      *
214      * @param fileTime the FileTime
215      * @return the NTFS time in 100-nanosecond units
216      */
toNtfsTime(final FileTime fileTime)217     public static long toNtfsTime(final FileTime fileTime) {
218         final Instant instant = fileTime.toInstant();
219         final long javaHundredNanos = instant.getEpochSecond() * HUNDRED_NANOS_PER_SECOND + instant.getNano() / 100;
220         return Math.subtractExact(javaHundredNanos, WINDOWS_EPOCH_OFFSET);
221     }
222 
FileTimes()223     private FileTimes() {
224         // No instances.
225     }
226 }
227