Java 解析格式略有不同的日期/时间字符串的最有效方法

Java 解析格式略有不同的日期/时间字符串的最有效方法,java,android,json,datetime,Java,Android,Json,Datetime,我正在解析来自服务器的JSON,其中使用了一些类似但不相同的日期格式,有些格式如下: 2013-12-13T09:59:59Z 我可以使用 SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") SimpleDateFormat("yyyy/MM/dd HH:mm:ss ZZZ") 而其他人看起来像 2013/11/14 11:00:14 -0500 我可以使用 SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")

我正在解析来自服务器的JSON,其中使用了一些类似但不相同的日期格式,有些格式如下:

2013-12-13T09:59:59Z
我可以使用

SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
SimpleDateFormat("yyyy/MM/dd HH:mm:ss ZZZ")
而其他人看起来像

2013/11/14 11:00:14 -0500
我可以使用

SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
SimpleDateFormat("yyyy/MM/dd HH:mm:ss ZZZ")

有没有更通用的方法?如果有一个标准的服务器端方法,显然会更好,但我无法改变这一点。

如果您在格式方面只有两种变体,则可以使用以下代码:

SimpleDateFormat iso = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXX");
SimpleDateFormat other = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss XX");

String input = "2013/11/14 11:00:14 -0500";
Date result;

if (input.indexOf('/') != -1) { // or: input.charAt(4) == '/'
  result = other.parse(input);
} else {
  result = iso.parse(input);
}
注意:对于Android,您必须使用ZZ而不是XX,但我不确定Android上的ZZ是否能够正确解析ISO输入中的Z符号。如有疑问(测试!),您必须以特定方式处理另一种格式变体(使用类似于
input.endsWith(“Z”)
)的方法)。您可以使用此方法。 您的日期格式不应含糊不清,例如,“07/08/2013”可以是“dd/MM/YYYY”或“MM/dd/YYYY”


我觉得最好保留数组中可能出现的所有日期格式,然后通过使用foreach循环,您可以检查哪种格式最适合,并以这种方式对其进行解析。 我使用以下代码来实现它

public static String postedTimeFormat(String inPostedTime) {

        String[] formats = {
                "EEE MMM dd HH:mm:ss Z yyyy", "yyyy-MM-dd'T'HH:mm:ss",
                "yyyy-MM-dd'T'HH:mm:ss'Z'", "yyyy-MM-dd'T'HH:mm:ssZ", 
                "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "yyyy-MM-dd'T'HH:mm:ss.SSSZ", 
                "yyyy-MM-dd HH:mm:ss", "MM/dd/yyyy HH:mm:ss", 
                "MM/dd/yyyy'T'HH:mm:ss.SSS'Z'", "MM/dd/yyyy'T'HH:mm:ss.SSSZ", 
                "MM/dd/yyyy'T'HH:mm:ss.SSS", "MM/dd/yyyy'T'HH:mm:ssZ", 
                "MM/dd/yyyy'T'HH:mm:ss", "yyyy:MM:dd HH:mm:ss",
                "yyyyMMdd", "yyyy-MM-dd" ,
                "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mmZ",
        "yyyy-MM-dd HH:mm:ss.SSSZ"};

        if (inPostedTime != null) {
            for (String format : formats) {
                SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);
                try {
                    sdf.parse(inPostedTime);
                    return format;

                } catch (ParseException e) {
                }
            }
        }
        return null;
    }

通过这样做,将日期标准化为一种格式

  • 将所有
    /
    字符替换为
    -
  • 将第一个空格字符替换为
    T
  • 用空字符串替换任何后续空格字符
完成后,您应该能够使用

"yyyy-MM-dd'T'HH:mm:ssX"
如果您在Android代码中执行此操作,则还需要一个步骤:

  • 将任何Z替换为+00:00
您需要使用

"yyyy-MM-dd'T'HH:mm:ssZ"

“通用”指的是能猜出格式是什么的东西?我怀疑。猜测日期格式容易出错。例如,“07/08/2014”的格式是什么?服务器应该以固定格式发送,也可以随附格式发送。我不是在寻找一种完全通用的格式获取方法,我正在寻找一种更好的方法来处理上述两种格式,其中一种使用“T”,另一种使用空格来分隔日期和时间,其中一个使用Z表示“祖鲁时间”,另一个明确指定了时区。我认为使用
“yyyy-MM-dd'T'HH:MM:ss'Z'
来解析
2013-12-13T09:59:59Z
是不正确的。“代码”>Z < /代码>在时间之后表示这一时间是UTC,但是您的日期格式忽略了<代码> z <代码>,并根据默认的区域设置给了您一个日期。我确实考虑了这种方法,它肯定比调用一组不同的DateFormats更好。但我希望会有一些看起来更整洁的东西。@JonathanCaryl是的,我的目标是尽量避免过度解析和捕捉解析错误。不幸的是,你运气不好,有不同的格式。SimpleDataFormat不支持开箱即用的多种格式解析,我怀疑是否有一种可能的开箱即用的解决方案在内部能更好地进行解析。因为解析日期不是最快的操作,所以这可能会非常慢。它也没有利用我试图解析的两种格式非常相似的事实:上面的dateFormats可能完全不同。同意。我错过了“高效”部分,更多地关注所有格式的通用代码。这会很慢,但是在第一次解析json时只调用一次函数,就像在实用程序类中那样,而不是每次都能得到好的结果。Jonathan,你怎么会认为会很慢?我不明白为什么会这么慢。我看错了代码,以为它在尝试@sanghrash的答案中的所有格式。我想这是找到合适格式的合理方法。我认为@Sanghrash的答案与此相当。你在回答中说“这可能会很慢”,但我看不到任何证据。@JonathanCaryl@DavidWallace该代码速度较慢,因为它通过捕获例外来工作(如果第一次尝试的格式不合适)。重用代码“> PARSETPONT <代码>代替TIGET catch可能会提高性能,但是,FWW,我认为Android中的bug是他们已经制造了一个类,叫做代码> java .Text。SimuleDealFrase,这与标准JDK中提供的<代码> java .Text。SimuleDead格式< /C> >不同。他们应该称它为android.text.SimpleDataFormat或类似的东西。或者更好的方法是,用Android打包真正的
java.text.SimpleDataFormat
。不,这不是一个bug,因为:Android!=JAVA如果实际的实现行为与规范相矛盾,那么您就有一个bug。这里我们有Android规范,所以从谷歌的角度来看,一切都是正确的,尽管他们确实模仿java类名(恼人的Oracle/Sun)。