001package com.nimbusds.jwt.util;
002
003
004import java.util.Date;
005
006
007/**
008 * Date utilities.
009 */
010public class DateUtils {
011
012
013        /**
014         * Converts the specified date object to a Unix epoch time in seconds.
015         *
016         * @param date The date. Must not be {@code null}.
017         *
018         * @return The Unix epoch time, in seconds.
019         */
020        public static long toSecondsSinceEpoch(final Date date) {
021
022                return date.getTime() / 1000L;
023        }
024
025
026        /**
027         * Converts the specified Unix epoch time in seconds to a date object.
028         *
029         * @param time The Unix epoch time, in seconds. Must not be negative.
030         *
031         * @return The date.
032         */
033        public static Date fromSecondsSinceEpoch(final long time) {
034
035                return new Date(time * 1000L);
036        }
037
038
039        /**
040         * Check if the specified date is after the specified reference, given
041         * the maximum accepted negative clock skew.
042         *
043         * <p>Formula:
044         *
045         * <pre>
046         * return date + clock_skew > reference
047         * </pre>
048         *
049         * Example: Ensure a JWT expiration (exp) timestamp is after the
050         * current time, with a minute of acceptable clock skew.
051         *
052         * <pre>
053         * boolean valid = DateUtils.isAfter(exp, new Date(), 60);
054         * </pre>
055         *
056         * @param date                The date to check. Must not be
057         *                            {@code null}.
058         * @param reference           The reference date (e.g. the current
059         *                            time). Must not be {@code null}.
060         * @param maxClockSkewSeconds The maximum acceptable negative clock
061         *                            skew of the date value to check, in
062         *                            seconds.
063         *
064         * @return {@code true} if the date is before the reference, plus the
065         *         maximum accepted clock skew, else {@code false}.
066         */
067        public static boolean isAfter(final Date date,
068                                      final Date reference,
069                                      final long maxClockSkewSeconds) {
070
071                return new Date(date.getTime() + maxClockSkewSeconds*1000L).after(reference);
072        }
073
074
075        /**
076         * Checks if the specified date is before the specified reference,
077         * given the maximum accepted positive clock skew.
078         *
079         * <p>Formula:
080         *
081         * <pre>
082         * return date - clock_skew < reference
083         * </pre>
084         *
085         * Example: Ensure a JWT issued-at (iat) timestamp is before the
086         * current time, with a minute of acceptable clock skew.
087         *
088         * <pre>
089         * boolean valid = DateUtils.isBefore(iat, new Date(), 60);
090         * </pre>
091         *
092         * @param date                The date to check. Must not be
093         *                            {@code null}.
094         * @param reference           The reference date (e.g. the current
095         *                            time). Must not be {@code null}.
096         * @param maxClockSkewSeconds The maximum acceptable clock skew of the
097         *                            date value to check, in seconds.
098         *
099         * @return {@code true} if the date is before the reference, minus the
100         *         maximum accepted clock skew, else {@code false}.
101         */
102        public static boolean isBefore(final Date date,
103                                       final Date reference,
104                                       final long maxClockSkewSeconds) {
105
106                return new Date(date.getTime() - maxClockSkewSeconds*1000L).before(reference);
107        }
108
109
110        /**
111         * Prevents instantiation.
112         */
113        private DateUtils() { }
114}