java.time
The legacy date-time API (java.util
date-time types and their formatting type, SimpleDateFormat
etc.) is outdated and error-prone. It is recommended to stop using it completely and switch to java.time
, the modern date-time API*.
Moreover, avoid performing calculations yourself if there is an OOTB (Out-Of-The-Box) API available for it e.g. TimeUnit#convert
. Given below is a java.time
API based solution with a precision of nanosecond:
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
Instant instantNow = Instant.now();
Instant instant14DaysAgo = instantNow.minus(14, ChronoUnit.DAYS);
// A random instant from 14 days ago until a nanosecond ago
Instant instantRandom = instant14DaysAgo.plusNanos(
ThreadLocalRandom.current().nextLong(ChronoUnit.NANOS.between(instant14DaysAgo, instantNow)));
System.out.println(instantRandom);
// The corresponding Epoch milliseconds
System.out.println(instantRandom.toEpochMilli());
// The corresponding Epoch seconds
System.out.println(TimeUnit.SECONDS.convert(instantRandom.toEpochMilli(), TimeUnit.MILLISECONDS));
// The corresponding date-time in JVM's timezone
ZonedDateTime zdtJvm = instantRandom.atZone(ZoneId.systemDefault());
System.out.println(zdtJvm);
// The corresponding date-time in a specific timezone
ZonedDateTime zdtToronto = instantRandom.atZone(ZoneId.of("America/Toronto"));
System.out.println(zdtToronto);
}
}
Output of a sample run:
2021-05-07T01:52:12.382493303Z
1620352332382
1620352332
2021-05-07T02:52:12.382493303+01:00[Europe/London]
2021-05-06T21:52:12.382493303-04:00[America/Toronto]
Learn more about java.time
, the modern date-time API* from Trail: Date Time.
Note: I've updated the answer to incorporate the following good suggestion from Ole V.V.:
Thank you for showing the modern way. While the TimeUnit
enum
certainly has good uses, we don’t need it here. I’d prefer the simpler
instantNow.minus(14, ChronoUnit.DAYS)
and then
instant14DaysAgo.plusNanos(ThreadLocalRandom.current().nextLong(ChronoUnit.NANOS.between(instant14DaysAgo, instantNow)))
.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.