我一直在为此抨击我。我制作了一个小样本应用程序,以确保我没有看到任何东西,或者在稍后我没有抓到的时候没有操纵这些值。
问题在于,当我尝试使用日期格式解析字符串日期时,根据设备API级别,我得到两个非常不同的结果。
DateFormat utcFormat;
String utcDate = "2017-01-31 18:58:12.2334924Z";
utcFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSSS'Z'");
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
try{
conversion.setText(utcFormat.parse(utcDate).toString());
}
catch (ParseException e){
conversion.setText("exception encountered: " + e.getMessage());
}
以下是我的结果:
On Android 4.4.2 device: Tue Jan 31 14:37:06 EST 2017
On Android 6.0.1 device: Tue Jan 31 13:58:12 EST 2017
正如您所看到的,基于完全相同的输入,差异大约为40分钟。设备区域设置是相同的(虽然我也尝试过硬编码区域设置),设备上的设置时间相等。
我在这里做错了吗?
答案 0 :(得分:2)
符号S的一般问题是: java.util.Date
和java.text.SimpleDateFormat
的精度最多只能达到毫秒。不支持更高的精度。因此,指定多于3个模式符号SSS是没有意义的。
此外,我尝试做了一些研究,发现了这个:
pattern symbol table of official javadoc指定" S" as" Millisecond"。这意味着,值为" 2334924"输入中点后面的字面解析为毫秒的绝对计数,导致大约39分钟。这解释了在Android v4.4上测试的第一个示例的解析时间。
然而,发布的javadoc似乎在这个细节上略显过时。如果你谷歌搜索source code,那么你会在第71行找到:
<tr> <td>{@code S}</td>
<td>fractional seconds</td>
<td>(Number)</td>
<td>978</td> </tr>
但小数秒会导致对文本的完全不同的解释 &#34; 2334924&#34;,即233毫秒(加上忽略的更高精度部分)。这解释了您在Android v6上的第二个代码示例。我怀疑在两个Android版本之间的某个地方,谷歌决定在没有任何文档的情况下改变行为。我能找到的最好的东西似乎是issue 78859,这可能与行为的这种变化有关。
ICU4J似乎越来越多地集成到较新的Android版本中,也声明了符号&#34; S&#34;作为小数秒。
解决方法和解决方案:
避免使用3个以上的图案符号S.而是使用(忽略更高精度的部分):
String input = "2017-01-31 18:58:12.2334924Z";
int dot = input.indexOf(".");
String trimmed = input.substring(0, dot + 4) + "Z"; // 2017-01-31 18:58:12.233Z
DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS'Z'");
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
java.util.Date d = utcFormat.parse(trimmed);