我正在以UTC ISO8601
格式从我的服务器接收时间,如下所示:
2018-01-25T05:14:03.4973436
我正在使用我当前的string
将此milliseconds
转换为generating
,并且我time
已经过了一段时间值:
public static CharSequence getRelativeTimeSpan(String timeStamp) {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
format.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = format.parse(timeStamp);
long past = date.getTime();
int offset = TimeZone.getDefault().getRawOffset() + TimeZone.getDefault().getDSTSavings();
long now = System.currentTimeMillis() + offset;
return DateUtils.getRelativeTimeSpanString(
past,
now,
DateUtils.MINUTE_IN_MILLIS);
}
但是,出于某种原因,代码会在 过去 和 现在 <之间产生12 hours
的直接差异/ strong>即可。我不确定为什么存在这样的差异但是例如UTC
字符串( 2018-01-25T05:14:03.4973436 )
会生成以下milliseconds
值( 1516857243000 )
,但它并不真正对应到time
中的当前milliseconds
。
所有这一切的有趣之处在于,这种自动12 hour
存在差异。我确保使用"HH"
代替"hh"
来解释AM/PM
差异,因此我不知道造成这种差异的原因。
使用JAVA8时间更新 - 仍然是相同的行为
我已使用以下代码段更新了代码,但我得到了完全相同的行为(12小时即时差异)
public static CharSequence getRelativeTimeSpan(String timeStamp) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSS");
LocalDateTime fromCustomPattern = LocalDateTime.parse(timeStamp, formatter);
return DateUtils.getRelativeTimeSpanString(
fromCustomPattern.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(),
Instant.now().toEpochMilli(),
DateUtils.MINUTE_IN_MILLIS);
}
答案 0 :(得分:3)
两个问题:
long
和Date
的 System.currentTimeInMillis()
毫秒来自UTC。在比较这些值时,不需要添加时区偏移。你不应该像那样调整时区。
Date
,SimpleDateFormat
等仅支持毫秒分辨率,但源字符串的分辨率为100纳秒。有些实现将4973436
中的2018-01-25T05:14:03.4973436
作为毫秒,导致436毫秒,并将4973000溢出到其他字段。这种情况发生在一些较旧的API级别上,较新的API会将毫秒级别截断/填充为3位数。
要解决此问题,您可以自行将输入截断为3个小数位,或使用较新的java.time
API(API 26+,可在ThreeTenABP库中使用后端)。
答案 1 :(得分:0)
当然可以使用java.time,即现代Java日期和时间API,也称为JSR-310:
public static CharSequence getRelativeTimeSpan(String timeStamp) {
LocalDateTime fromIso8601 = LocalDateTime.parse(timeStamp);
return DateUtils.getRelativeTimeSpanString(
fromIso8601.atOffset(ZoneOffset.UTC).toInstant().toEpochMilli(),
Instant.now().toEpochMilli(),
DateUtils.MINUTE_IN_MILLIS);
}
您不需要显式格式化程序。现代日期和时间类将ISO 8601解析为默认值。由于您的日期时间字符串是UTC格式,请使用atOffset(ZoneOffset.UTC)
(不是您的默认时区进行转换),这肯定是导致错误结果的原因。
要在ThreeTenABP上使用上述代码,请务必从org.threeten.bp
导入:
import org.threeten.bp.Instant;
import org.threeten.bp.LocalDateTime;
import org.threeten.bp.ZoneOffset;
java.time
。java.time
。java.time
向Java 6和7的后端(JST-310的ThreeTen)。