Java Android Studio - 使用 Android 10 的物理设备上出现无法解析的日期错误
Posted
技术标签:
【中文标题】Java Android Studio - 使用 Android 10 的物理设备上出现无法解析的日期错误【英文标题】:Java Android Studio - Unparseable date error on phisycal device with Android 10 【发布时间】:2021-02-18 07:35:09 【问题描述】:这部分代码将“2020 年 1 月 1 日”等输入转换为“01/01”。整个代码在 android 到 Pie 的设备上完美运行,在 AVD 中也可以在 Q 和 R 的设备上完美运行。当我尝试在具有 Android Q 的物理 Android 设备上运行它时,它无法运行(我尝试了 2 种不同的设备,即 Mi Note 10 和 OnePlus 6T)。我对调试器进行了检查,一旦进入 IF 循环,我就发现了这个错误(我认为在指令中:@SuppressLint("SimpleDateFormat") SimpleDateFormat dt = new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy");"
W/System.err:java.text.ParseException:无法解析的日期:“Thu Nov 05 00:00:00 GMT+01:00 2020”
String[] mese = new String[] "January","February","March","April","May","June","July","August","September","October","November","December";
int a= 0 ;
while (a < 12)
if(dato.contains(mese[a]))
System.out.println("Test 3");
DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
Date date = format.parse(dato);
@SuppressLint("SimpleDateFormat") SimpleDateFormat dt = new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy");
Date date2 = dt.parse(String.valueOf(date));
@SuppressLint("SimpleDateFormat") SimpleDateFormat dt1 = new SimpleDateFormat("dd/MM");
assert date2 != null;
dato = dato.replaceAll(dato,dt1.format(date2));
a++;
我的模式错了?我试过 EEE MMM dd HH:mm:ss zzz yyyy 和 EEE MMM dd HH:mm:ss zzzz yyyy 但结果相同
【问题讨论】:
顺便考虑扔掉长期过时且臭名昭著的麻烦SimpleDateFormat
和朋友。看看您是否可以使用desugaring 或将ThreeTenABP 添加到您的Android 项目中,以便使用现代Java 日期和时间API 的java.time。使用起来感觉好多了。
我会尽力做到的。顺便说一句,仍然不知道我的问题:/
作为反馈。我使用新的 Java.time 完全转换了代码,这解决了我在物理设备上与 Android Q(和 R)的兼容性问题。看来他们不喜欢 SimpleDataFormat
很高兴听到!如果您能将其发布为您自己问题的答案,以供其他读者学习,我会很高兴。
【参考方案1】:
我以这种方式解决了不再使用 SimpleDateFormat:
while (a < 12)
if(dato.contains(mese[a]))
String dateInString = dato;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
LocalDate dateTime = LocalDate.parse(dateInString, formatter);
DateTimeFormatter f2 = DateTimeFormatter.ofPattern("dd/MM");
String newDate = dateTime.format(f2);
dato = dato.replaceAll(dato,newDate);
a++;
【讨论】:
【参考方案2】:java.time 和脱糖或 ThreeTenABP
我建议您使用现代 Java 日期和时间 API java.time 进行日期工作。
java.time 格式化程序是线程安全的,因此我们通常更喜欢将它们声明为静态:
private static final DateTimeFormatter sourceFormatter
= DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
private static final DateTimeFormatter targetFormatter
= DateTimeFormatter.ofPattern("dd/MM");
现在您的转换如下所示:
String dato = "November 5, 2020";
LocalDate date = LocalDate.parse(dato, sourceFormatter);
dato = date.format(targetFormatter);
System.out.println(dato);
输出:
05/11
你的代码出了什么问题?
在我看来,您正在以一种比需要更复杂的方式进行格式转换。与其检查字符串中是否有月份名称,不如尝试解析它?如果没有,我的代码会抛出一个DateTimeParseException
,然后您可以捕获并处理适合您情况的方式。您的代码将您的String
转换为Date
再转换为String
再转换为Date
并再次转换为String
。我不明白原因。您还使用了 SimpleDateFOrmat
类。它是出了名的麻烦和过时。第二次从String
解析到Date
失败了,我敢打赌我知道原因:对于你的第一个SimpleDateFormat
,你记得指定Locale.ENGLISH
,但是你忘记了你的第二个SimpleDateFormat
。该字符串包含英文的Thu
和Nov
,因此如果您的Android Q 和R 设备具有不同的语言设置,这说明。最后为了您的目的,这一行:
dato = dato.replaceAll(dato,dt1.format(date2));
和更简单的一样:
dato = dt1.format(date2);
问题:java.time 不需要 Android API 26 级吗?
java.time 在较旧和较新的 Android 设备上都能很好地工作。它只需要至少 Java 6。
在 Java 8 及更高版本以及更新的 Android 设备(从 API 级别 26 起)中,现代 API 是内置的。 在非 Android Java 6 和 7 中,获取 ThreeTen Backport,这是现代类的后向端口(对于 JSR 310,ThreeTen;请参阅底部的链接)。 在较旧的 Android 上,请使用脱糖或 Android 版本的 ThreeTen Backport。后者称为 ThreeTenABP。使用 ThreeTenABP 时,请确保从org.threeten.bp
导入日期和时间类以及子包。
链接
Oracle tutorial: Date Time 解释如何使用 java.time。 Java Specification Request (JSR) 310,其中首次描述了java.time
。
ThreeTen Backport project,java.time
的反向移植到 Java 6 和 7(JSR-310 的 ThreeTen)。
Java 8+ APIs available through desugaring
ThreeTenABP,Android 版 ThreeTen Backport
Question: How to use ThreeTenABP in Android Project,解释得很透彻。
类似问题:Java - Unparseable date
【讨论】:
以上是关于Java Android Studio - 使用 Android 10 的物理设备上出现无法解析的日期错误的主要内容,如果未能解决你的问题,请参考以下文章
[Java] 使用Android Studio编写Java测试代码
使用错误 Java 源的 Android Studio 外部库
使用 maven 存储库将 java 库添加到 Android Studio 项目