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。该字符串包含英文的ThuNov,因此如果您的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测试代码

android studio虚拟机怎么安装apk

使用错误 Java 源的 Android Studio 外部库

使用 maven 存储库将 java 库添加到 Android Studio 项目

Android studio 1.2 Java 7 无法创建窗口纹理

如何建立与 Android studio和 gradle android 库