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

Retrofit2.3.0中如何解析响应头未知格式的UTC日期

解析响应头中格式不固定的UTC日期字符串为Date对象

问题描述

我正在处理OkHttp的响应回调,需要从PHP服务器返回的响应头date字段获取UTC日期,但这个日期字符串的格式不固定,不确定该用哪种格式解析。以下是我的代码片段,需要补全日期解析的部分:

@Override public void onResponse(@NonNull Call<ConfigurationData> call, @NonNull Response<ConfigurationData> response) { 
    CacheDb db = new CacheDb(this); 
    int statusCode = response.code(); 
    ConfigurationData configData = response.body(); 
    String dateString = response.headers().get("date");//date String 
    Date date = ..............//***我需要这部分代码*** 
    switch (statusCode){ 
        case 200: 
            db.setClass("config", configData); 
            startActivity(new Intent(SplashActivity.this, HomePage.class)); 
            handler.removeCallbacks(null); 
            handler.removeCallbacksAndMessages(null); 
            SplashActivity.this.finish(); 
            finish(); 
            break; 
        default: 
            setDialog(); 
            break; 
    } 
} 
@Override public void onFailure(@NonNull Call<ConfigurationData> call, @NonNull Throwable t) { 
    setDialog(); 
} 

解决方案

其实HTTP协议的Date响应头是有明确规范的,主要支持三种格式:RFC 1123、RFC 850和ANSI C的asctime格式。我们可以通过依次尝试这些格式来解析,不管服务器返回哪种标准格式都能处理。下面给你两种适配不同Java/Android版本的方案:

方案1:Java 8+ / Android API 26+ (推荐)

使用Java 8引入的java.time包,这是更现代、线程安全的日期处理方式:

import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.Locale;

// 替换你代码中需要补全的部分
String dateString = response.headers().get("date");//date String
Date date = null;
if (dateString != null) {
    // 定义所有HTTP标准支持的日期格式,额外兼容ISO8601格式以防万一
    DateTimeFormatter[] formatters = {
        DateTimeFormatter.RFC_1123_DATE_TIME,
        DateTimeFormatter.RFC_1036_DATE_TIME, // 对应RFC 850
        DateTimeFormatter.ISO_INSTANT
    };
    
    for (DateTimeFormatter formatter : formatters) {
        try {
            // 强制使用US locale,避免系统本地化影响英文日期解析
            Instant instant = formatter.withLocale(Locale.US).parse(dateString, Instant::from);
            date = Date.from(instant);
            break; // 解析成功就跳出循环
        } catch (DateTimeParseException e) {
            // 格式不匹配,尝试下一种
            continue;
        }
    }
}

// 容错处理:如果所有格式都解析失败,date会是null,这里可以根据需求处理
if (date == null) {
    // 比如设置默认日期,或者记录日志
}

方案2:兼容Java 7 / Android API <26

如果需要兼容旧版本,可以用SimpleDateFormat来实现,注意它是非线程安全的,所以要在循环里每次创建实例:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

// 替换你代码中需要补全的部分
String dateString = response.headers().get("date");//date String
Date date = null;
if (dateString != null) {
    // 定义HTTP标准支持的三种日期格式
    String[] dateFormats = {
        "EEE, dd MMM yyyy HH:mm:ss zzz", // RFC 1123
        "EEEE, dd-MMM-yy HH:mm:ss zzz", // RFC 850
        "EEE MMM d HH:mm:ss yyyy"       // ANSI C asctime
    };
    
    for (String format : dateFormats) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);
            sdf.setLenient(false); // 严格解析,避免错误格式被强制兼容
            date = sdf.parse(dateString);
            break; // 解析成功跳出循环
        } catch (ParseException e) {
            // 尝试下一种格式
            continue;
        }
    }
}

// 容错处理
if (date == null) {
    // 处理解析失败的情况
}

说明

  • 强制使用Locale.US是因为日期字符串里的星期、月份都是英文缩写/全称,避免系统用其他语言的本地化规则导致解析失败。
  • 设置setLenient(false)(针对SimpleDateFormat)可以避免一些不符合规范的日期被错误解析,保证解析的准确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:26:53