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 date, with the milliseconds removed.
032         *
033         * @return The current 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 date object to a Unix epoch time in seconds.
043         *
044         * @param date The date. Must not be {@code null}.
045         *
046         * @return The Unix epoch time, in seconds.
047         */
048        public static long toSecondsSinceEpoch(final Date date) {
049
050                return date.getTime() / 1000L;
051        }
052
053
054        /**
055         * Converts the specified Unix epoch time in seconds to a date object.
056         *
057         * @param time The Unix epoch time, in seconds. Must not be negative.
058         *
059         * @return The date.
060         */
061        public static Date fromSecondsSinceEpoch(final long time) {
062
063                return new Date(time * 1000L);
064        }
065
066
067        /**
068         * Check if the specified date is after the specified reference, given
069         * the maximum accepted negative clock skew.
070         *
071         * <p>Formula:
072         *
073         * <pre>
074         * return date + clock_skew &gt; reference
075         * </pre>
076         *
077         * Example: Ensure a JWT expiration (exp) timestamp is after the
078         * current time, with a minute of acceptable clock skew.
079         *
080         * <pre>
081         * boolean valid = DateUtils.isAfter(exp, new Date(), 60);
082         * </pre>
083         *
084         * @param date                The date to check. Must not be
085         *                            {@code null}.
086         * @param reference           The reference date (e.g. the current
087         *                            time). Must not be {@code null}.
088         * @param maxClockSkewSeconds The maximum acceptable negative clock
089         *                            skew of the date value to check, in
090         *                            seconds.
091         *
092         * @return {@code true} if the date is before the reference, plus the
093         *         maximum accepted clock skew, else {@code false}.
094         */
095        public static boolean isAfter(final Date date,
096                                      final Date reference,
097                                      final long maxClockSkewSeconds) {
098
099                return new Date(date.getTime() + maxClockSkewSeconds*1000L).after(reference);
100        }
101
102
103        /**
104         * Checks if the specified date is before the specified reference,
105         * given the maximum accepted positive clock skew.
106         *
107         * <p>Formula:
108         *
109         * <pre>
110         * return date - clock_skew &lt; reference
111         * </pre>
112         *
113         * Example: Ensure a JWT issued-at (iat) timestamp is before the
114         * current time, with a minute of acceptable clock skew.
115         *
116         * <pre>
117         * boolean valid = DateUtils.isBefore(iat, new Date(), 60);
118         * </pre>
119         *
120         * @param date                The date to check. Must not be
121         *                            {@code null}.
122         * @param reference           The reference date (e.g. the current
123         *                            time). Must not be {@code null}.
124         * @param maxClockSkewSeconds The maximum acceptable clock skew of the
125         *                            date value to check, in seconds.
126         *
127         * @return {@code true} if the date is before the reference, minus the
128         *         maximum accepted clock skew, else {@code false}.
129         */
130        public static boolean isBefore(final Date date,
131                                       final Date reference,
132                                       final long maxClockSkewSeconds) {
133
134                return new Date(date.getTime() - maxClockSkewSeconds*1000L).before(reference);
135        }
136        
137        
138        /**
139         * Checks if the specified date is within the specified reference,
140         * give or take the maximum accepted clock skew.
141         *
142         * @param date                The date to check. Must not be
143         *                            {@code null}.
144         * @param reference           The reference date (e.g. the current
145         *                            time). Must not be {@code null}.
146         * @param maxClockSkewSeconds The maximum acceptable clock skew of the
147         *                            date value to check, in seconds.
148         *
149         * @return {@code true} if the date is within the reference, give or
150         *         take the maximum accepted clock skew, else {@code false}.
151         */
152        public static boolean isWithin(final Date date,
153                                       final Date reference,
154                                       final long maxClockSkewSeconds) {
155                
156                long minTime = reference.getTime() - maxClockSkewSeconds*1000L;
157                long maxTime = reference.getTime() + maxClockSkewSeconds*1000L;
158                
159                return date.getTime() > minTime && date.getTime() < maxTime;
160        }
161
162
163        /**
164         * Prevents instantiation.
165         */
166        private DateUtils() { }
167}