从SharedPreferences读取日期转换异常:显示12/31/1969问题排查
问题描述
我尝试将SharedPreferences中存储的MMddyyyy格式的dateDue整数转换为MM/dd/yyyy格式,但执行以下代码后,返回的日期始终是12/31/1969,而非预期的12/30/2022。请问这是什么原因?是否与Calendar相关?
代码如下:
String myFormat = "MM/dd/yyyy"; SimpleDateFormat format = new SimpleDateFormat(myFormat); SharedPreferences settings = context.getApplicationContext().getSharedPreferences(name, 0); Integer dateDue = Integer.valueOf(settings.getInt("dateDue", 0)); format = new SimpleDateFormat(myFormat); String date = format.format(dateDue); if (Integer.valueOf(String.valueOf(dueAmount)) > 0) { holder.getDateDue.setText(String.valueOf(date)); }
原因分析
核心错误在于对SimpleDateFormat.format()方法的理解偏差:该方法接收的参数是时间戳(从1970-01-01 00:00:00 UTC开始计算的毫秒数),但你传入的是MMddyyyy格式的整数(比如20221230)。这个数值对应的时间戳仅相当于1970年1月1日之后的约20221230毫秒(约234天),再结合本地时区的偏移(比如西五区时区下,UTC时间1970-01-01 05:37对应本地时间1969-12-31 23:37),最终显示为12/31/1969。这个问题和Calendar无关。
解决方案
有两种可靠的处理方式:
方式一:直接字符串拼接(简单高效)
将存储的整数转为8位字符串后,手动插入分隔符:
SharedPreferences settings = context.getApplicationContext().getSharedPreferences(name, 0); int dateDue = settings.getInt("dateDue", 0); // 转为8位字符串,不足位数时补前导0 String dateStr = String.format("%08d", dateDue); // 拼接成MM/dd/yyyy格式 String formattedDate = dateStr.substring(0,2) + "/" + dateStr.substring(2,4) + "/" + dateStr.substring(4); if (dueAmount > 0) { holder.getDateDue.setText(formattedDate); }
方式二:日期解析再格式化(规范严谨)
先用SimpleDateFormat将MMddyyyy格式的字符串解析为Date对象,再格式化为目标格式:
SharedPreferences settings = context.getApplicationContext().getSharedPreferences(name, 0); int dateDue = settings.getInt("dateDue", 0); String dateStr = String.format("%08d", dateDue); // 定义输入格式(存储的MMddyyyy)和输出格式 SimpleDateFormat inputFormat = new SimpleDateFormat("MMddyyyy"); SimpleDateFormat outputFormat = new SimpleDateFormat("MM/dd/yyyy"); try { Date date = inputFormat.parse(dateStr); String formattedDate = outputFormat.format(date); if (dueAmount > 0) { holder.getDateDue.setText(formattedDate); } } catch (ParseException e) { // 处理日期解析异常,比如存储的数值格式错误 e.printStackTrace(); }
注意事项(Java 8+推荐写法)
SimpleDateFormat是线程不安全的,若项目基于Java 8及以上版本,建议使用线程安全的DateTimeFormatter:
SharedPreferences settings = context.getApplicationContext().getSharedPreferences(name, 0); int dateDue = settings.getInt("dateDue", 0); String dateStr = String.format("%08d", dateDue); DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("MMddyyyy"); DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy"); try { LocalDate localDate = LocalDate.parse(dateStr, inputFormatter); String formattedDate = outputFormatter.format(localDate); if (dueAmount > 0) { holder.getDateDue.setText(formattedDate); } } catch (DateTimeParseException e) { e.printStackTrace(); }
内容的提问来源于stack exchange,提问作者user20791491
相关产品推荐
相关产品推荐

