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    *      https://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.lang3.time;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertNotNull;
22  import static org.junit.jupiter.api.Assertions.assertSame;
23  import static org.junit.jupiter.api.Assertions.assertTrue;
24  
25  import java.time.Instant;
26  
27  import org.apache.commons.lang3.AbstractLangTest;
28  import org.junit.jupiter.api.Test;
29  
30  /**
31   * Tests {@link Instants}.
32   */
33  class InstantsTest extends AbstractLangTest {
34  
35      /**
36       * An Instant far in the future whose epoch-millis overflow {@code long}: seconds chosen so that {@code seconds * 1_000} exceeds {@link Long#MAX_VALUE}.
37       */
38      private static final Instant INSTANT_FAR_FUTURE = Instant.ofEpochSecond(Long.MAX_VALUE / 1_000 + 1_000);
39      /**
40       * An Instant far in the past whose epoch-millis underflow {@code long}: seconds chosen so that {@code seconds * 1_000} is less than {@link Long#MIN_VALUE}.
41       */
42      private static final Instant INSTANT_FAR_PAST = Instant.ofEpochSecond(Long.MIN_VALUE / 1_000 - 1_000);
43  
44      @Test
45      void testToEpochMillisEpoch() {
46          assertEquals(0L, Instants.toEpochMillis(Instant.EPOCH));
47      }
48  
49      @Test
50      void testToEpochMillisMaxValue() {
51          assertEquals(Long.MAX_VALUE, Instants.toEpochMillis(Instant.ofEpochMilli(Long.MAX_VALUE)));
52      }
53  
54      @Test
55      void testToEpochMillisMinValue() {
56          assertEquals(Long.MIN_VALUE, Instants.toEpochMillis(Instant.ofEpochMilli(Long.MIN_VALUE)));
57      }
58  
59      @Test
60      void testToEpochMillisNegativeMillis() {
61          assertEquals(-1_000_000L, Instants.toEpochMillis(Instant.ofEpochMilli(-1_000_000L)));
62      }
63  
64      @Test
65      void testToEpochMillisNormalInstant() {
66          assertEquals(1_000_000L, Instants.toEpochMillis(Instant.ofEpochMilli(1_000_000L)));
67      }
68  
69      @Test
70      void testToEpochMillisNow() {
71          final Instant now = Instant.now();
72          assertEquals(now.toEpochMilli(), Instants.toEpochMillis(now));
73      }
74  
75      @Test
76      void testToEpochMillisOverflowReturnsMaxValue() {
77          assertEquals(Long.MAX_VALUE, Instants.toEpochMillis(INSTANT_FAR_FUTURE));
78      }
79  
80      @Test
81      void testToEpochMillisUnderflowReturnsMinValue() {
82          assertEquals(Long.MIN_VALUE, Instants.toEpochMillis(INSTANT_FAR_PAST));
83      }
84  
85      @Test
86      void testToInstantEpochReturnsSameInstance() {
87          assertSame(Instant.EPOCH, Instants.toInstant(Instant.EPOCH));
88      }
89  
90      @Test
91      void testToInstantMaxReturnsSameInstance() {
92          assertSame(Instant.MAX, Instants.toInstant(Instant.MAX));
93      }
94  
95      @Test
96      void testToInstantMinReturnsSameInstance() {
97          assertSame(Instant.MIN, Instants.toInstant(Instant.MIN));
98      }
99  
100     @Test
101     void testToInstantNonNullIsNotNull() {
102         assertNotNull(Instants.toInstant(Instant.now()));
103     }
104 
105     @Test
106     void testToInstantNonNullReturnsSameInstance() {
107         final Instant now = Instant.now();
108         assertSame(now, Instants.toInstant(now));
109     }
110 
111     @Test
112     void testToInstantNullReturnsEpoch() {
113         assertEquals(Instant.EPOCH, Instants.toInstant(null));
114     }
115 
116     @Test
117     void testToInstantWithDefaultEpochReturnsSameInstance() {
118         assertSame(Instant.EPOCH, Instants.toInstant(Instant.EPOCH, Instant.MAX));
119     }
120 
121     @Test
122     void testToInstantWithDefaultMaxReturnsSameInstance() {
123         assertSame(Instant.MAX, Instants.toInstant(Instant.MAX, Instant.MIN));
124     }
125 
126     @Test
127     void testToInstantWithDefaultMinReturnsSameInstance() {
128         assertSame(Instant.MIN, Instants.toInstant(Instant.MIN, Instant.MAX));
129     }
130 
131     @Test
132     void testToInstantWithDefaultNonNullIgnoresDefault() {
133         final Instant value = Instant.ofEpochMilli(1_000L);
134         final Instant defaultInstant = Instant.ofEpochMilli(9_999L);
135         assertSame(value, Instants.toInstant(value, defaultInstant));
136     }
137 
138     @Test
139     void testToInstantWithDefaultNonNullReturnsSameInstance() {
140         final Instant now = Instant.now();
141         assertSame(now, Instants.toInstant(now, Instant.EPOCH));
142     }
143 
144     @Test
145     void testToInstantWithDefaultNullAndEpochDefaultReturnsEpoch() {
146         assertSame(Instant.EPOCH, Instants.toInstant(null, Instant.EPOCH));
147     }
148 
149     @Test
150     void testToInstantWithDefaultNullReturnsDefault() {
151         final Instant defaultInstant = Instant.ofEpochMilli(12345L);
152         assertSame(defaultInstant, Instants.toInstant(null, defaultInstant));
153     }
154 
155     @Test
156     void testToInstantWithDefaultNullReturnsNullDefault() {
157         assertSame(null, Instants.toInstant(null, null));
158     }
159 
160     /**
161      * Epoch instant (time zero): milliseconds since epoch should be positive and equal to
162      * roughly the current time in millis (with a generous lower bound).
163      */
164     @Test
165     void testToMillisSinceEpoch() {
166         // As of 2026, ~1.7 trillion ms have elapsed since epoch.
167         assertTrue(Instants.toMillisSince(Instant.EPOCH) > 0);
168     }
169 
170     /**
171      * A future instant one second from now; milliseconds since it should be negative (roughly -1_000).
172      */
173     @Test
174     void testToMillisSinceFutureInstantIsNegative() {
175         final Instant oneSecondFuture = Instant.now().plusMillis(1_000);
176         final long millis = Instants.toMillisSince(oneSecondFuture);
177         // Duration from a future instant to now is negative.
178         assertTrue(millis <= -900, "Expected millis <= -900 but was " + millis);
179     }
180 
181     /**
182      * {@link Instant#MAX} is in the future, so the duration from it to now is negative and underflows {@code long}
183      * millis; the bound is {@link Long#MIN_VALUE}.
184      */
185     @Test
186     void testToMillisSinceInstantMaxUnderflowReturnsMinValue() {
187         assertEquals(Long.MIN_VALUE, Instants.toMillisSince(Instant.MAX));
188     }
189 
190     /**
191      * {@link Instant#MIN} is in the past, so the duration from it to now is positive and overflows {@code long}
192      * millis; the bound is {@link Long#MAX_VALUE}.
193      */
194     @Test
195     void testToMillisSinceInstantMinOverflowReturnsMaxValue() {
196         assertEquals(Long.MAX_VALUE, Instants.toMillisSince(Instant.MIN));
197     }
198 
199     /**
200      * Instant.now(); milliseconds since should be very close to zero (within a generous tolerance).
201      */
202     @Test
203     void testToMillisSinceNowIsNearZero() {
204         final Instant now = Instant.now();
205         final long millis = Instants.toMillisSince(now);
206         // Allow a generous 5_000 ms window for slow test environments.
207         assertTrue(millis >= 0 && millis < 5_000, "Expected millis in [0, 5000) but was " + millis);
208     }
209 
210     /**
211      * A past instant one second ago; milliseconds since it should be approximately 1_000.
212      */
213     @Test
214     void testToMillisSincePastInstantIsPositive() {
215         final Instant oneSecondAgo = Instant.now().minusMillis(1_000);
216         final long millis = Instants.toMillisSince(oneSecondAgo);
217         // Should be at least 1_000 ms (wall time may have advanced slightly more).
218         assertTrue(millis >= 1_000, "Expected millis >= 1000 but was " + millis);
219     }
220 }