问题描述
这部分代码将输入从“ 2020年1月1日”转换为“ 01/01”。整个代码在配备Pie的Android设备以及配备Q和R的AVD设备中均能完美运行。当我尝试在带有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:无法解析的日期:“星期四11月5日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,但是结果相同
解决方法
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,这是现代类的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
我以这种方式解决了,不再使用SimpleDateFormat:
while (a < 12){
if(dato.contains(mese[a])){
String dateInString = dato;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d,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++;
}