001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.lang3.time;
019
020import java.time.Instant;
021
022/**
023 * Works with {@link Instant}s.
024 *
025 * @since 3.21.0
026 */
027public class Instants {
028
029    private static long toBound(final Instant instant, final long negBound, final long posBound) {
030        return instant.getEpochSecond() < 0 ? negBound : posBound;
031    }
032
033    /**
034     * Converts an Instant to milliseconds bound to a {@code long} without throwing {@link ArithmeticException}.
035     * <ul>
036     * <li>If the duration milliseconds are greater than {@link Long#MAX_VALUE}, then return {@link Long#MAX_VALUE}.</li>
037     * <li>If the duration milliseconds are lesser than {@link Long#MIN_VALUE}, then return {@link Long#MIN_VALUE}.</li>
038     * <li>If the instant is null, treat it as {@link Instant#EPOCH}.</li>
039     * </ul>
040     *
041     * @param instant The instant to convert, not null.
042     * @return long The given Instant in milliseconds.
043     * @see Instant#toEpochMilli()
044     * @see Long#MIN_VALUE
045     * @see Long#MAX_VALUE
046     */
047    public static long toEpochMillis(final Instant instant) {
048        final Instant instant2 = toInstant(instant);
049        try {
050            return instant2.toEpochMilli();
051        } catch (final ArithmeticException e) {
052            return toBound(instant2, Long.MIN_VALUE, Long.MAX_VALUE);
053        }
054    }
055
056    /**
057     * Returns the given non-null instant, or {@link Instant#EPOCH} if null.
058     *
059     * @param instant The instant to test, may be null.
060     * @return The given non-null instant, or {@link Instant#EPOCH} if null.
061     */
062    public static Instant toInstant(final Instant instant) {
063        return toInstant(instant, Instant.EPOCH);
064    }
065
066    /**
067     * Returns the given non-null instant, or {@code defaultInstant} if instant is null.
068     *
069     * @param instant The instant to test, may be null.
070     * @param defaultInstant The default instant to use if the given instant is null, may be null.
071     * @return The given non-null instant, or {@code defaultInstant} if null.
072     */
073    public static Instant toInstant(final Instant instant, final Instant defaultInstant) {
074        return instant != null ? instant : defaultInstant;
075    }
076
077    /**
078     * Converts an Instant to milliseconds since that Instant bound to a {@code long} without throwing {@link ArithmeticException}.
079     * <ul>
080     * <li>If the duration milliseconds are greater than {@link Long#MAX_VALUE}, then return {@link Long#MAX_VALUE}.</li>
081     * <li>If the duration milliseconds are lesser than {@link Long#MIN_VALUE}, then return {@link Long#MIN_VALUE}.</li>
082     * <li>If the instant is null, treat it as {@link Instant#EPOCH}.</li>
083     * </ul>
084     *
085     * @param instant The instant to convert, not null.
086     * @return long The duration in milliseconds since the given Instant.
087     */
088    public static long toMillisSince(final Instant instant) {
089        return DurationUtils.toMillisLong(DurationUtils.since(toInstant(instant)));
090    }
091
092    /**
093     * No instances needed.
094     */
095    private Instants() {
096        // empty.
097    }
098}