You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 08:31:18