尝试在Java中创建一个纪元值,其中返回值介于现在和14天之前
我使用java.util.Random.nextInt(value)
并传递1209600
,基本上是14天
但是返回的价值从来没有比现在更早,为什么呢?
public class Debug {
private static final Random rng = new Random();
public static void main(String[] args) {
long now = System.currentTimeMillis();
long timeSinceLastVisit = rng.nextInt(14 * 24 * 60 * 60);
long timeOfLastVisit = now - timeSinceLastVisit;
String date = new java.text.SimpleDateFormat("MM/dd/yyyy HH:mm:ss").format(new java.util.Date (timeOfLastVisit));
System.out.println("1. " + timeOfLastVisit);
System.out.println(date);
}
}
5个样本输出:
1. 1397057814065
04/09/2014 16:36:54
1. 1397058754779
04/09/2014 16:52:34
1. 1397058553618
04/09/2014 16:49:13
1. 1397058294674
04/09/2014 16:44:54
1. 1397058408390
04/09/2014 16:46:48
答案 0 :(得分:2)
旧的日期时间 API(java.util
日期时间类型及其格式类型,SimpleDateFormat
等)已经过时且容易出错。建议完全停止使用,改用java.time
,modern date-time API*。
此外,如果有可用的 OOTB(开箱即用)API,请避免自己执行计算,例如TimeUnit#convert
。下面给出了一个基于 java.time
API 的解决方案,精度为纳秒:
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);
}
}
示例运行的输出:
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]
从 modern date-time API 中详细了解 java.time
,Trail: Date Time*。
注意:我已经更新了答案以纳入来自 Ole V.V. 的以下好建议:
<块引用>感谢您展示现代方式。而 TimeUnit
枚举
当然有很好的用途,我们这里不需要它。我更喜欢简单的
instantNow.minus(14, ChronoUnit.DAYS)
然后
instant14DaysAgo.plusNanos(ThreadLocalRandom.current().nextLong(ChronoUnit.NANOS.between(instant14DaysAgo, instantNow)))
。
* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring 和 How to use ThreeTenABP in Android Project。
答案 1 :(得分:1)
您应该使用毫秒,并在行
中long timeSinceLastVisit = rng.nextInt(14 * 24 * 60 * 60);
你刚刚得到&#34;秒&#34;。要解决此问题,请乘以1000
,以便得到一个代表毫秒的值:
long timeSinceLastVisit = rng.nextInt(14 * 24 * 60 * 60 * 1000);
示例输出:
04/01/2014 21:56:04
04/03/2014 21:44:41
04/07/2014 05:38:58
03/29/2014 22:19:29
04/02/2014 08:54:51
答案 2 :(得分:0)
关于毫秒和秒的混淆是之前认可的原因,但我建议稍微修改一下,以实现两个目标:
关于整数溢出的更多稳定性(想象一下,OP希望将14改为100)
long timeSinceLastVisit = rng.nextInt(14 * 24 * 60 * 60)* 1000L;