001/*
002 * nimbus-jose-jwt
003 *
004 * Copyright 2012-2016, Connect2id Ltd.
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
007 * this file except in compliance with the License. You may obtain a copy of the
008 * License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software distributed
013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the
015 * specific language governing permissions and limitations under the License.
016 */
017
018package com.nimbusds.jwt.util;
019
020
021import java.util.Date;
022
023
024/**
025 * Date utilities.
026 */
027public class DateUtils {
028        
029        
030        /**
031         * Returns the current {@link Date}, with the milliseconds removed.
032         *
033         * @return The current {@link Date}, with seconds precision.
034         */
035        public static Date nowWithSecondsPrecision() {
036                
037                return fromSecondsSinceEpoch(toSecondsSinceEpoch(new Date()));
038        }
039
040
041        /**
042         * Converts the specified {@link Date} to seconds since the Unix epoch.
043         *
044         * @param date The {@link Date}. Must not be {@code null}.
045         *
046         * @return The seconds since the Unix epoch.
047         */
048        public static long toSecondsSinceEpoch(final Date date) {
049
050                return date.getTime() / 1000L;
051        }
052
053
054        /**
055         * Converts the specified seconds since the Unix epoch to a
056         * {@link Date}.
057         *
058         * @param time The seconds since the Unix epoch. Must not be negative.
059         *
060         * @return The {@link Date}.
061         */
062        public static Date fromSecondsSinceEpoch(final long time) {
063
064                return new Date(time * 1000L);
065        }
066
067
068        /**
069         * Check if the specified {@link Date} is after the specified
070         * reference, given the maximum accepted negative clock skew.
071         *
072         * <p>Formula:
073         *
074         * <pre>
075         * return date + clock_skew &gt; reference
076         * </pre>
077         *
078         * Example: Ensure a JWT expiration (exp) timestamp is after the
079         * current time, with a minute of acceptable clock skew.
080         *
081         * <pre>
082         * boolean valid = DateUtils.isAfter(exp, new Date(), 60);
083         * </pre>
084         *
085         * @param date                The {@link Date} to check. Must not be
086         *                            {@code null}.
087         * @param reference           The reference {@link Date} (e.g. the
088         *                            current time). Must not be {@code null}.
089         * @param maxClockSkewSeconds The maximum acceptable negative clock
090         *                            skew of the date value to check, in
091         *                            seconds.
092         *
093         * @return {@code true} if the {@link Date} is before the reference,
094         *         plus the maximum accepted clock skew, else {@code false}.
095         */
096        public static boolean isAfter(final Date date,
097                                      final Date reference,
098                                      final long maxClockSkewSeconds) {
099
100                return new Date(date.getTime() + maxClockSkewSeconds*1000L).after(reference);
101        }
102
103
104        /**
105         * Checks if the specified {@link Date} is before the specified
106         * reference, given the maximum accepted positive clock skew.
107         *
108         * <p>Formula:
109         *
110         * <pre>
111         * return date - clock_skew &lt; reference
112         * </pre>
113         *
114         * Example: Ensure a JWT issued-at (iat) timestamp is before the
115         * current time, with a minute of acceptable clock skew.
116         *
117         * <pre>
118         * boolean valid = DateUtils.isBefore(iat, new Date(), 60);
119         * </pre>
120         *
121         * @param date                The {@link Date} to check. Must not be
122         *                            {@code null}.
123         * @param reference           The reference {@link Date} (e.g. the
124         *                            current time). Must not be {@code null}.
125         * @param maxClockSkewSeconds The maximum acceptable clock skew of the
126         *                            date value to check, in seconds.
127         *
128         * @return {@code true} if the {@link Date} is before the reference,
129         *         minus the maximum accepted clock skew, else {@code false}.
130         */
131        public static boolean isBefore(final Date date,
132                                       final Date reference,
133                                       final long maxClockSkewSeconds) {
134
135                return new Date(date.getTime() - maxClockSkewSeconds*1000L).before(reference);
136        }
137        
138        
139        /**
140         * Checks if the specified {@link Date} is within the specified
141         * reference, give or take the maximum accepted clock skew.
142         *
143         * @param date                The {@link Date} to check. Must not be
144         *                            {@code null}.
145         * @param reference           The reference {@link Date} (e.g. the
146         *                            current time). Must not be {@code null}.
147         * @param maxClockSkewSeconds The maximum acceptable clock skew of the
148         *                            date value to check, in seconds.
149         *
150         * @return {@code true} if the {@link Date} is within the reference,
151         *         give or take the maximum accepted clock skew, else
152         *         {@code false}.
153         */
154        public static boolean isWithin(final Date date,
155                                       final Date reference,
156                                       final long maxClockSkewSeconds) {
157                
158                long minTime = reference.getTime() - maxClockSkewSeconds*1000L;
159                long maxTime = reference.getTime() + maxClockSkewSeconds*1000L;
160                
161                return date.getTime() > minTime && date.getTime() < maxTime;
162        }
163
164
165        /**
166         * Prevents instantiation.
167         */
168        private DateUtils() { }
169}