/** * */ package com.github.javafaker; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.concurrent.TimeUnit; /** * A generator of random dates. * * @author pmiklos * */ public class DateAndTime { private static final int DEFAULT_MIN_AGE = 18; private static final int DEFAULT_MAX_AGE = 65; private final Faker faker; protected DateAndTime(Faker faker) { this.faker = faker; } /** * Generates a future date from now. Note that there is a 1 second slack to avoid generating a past date. * * @param atMost * at most this amount of time ahead from now exclusive. * @param unit * the time unit. * @return a future date from now. */ public Date future(int atMost, TimeUnit unit) { Date now = new Date(); Date aBitLaterThanNow = new Date(now.getTime() + 1000); return future(atMost, unit, aBitLaterThanNow); } /** * Generates a future date from now, with a minimum time. * * @param atMost * at most this amount of time ahead from now exclusive. * @param minimum * the minimum amount of time in the future from now. * @param unit * the time unit. * @return a future date from now. */ public Date future(int atMost, int minimum, TimeUnit unit) { Date now = new Date(); Date minimumDate = new Date(now.getTime() + unit.toMillis(minimum)); return future(atMost - minimum, unit, minimumDate); } /** * Generates a future date relative to the {@code referenceDate}. * * @param atMost * at most this amount of time ahead to the {@code referenceDate} exclusive. * @param unit * the time unit. * @param referenceDate * the future date relative to this date. * @return a future date relative to {@code referenceDate}. */ public Date future(int atMost, TimeUnit unit, Date referenceDate) { long upperBound = unit.toMillis(atMost); long futureMillis = referenceDate.getTime(); futureMillis += 1 + faker.random().nextLong(upperBound - 1); return new Date(futureMillis); } /** * Generates a past date from now. Note that there is a 1 second slack added. * * @param atMost * at most this amount of time earlier from now exclusive. * @param unit * the time unit. * @return a past date from now. */ public Date past(int atMost, TimeUnit unit) { Date now = new Date(); Date aBitEarlierThanNow = new Date(now.getTime() - 1000); return past(atMost, unit, aBitEarlierThanNow); } /** * Generates a past date from now, with a minimum time. * * @param atMost * at most this amount of time earlier from now exclusive. * @param minimum * the minimum amount of time in the past from now. * @param unit * the time unit. * @return a past date from now. */ public Date past(int atMost, int minimum, TimeUnit unit) { Date now = new Date(); Date minimumDate = new Date(now.getTime() - unit.toMillis(minimum)); return past(atMost - minimum, unit, minimumDate); } /** * Generates a past date relative to the {@code referenceDate}. * * @param atMost * at most this amount of time past to the {@code referenceDate} exclusive. * @param unit * the time unit. * @param referenceDate * the past date relative to this date. * @return a past date relative to {@code referenceDate}. */ public Date past(int atMost, TimeUnit unit, Date referenceDate) { long upperBound = unit.toMillis(atMost); long futureMillis = referenceDate.getTime(); futureMillis -= 1 + faker.random().nextLong(upperBound - 1); return new Date(futureMillis); } /** * Generates a random date between two dates. * * @param from * the lower bound inclusive * @param to * the upper bound exclusive * @return a random date between {@code from} and {@code to}. * @throws IllegalArgumentException * if the {@code to} date represents an earlier date than {@code from} date. */ public Date between(Date from, Date to) throws IllegalArgumentException { if (to.before(from)) { throw new IllegalArgumentException("Invalid date range, the upper bound date is before the lower bound."); } long offsetMillis = faker.random().nextLong(to.getTime() - from.getTime()); return new Date(from.getTime() + offsetMillis); } /** * Generates a random birthday between 65 and 18 years ago. * * @return a random birthday between 65 and 18 years ago. */ public Date birthday() { return birthday(DEFAULT_MIN_AGE, DEFAULT_MAX_AGE); } /** * Generates a random birthday between two ages. * * @param minAge * the minimal age * @param maxAge * the maximal age * @return a random birthday between {@code minAge} and {@code maxAge} years ago. * @throws IllegalArgumentException * if the {@code maxAge} is lower than {@code minAge}. */ public Date birthday(int minAge, int maxAge) { int currentYear = Calendar.getInstance().get(Calendar.YEAR); Calendar from = new GregorianCalendar(currentYear - maxAge, 0, 1); Calendar to = new GregorianCalendar(currentYear - minAge, 11, 31); return between(from.getTime(), to.getTime()); } }