在JAVA中解析RFC 2822日期

发布于 2024-08-25 08:57:00 字数 232 浏览 7 评论 0原文

我需要解析 Java 中日期的 RFC 2822 字符串表示形式。示例字符串如下:

2010 年 3 月 13 日星期六 11:29:05 -0800

它看起来很糟糕,所以我想确保我做的一切都是正确的,并且稍后会遇到奇怪的问题,因为日期被解释为错误,无论是通过 AM-PM/军事时间问题, UTC 时间问题、我没有预料到的问题等等...

谢谢!

I need to parse an RFC 2822 string representation of a date in Java. An example string is here:

Sat, 13 Mar 2010 11:29:05 -0800

It looks pretty nasty so I wanted to make sure I was doing everything right and would run into weird problems later with the date being interpreted wrong either through AM-PM/Military time problems, UTC time problems, problems I don't anticipate, etc...

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

黑白记忆 2024-09-01 08:57:00

这是执行您要求的快速代码(使用 简单日期格式

String rfcDate = "Sat, 13 Mar 2010 11:29:05 -0800";
String pattern = "EEE, dd MMM yyyy HH:mm:ss Z";
SimpleDateFormat format = new SimpleDateFormat(pattern);
Date javaDate = format.parse(rfcDate);

//Done.

PS。我在这里没有处理异常和并发(因为 SimpleDateFormat 在解析日期时不同步)。

This is quick code that does what you ask (using SimpleDateFormat)

String rfcDate = "Sat, 13 Mar 2010 11:29:05 -0800";
String pattern = "EEE, dd MMM yyyy HH:mm:ss Z";
SimpleDateFormat format = new SimpleDateFormat(pattern);
Date javaDate = format.parse(rfcDate);

//Done.

PS. I've not dealt with exceptions and concurrency here (as SimpleDateFormat is not synchronized when parsing date).

过期情话 2024-09-01 08:57:00

如果您的应用程序使用英语以外的其他语言,您可能需要使用备用 SimpleDateFormat 构造函数强制日期解析/格式化的区域设置:

String pattern = "EEE, dd MMM yyyy HH:mm:ss Z";
SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.ENGLISH);

If your application is using another language than English, you may want to force the locale for the date parsing/formatting by using an alternate SimpleDateFormat constructor:

String pattern = "EEE, dd MMM yyyy HH:mm:ss Z";
SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.ENGLISH);
温柔一刀 2024-09-01 08:57:00

请记住,[星期几“,”] 在 RFC-2822 中是可选的,因此建议的示例并未涵盖所有 RFC-2822 日期格式。此外,RFC-822 日期类型允许许多不同的时区符号(obs-zone),“Z”格式说明符未涵盖这些符号。

我想除了寻找“,”和“-|+”来确定使用哪种模式之外,没有简单的方法。

Please keep in mind that the [day-of-week ","] is optional in RFC-2822, hence the suggested examples are not covering all RFC-2822 date formats. Additional, the RFC-822 date type allowed many different time zone notations(obs-zone), which are not covered by the "Z" format specifier.

I guess there is no easy way out, other than looking for "," and "-|+" to determine which pattern to use.

苯莒 2024-09-01 08:57:00

DateTimeFormatter.RFC_1123_DATE_TIME

自 Java 8 以来,实现了新的日期时间类:java.time.ZonedDateTimejava.time.LocalDateTimeZonedDateTime 支持几乎开箱即用的 RFC 字符串解析:

String rfcDate = "Tue, 4 Dec 2018 17:37:31 +0100 (CET)";  
if (rfcDate.matches(".*[ ]\\(\\w\\w\\w\\)$")) {
    //Brackets with time zone are added sometimes, for example by JavaMail
    //This must be removed before parsing
    //from: "Tue, 4 Dec 2018 17:37:31 +0100 (CET)"
    //  to: "Tue, 4 Dec 2018 17:37:31 +0100"
    rfcDate = rfcDate.substring(0, rfcDate.length() - 6);
}

//and now parsing... 
DateTimeFormatter dateFormat = DateTimeFormatter.RFC_1123_DATE_TIME;
try {
    ZonedDateTime zoned = ZonedDateTime.parse(rfcDate, dateFormat);
    LocalDateTime local = zoned.toLocalDateTime();        
} catch (DateTimeParseException e) { ... }

DateTimeFormatter.RFC_1123_DATE_TIME

Since Java 8 new datetime classes were implemented: java.time.ZonedDateTime and java.time.LocalDateTime. ZonedDateTime supports the parsing of RFC strings nearly out of the box:

String rfcDate = "Tue, 4 Dec 2018 17:37:31 +0100 (CET)";  
if (rfcDate.matches(".*[ ]\\(\\w\\w\\w\\)
quot;)) {
    //Brackets with time zone are added sometimes, for example by JavaMail
    //This must be removed before parsing
    //from: "Tue, 4 Dec 2018 17:37:31 +0100 (CET)"
    //  to: "Tue, 4 Dec 2018 17:37:31 +0100"
    rfcDate = rfcDate.substring(0, rfcDate.length() - 6);
}

