在Java中应使用哪种模式来解析RFC 3339日期时间字符串 [英] What pattern should be used to parse RFC 3339 datetime strings in java

查看:1704
本文介绍了在Java中应使用哪种模式来解析RFC 3339日期时间字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎是一个常见问题,答案很多.在您回答之前,我同时使用了 joda-time

This seems to be a common question with many different answers. Before you answer, I have used both joda-time and atomdate and they work great. My interest here is not what library to use but instead a clarification on how RFC pattern should be defined in java.

根据我的理解和此答案 RFC 3339是ISO 8601的配置文件.PHP 这个答案中也有提及) ):

From my understanding and this answer RFC 3339 is a profile of ISO 8601. PHP clearly defines the RFC 3339 datetime pattern to be Y-m-d\TH:i:sP. If we were to transfer this definition to java 7 (to my knowledge) we would end up with this (which is also referred to in this answer):

// example "2005-08-15T15:52:01+00:00"
pattern = "yyyy-MM-dd'T'HH:mm:ssXXX";

但是,有几个堆栈溢出答案,例如指向其中一个(或两者)是正确的模式适用于RFC 3339

However, several stack overflow answers like this one point to one of these (or both) as being the correct pattern for RFC 3339

// example "2016-11-01T20:44:39Z"
pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'";

// example "1937-01-01T12:00:27.87Z"
pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

为了使事情更加复杂,正式的 RFC 3339 文档列出了以下所有示例(添加了我认为是它们相应的模式):

To further complicate matters the official RFC 3339 documentation lists all of these following examples (I've added in what I think would be their corresponding patterns):

// 1996-12-19T16:39:57-08:00
pattern = "yyyy-MM-dd'T'HH:mm:ssXXX";

// 1990-12-31T23:59:60Z
pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'";

// 1990-12-31T15:59:60-08:00
pattern = "yyyy-MM-dd'T'HH:mm:ssXXX";

// 1937-01-01T12:00:27.87+00:20
pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";

旁注::Android不支持时区的XXX模式,但您可以根据

Side note: Android does not support the XXX pattern for timezones but you can use ZZZZZ instead as per this answer.

我认为让我感到困惑的部分原因是,我一直看到RFC 822和RFC 2822分别由一个模式专门提及,因此我认为RFC 3339也可以归结为一个模式匹配:

I think part of what's confusing me is I've always seen RFC 822 and RFC 2822 specifically referred to by one pattern each, so I assumed RFC 3339 could also be boiled down to a single pattern match:

static String RFC_822 = "EEE, dd MMM yy HH:mm:ss zzz";
static String RFC_2822 = "EEE, dd MMM yyyy HH:mm:ss zzz";


我的结论

与php不同,RFC 3339不能仅使用单个匹配表达式在java中表示.相反,所有这些都是有效的RFC 3339模式,并且在通过SimpleDateFormat解析日期时间字符串时必须进行检查:


My Conclusion

Unlike in php, RFC 3339 cannot be represented in java using only a single matching expression. Instead all of these are valid RFC 3339 patterns and must be checked when parsing a datetime String via SimpleDateFormat:

static String[] RFC_3339_VARIANTS = {
        "yyyy-MM-dd'T'HH:mm:ss'Z'",
        "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",
        "yyyy-MM-dd'T'HH:mm:ssXXX",
        "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"
};


更新

要使事情复杂化,SimpleDateFormat似乎不能正确处理'Z'时区文字.它不是默认采用UTC,而是默认为PST或您的本地时间(我不确定是哪个时间).这意味着您可能需要用+00:00手动替换'Z'文字以更正此行为?


Update

To complicate matters SimpleDateFormat does not seem to correctly handle the 'Z' timezone literal. Instead of assuming UTC as it should, it defaults to either PST or your local time (I'm not sure which). That means you might need to manually replace 'Z' literals with +00:00 to correct this behaviour?

根据建议,我创建了一个实用程序类Gist,其中包括我当前正在运行的代码.它应在Android上运行,并且与Java 7+兼容.请随时提出任何问题或发表评论.如果有足够的兴趣,我可以将其移至Github,以便其他人可以贡献力量:

As suggested I have created a utility class Gist which includes my currently running code. This should run on Android and also be compatible with Java 7+. Please feel free to ask any questions or leave comments. If there's enough interest I can move it over to Github so other people can contribute:

https://gist.github.com/oseparovic/d9ee771927ac5f3aefc8ba0b99c0cf38

我是否正确理解了这一点?还是我完全不了解?非常感谢你们对如何在Java 7中解析RFC 3339字符串所做的任何澄清.

Am I understanding this correctly or am I completely off? I would really appreciate any clarification you guys can offer about how to parse RFC 3339 strings in java 7.

推荐答案

您基本上回答了自己的问题,只是即使您的要旨在所有情况下都不正确...也就是说,它需要的模式比您拥有的两种模式还要多(例如处理纳秒).

You basically almost answered your own question except that even your gist is not correct for all cases... that is it requires even more patterns than the two you have (e.g. to deal with nano seconds).

这就是为什么Joda和Java 8具有用于ISO 8601(超集)的特殊解析器的原因.

And this is why Joda and Java 8 have special parsers for ISO 8601 (a superset).

我知道您不需要引用其他库,但对于使用Java 8的其他库,或者想要显式限制为RFC 3339的库(我相信joda iso解析器将采用比rfc 3339更多的格式),库: https://github.com/ethlo/itu

I know you don't need references to other libraries but for others that are using Java 8 and or want to explicitly limit to RFC 3339 (the joda iso parsers I believe will take even more formats than rfc 3339) there is this library: https://github.com/ethlo/itu

这篇关于在Java中应使用哪种模式来解析RFC 3339日期时间字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