1. 需求描述
根据业务方的需求,我们需要取数据库里某个类型为timestamp的字段存到ES,但是这个字段需要转成当日0时刻(即00:00:00)时刻的时间戳。
2. 解决方案
最初的设想是计算当天已经经过的毫秒数,然后通过getTime()拿到的时间戳减去当天已经经过的毫秒数加上当前时区时间戳的偏移量
import java.util.Date; import java.util.TimeZone; /** * @author * @version 1.0 * @date */ public class DateUtils { private static final long MILLIS_PER_DAY = 86400000L; private static final long TIME_ZONE_OFFSET = TimeZone.getDefault().getRawOffset(); /** * 获取指定时间当日 00:00:00 时刻的时间戳 */ public static Long getDayTimestamp(Date date) { if (date == null) { return null; } /* 距离当日 00:00:00 时刻毫秒数 */ long dayOffsetTimestamp = date.getTime() % MILLIS_PER_DAY; return date.getTime() - dayOffsetTimestamp + TIME_ZONE_OFFSET; } private DateUtils () {} }
但是这样存在 bug,当0时区和当前时区时间不在同一天的时候会出现问题,getTime() % MILLIS_PER_DAY 得到的是0时区当天已经经过的毫秒数而非当前时区,更悲惨的是,当时自测的时候只简单测了一下,用 new Date() 测试的没问题,第二天业务方反馈说有问题才发现。修复后的版本如下
import java.util.Date; import java.util.TimeZone; /** * @author * @version 1.0 * @date */ public class DateUtils { private static final long MILLIS_PER_DAY = 86400000L; private static final long TIME_ZONE_OFFSET = TimeZone.getDefault().getRawOffset(); /** * 获取指定时间当日 00:00:00 时刻的时间戳 */ public static Long getDayTimestamp(Date date) { if (date == null) { return null; } /* 距离当日 00:00:00 时刻毫秒数 */ long dayOffsetTimestamp = (date.getTime() + TIME_ZONE_OFFSET) % MILLIS_PER_DAY; return date.getTime() - dayOffsetTimestamp; } private DateUtils () {} }