1.应用场景
当我们想将毫秒值转换成一段时间长度时,比如想将5400000毫秒转换成01::30:00这样的格式,结果使用SimpleDateFormat转换过后变成了09:30:00。(结尾有源码)
String s = GalleryDateUtils.millisToString(5400000, "HH:mm:ss");
System.out.println(s);
2.原因解析
为什么只有小时变了?为什么不是其他数字而是9?
分析:如果将小于1小时的毫秒值转化,结果将是正确的,因为时间格式化将其转化为分钟和秒钟,不会受到时区的影响。
而我们是位于东八区,这个时间格式化类,将这个毫秒值看成了时间戳,自然会加上8,这样1变成9也就解释得通了。
为了确认,我们再将格式切换一下。
String s = GalleryDateUtils.millisToString(5400000, "yyyy-MM-dd HH:mm:ss");
System.out.println(s);
果然如我们所想,他是将毫秒值看成了时间戳,这样转换出来的自然是时间日期。
3.问题解决
给SimpleDateFormat设置时区为**“UTC”**。
class DateUtils {
private static final ThreadLocal<Map<String, SimpleDateFormat>> SDF_THREAD_LOCAL =
ThreadLocal.withInitial(() -> new HashMap<>());
public static String millisToString(long millis, final String pattern) {
return millisToString(millis, getSafeDateFormat(pattern));
}
private static SimpleDateFormat getSafeDateFormat(String pattern) {
Map<String, SimpleDateFormat> sdfMap = SDF_THREAD_LOCAL.get();
SimpleDateFormat simpleDateFormat = sdfMap.get(pattern);
if (simpleDateFormat == null) {
simpleDateFormat = new SimpleDateFormat(pattern);
//添加一行设置时区的代码
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
sdfMap.put(pattern, simpleDateFormat);
}
return simpleDateFormat;
}
public static String millisToString(final long millis, final DateFormat format) {
return format.format(new Date(millis));
}
}
这样就如我们所愿,将毫秒转换为时间长度了。