java解析出rfc的facility,在Java中应使用哪种模式来解析RFC 3339日期时间字符串

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.

Research

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";

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'";

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";

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

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";

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"

};

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

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:

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).

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值