如何使用FasterXML生成指定日期或24小时前的TimeBasedUUID及代码异常排查
解决FasterXML生成指定日期/24小时前TimeBasedUUID的问题
我来帮你排查这个问题——你代码里的核心问题是错误地初始化了UUIDTimer,咱们一步步来修正:
问题根源
你用new Random(cal.getTimeInMillis())作为UUIDTimer的第一个参数,但这个参数是用来传入随机数生成器的,不是用来设置UUID的生成时间!所以UUIDTimer还是会用当前时间来生成UUID,导致结果始终是当前日期的。
正确实现步骤
要生成指定时间的TimeBasedUUID,需要先把目标时间转换成UUID标准的时间戳格式(从1582-10-15 00:00:00开始的100纳秒间隔数),再用这个时间戳初始化UUIDTimer。
下面是修正后的完整代码:
import com.fasterxml.uuid.Generators; import com.fasterxml.uuid.impl.TimeBasedGenerator; import com.fasterxml.uuid.impl.UUIDTimer; import com.fasterxml.uuid.EthernetAddress; import java.util.Calendar; import java.util.Date; import java.util.Random; import java.util.UUID; public class UUIDGenerator { // UUID epoch到1970-01-01的100纳秒间隔数,这个常量是FasterXML库的标准值 private static final long NUM_100NS_INTERVALS_SINCE_UUID_EPOCH = 0x01b21dd213814000L; public static long getTimeFromUUID(UUID uuid) { return (uuid.timestamp() - NUM_100NS_INTERVALS_SINCE_UUID_EPOCH) / 10000; } public static void timeBasedGenerator() { try { // 1. 设置目标时间:当前时间的前一天 Calendar cal = Calendar.getInstance(); cal.add(Calendar.DAY_OF_MONTH, -1); Date targetDate = cal.getTime(); // 2. 把目标时间转换成UUID标准的时间戳(100纳秒间隔数) long targetMillis = targetDate.getTime(); long uuidTimestamp = (targetMillis * 10000) + NUM_100NS_INTERVALS_SINCE_UUID_EPOCH; // 3. 用目标时间戳初始化UUIDTimer UUIDTimer timer = new UUIDTimer(uuidTimestamp, new Random()); TimeBasedGenerator uuidV1Generator = Generators.timeBasedGenerator(EthernetAddress.fromInterface(), timer); // 4. 生成UUID并验证时间 UUID uuid = uuidV1Generator.generate(); System.out.println("生成的UUID:" + uuid.toString()); long extractedTime = getTimeFromUUID(uuid); Date extractedDate = new Date(extractedTime); System.out.println("UUID对应的时间:" + extractedDate); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { timeBasedGenerator(); } }
关键说明
- UUID时间戳转换:UUID的时间戳单位是100纳秒,而Java的
Date是毫秒,所以需要乘以10000转换;再加上UUID epoch到1970年的偏移量,得到符合UUID标准的时间戳。 UUIDTimer初始化:使用UUIDTimer(long timestamp, Random random)构造器,第一个参数就是我们计算好的目标时间戳,这样生成器就会用这个时间来生成UUID。- 随机数生成器:这里用默认的
Random()即可,不需要绑定时间,它只是用来生成UUID中的随机部分。
额外提示
如果要生成24小时前的UUID,其实和“前一天”逻辑一致(因为24小时就是一天),如果需要更精确的时间偏移(比如精确到小时/分钟),只需要修改Calendar的偏移设置即可,比如cal.add(Calendar.HOUR_OF_DAY, -24)效果是一样的。
内容的提问来源于stack exchange,提问作者Sooriya
相关产品推荐
相关产品推荐

