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

Android 基于指定时区判断营业时间是否超时 日期解析报错解决

问题解决方法

报错直接原因

你遇到的java.text.ParseException: Unparseable date: "10:00AM"错误核心是时间格式串定义错误:
你代码中写的格式串是"hh:mm\\aa",多余添加了转义反斜杠,导致解析器会强制匹配输入串中的\a字符,而你传入的时间里不存在该字符,直接解析失败。
另外还有两个隐藏的解析失败风险:

  • 用了Locale.getDefault(),如果设备本地语言不是英语,AM/PM的本地化标记和你传入的英文AM/PM不匹配,也会解析失败,需要固定使用Locale.US。
  • 第一版代码中tzs变量未初始化就调用sdf.setTimeZone(tzs),会直接抛出空指针异常。

其他隐藏逻辑问题

你当前的实现还有跨天营业时间判断错误的问题:比如调用示例中timeElapse("10:00AM", "01:00AM", "Asia/Kuala_Lumpur")属于次日凌晨关门的跨天营业场景,直接比较两个时分的时间戳会判定01:00AM早于10:00AM,逻辑完全错误。

修复实现

方案1:兼容Android 所有版本(基于SimpleDateFormat)

public void timeElapse(String businessStart, String businessEnd, String timeZoneId){
    // 修正格式串,固定Locale匹配英文AM/PM
    SimpleDateFormat sdf = new SimpleDateFormat("hh:mm a", Locale.US);
    try {
        TimeZone targetTz = TimeZone.getTimeZone(timeZoneId);
        sdf.setTimeZone(targetTz);

        // 解析营业时间为1970年基准的时间戳
        long startTs = sdf.parse(businessStart).getTime();
        long endTs = sdf.parse(businessEnd).getTime();

        // 获取当前指定时区的时分,转换为同基准的时间戳
        Calendar nowCal = Calendar.getInstance(targetTz);
        Calendar currentCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
        currentCal.set(1970, Calendar.JANUARY, 1, nowCal.get(Calendar.HOUR_OF_DAY), nowCal.get(Calendar.MINUTE), 0);
        currentCal.set(Calendar.MILLISECOND, 0);
        long currentTs = currentCal.getTimeInMillis();

        // 处理跨天营业逻辑
        if (endTs < startTs) {
            endTs += 24 * 60 * 60 * 1000;
            if (currentTs < startTs) {
                currentTs += 24 * 60 * 60 * 1000;
            }
        }

        // 输出结果
        if(currentTs > endTs){
            Log.e("timeElapse", "已过营业时间");
        } else if (currentTs < startTs) {
            Log.e("timeElapse", "尚未营业");
        } else {
            Log.e("timeElapse", "营业中");
        }
    } catch (ParseException e) {
        Log.e("timeElapse", "时间格式解析错误", e);
    }
}

方案2:推荐方案(Android 8.0及以上,基于java.time)

java.time是Android官方推荐的时间处理库,避免了SimpleDateFormat的线程安全、格式解析等各种历史坑,代码更简洁:

public void timeElapse(String businessStart, String businessEnd, String timeZoneId){
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm a", Locale.US);
    ZoneId targetZone = ZoneId.of(timeZoneId);
    // 解析营业时间
    LocalTime startTime = LocalTime.parse(businessStart, formatter);
    LocalTime endTime = LocalTime.parse(businessEnd, formatter);
    // 获取当前指定时区的时间
    LocalTime now = LocalTime.now(targetZone);

    if (endTime.isAfter(startTime)) {
        // 非跨天营业
        if (now.isAfter(endTime)) {
            Log.e("timeElapse", "已过营业时间");
        } else if (now.isBefore(startTime)) {
            Log.e("timeElapse", "尚未营业");
        } else {
            Log.e("timeElapse", "营业中");
        }
    } else {
        // 跨天营业
        if (now.isAfter(startTime) || now.isBefore(endTime)) {
            Log.e("timeElapse", "营业中");
        } else {
            Log.e("timeElapse", "已过营业时间");
        }
    }
}

如果需要兼容Android 8.0以下版本,引入ThreeTenABP适配库即可使用java.time相关API。

内容的提问来源于stack exchange,提问作者Peter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 18:00:00