//and now parsing... 
DateTimeFormatter dateFormat = DateTimeFormatter.RFC_1123_DATE_TIME;
try {
    ZonedDateTime zoned = ZonedDateTime.parse(rfcDate, dateFormat);
    LocalDateTime local = zoned.toLocalDateTime();        
} catch (DateTimeParseException e) { ... }
秋叶绚丽 2024-09-01 08:57:00

有一个 javax.mail 类执行 RFC-2822 日期的解析:

javax.mail.internet.MailDateFormat

包括可选和过时的格式。

只需这样做:

new javax.mail.internet.MailDateFormat().parse("Sat, 13 Mar 2010 11:29:00 -0800")
new javax.mail.internet.MailDateFormat().parse("13 Mar 2010 11:29:00 -0800")
new javax.mail.internet.MailDateFormat().parse("13 Mar 2010 11:29 -0800")

它将正确解析这些有效的 RFC-2822 日期

对于其他旧的 DateFormatters,MailDateFormat 类不是线程安全的。

There is a javax.mail class that perform the parsing of RFC-2822 dates :

javax.mail.internet.MailDateFormat

including the optional and obsolete formats.

Just do :

new javax.mail.internet.MailDateFormat().parse("Sat, 13 Mar 2010 11:29:00 -0800")
new javax.mail.internet.MailDateFormat().parse("13 Mar 2010 11:29:00 -0800")
new javax.mail.internet.MailDateFormat().parse("13 Mar 2010 11:29 -0800")

It will correctly parse these valid RFC-2822 dates

As for other old DateFormatters, the MailDateFormat class is not thread safe.

沦落红尘 2024-09-01 08:57:00

RFC 2822 日期时间字符串包含时区偏移量,例如给定字符串 Sat, 13 Mar 2010 11:29:05 -0800 与 UTC 的时区偏移量为 -08:00 小时,即等效日期时间UTC 时间可以通过在2010 年 3 月 13 日星期六 11:29:05 基础上加上 8 个小时来获得。

java.time

现代日期时间 API API 有 OffsetDateTime 来表示带有时区偏移的日期时间。

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

class Main {
    public static void main(String[] args) {
        String strRFC2822DateTimeStr = "Sat, 13 Mar 2010 11:29:05 -0800";

        OffsetDateTime odt = OffsetDateTime.parse(strRFC2822DateTimeStr, DateTimeFormatter.RFC_1123_DATE_TIME);
        System.out.println(odt);

        // Alternatively: using a custom DateTimeFormatter
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("EEE, dd MMM uuuu HH:mm:ss XX", Locale.ENGLISH);
        System.out.println(OffsetDateTime.parse(strRFC2822DateTimeStr, parser));

        // In case you need the equivalent date-time at UTC
        OffsetDateTime odtUtc = odt.withOffsetSameInstant(ZoneOffset.UTC);
        System.out.println(odtUtc);
    }
}

输出

2010-03-13T11:29:05-08:00
2010-03-13T11:29:05-08:00
2010-03-13T19:29:05Z

跟踪:日期时间

一些有用的链接

  1. 切勿在没有区域设置的情况下使用 SimpleDateFormat 或 DateTimeFormatter
  2. 您可以使用 y 代替 u,但我更喜欢 u代码> 到 y
  3. 如何将 OffsetDateTime 与 JDBC 结合使用

RFC 2822 date-time string contains timezone offset e.g. the given string Sat, 13 Mar 2010 11:29:05 -0800 has a timezone offset of -08:00 hours from UTC i.e. the equivalent date-time at UTC can be obtained by adding 8 hours to Sat, 13 Mar 2010 11:29:05.

java.time

The modern date-time API API has OffsetDateTime to represent a date-time with timezone offset.

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

class Main {
    public static void main(String[] args) {
        String strRFC2822DateTimeStr = "Sat, 13 Mar 2010 11:29:05 -0800";

        OffsetDateTime odt = OffsetDateTime.parse(strRFC2822DateTimeStr, DateTimeFormatter.RFC_1123_DATE_TIME);
        System.out.println(odt);

        // Alternatively: using a custom DateTimeFormatter
        DateTimeFormatter parser = DateTimeFormatter.ofPattern("EEE, dd MMM uuuu HH:mm:ss XX", Locale.ENGLISH);
        System.out.println(OffsetDateTime.parse(strRFC2822DateTimeStr, parser));

        // In case you need the equivalent date-time at UTC
        OffsetDateTime odtUtc = odt.withOffsetSameInstant(ZoneOffset.UTC);
        System.out.println(odtUtc);
    }
}

Output:

2010-03-13T11:29:05-08:00
2010-03-13T11:29:05-08:00
2010-03-13T19:29:05Z

Learn more about the modern Date-Time API from Trail: Date Time.

Some useful links:

  1. Never use SimpleDateFormat or DateTimeFormatter without a Locale.
  2. You can use y instead of u but I prefer u to y.
  3. How to use OffsetDateTime with JDBC.
醉生梦死 2024-09-01 08:57:00

试试这个:

String dateTime = OffsetDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME); 
//RFC_1123 == RFC_2822

Try this:

String dateTime = OffsetDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME); 
//RFC_1123 == RFC_2822
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文