【问题标题】:How to convert Gmail date format to java.util.Date?如何将 Gmail 日期格式转换为 java.util.Date?
【发布时间】:2018-09-23 16:04:09
【问题描述】:

我尝试使用 tPOP 从 Gmail 帐户检索邮件,然后将最后一次检索邮件的日期保存在某处(因此下次运行该作业时,我不会检索相同的邮件两次)。

我可以从 gmail 邮件中检索到的唯一日期是这种格式:

2018 年 4 月 13 日星期五 02:26:19 -0700(太平洋夏令时间)

如何将其转换为 Java.util.Date 格式?

【问题讨论】:

标签: java talend


【解决方案1】:

您可以使用SimpleDateFormat 执行此任务:

String dt = "Fri, 13 Apr 2018 02:26:19 -0700 (PDT)";
Date date = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss", Locale.ENGLISH).parse(dt);

阅读更多:

【讨论】:

  • 感谢您的回答,但它给了我这个错误:java.text.ParseException: Unparseable date: "Fri, 13 Apr 2018 02:26:19 -0700 (PDT)"
  • @AniketSahrawat :简单的日期格式对区域设置敏感。 “Fri”在英语中具有含义,而不是法语或俄语或其他含义。因此,“法语” SimpleDateFormat 将无法解析它。您可能应该在解析之前设置 SimpleDateFormat 的语言环境。无论如何,这不是一个完整的答案(尽管它应该在大多数情况下都有效)。请参阅:stackoverflow.com/a/17404726/2131074:星期几是可选的,并且此示例中未考虑时区规范,这两者都可能导致解析失败。
  • @AniketSahrawat 添加 Locale.ENGLISH 后我仍然遇到同样的问题。
  • 请不要教年轻人使用早已过时且臭名昭著的SimpleDateFormat类。至少不是第一选择。而且不是没有任何保留。今天我们在java.time, the modern Java date and time API 和它的DateTimeFormatter 中做得更好。
  • java.time 不适用于 Android API
【解决方案2】:

tl;博士

String input = "Fri, 13 Apr 2018 02:26:19 -0700 (PDT)" ;
…
java.util.Date.from(                                     // Convert from modern classes `OffsetDateTime` & `Instant` to troublesome legacy class `Date`. Do so only if absolutely necessary.
    OffsetDateTime.parse(
        input.substring( 0 , input.indexOf( " (" ) ) ,   // Drop the ambiguity-prone pseudo-zone ` (PDT)` from the end.
        DateTimeFormatter.RFC_1123_DATE_TIME             // Parse using a built-in formatter defined for RFC 1123 strings.
    )
    .toInstant()                                         // Extract UTC value (`Instant`) from `OffsetDateTime`.
)                                                        // Returns a legacy `java.util.Date` object.

DateTimeFormatter.RFC_1123_DATE_TIME

正如the Answer by GPI 中所讨论的,Java 为 RFC 1123 中定义的这种格式提供了一个格式化程序(另请参阅 RFC 822)。

除非像PDT 这样的伪时区代码不能被明确解析,因为它们不是标准化的并且不是唯一的。所以把它去掉。

String original = "Fri, 13 Apr 2018 02:26:19 -0700 (PDT)";
// Delete non-standard pseudo-zone at end.
String input = original;
if ( input.endsWith( ")" ) ) {
    int index = input.indexOf( " (" );
    input = input.substring( 0 , index );
}
DateTimeFormatter f = DateTimeFormatter.RFC_1123_DATE_TIME;
OffsetDateTime odt = OffsetDateTime.parse( input , f );

转储到控制台。

System.out.println( original );
System.out.println( input );
System.out.println( odt );

2018 年 4 月 13 日星期五 02:26:19 -0700(太平洋夏令时间)

2018 年 4 月 13 日星期五 02:26:19 -0700

2018-04-13T02:26:19-07:00

转换

如何将其转换为 Java.util.Date 格式?

不要。 java.util.Date 是一个设计不佳、令人困惑和麻烦的东西。躲开它。

但如果您必须与尚未更新到 java.time 类的旧代码进行互操作,则可以来回转换。调用添加到旧类的新方法。

从OffsetDateTime 中提取Instant,因为该类替换java.util.Date 以表示UTC 时刻。

Instant instant = odt.toInstant() ;
java.util.Date d = java.util.Date.from( instant ) ;

关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。

【讨论】:

  • 当您的 hack 有效时,应更正两个错误语句:a) 输入字符串未在 RFC 1123 中定义,但 RFC 5322 允许 cmets(尾随的“(PDT)”确实是这样的评论)。 b) 在 RFC 1123 中,区域 PDT 等不是模棱两可的,而是明确定义的,并且仅与北美相关,请参阅 RFC 822 中的原始论文 - 第 25 页)。
【解决方案3】:

迄今为止的其他答案,尽管它们可能在大多数情况下都有效,但不要考虑 RFC1123 格式的细节(请参阅第 5.2.14 节,它替换了原来的 RFC-822 定义)。

根据这个规范定义,星期几字段是可选的(SimpleDateForamt 不能处理可选字段),时区可以作为 +/- 偏移量(SimpleDateFormat 中的大写 Z)或名称( SimpleDateFormat 中的小写 z)。

您可以创建 SimpleDateFormats 的组合,然后查看哪个匹配,但这很慢。您可以使用 JodaTime 并构建可选部分,因为它有一个 API,但这也需要时间。

或者如果你有 Java8+,你有DateTimeFormatter.RFC_1123_DATE_TIME 是免费的。这不是标准的完整实现,但如果您自己编写代码,可能会尽可能接近。而且可能也更安全。

另见:Getting Date in HTTP format in Java

【讨论】:

  • RFC_1123_DATE_TIME 不会考虑时区名称,我不认为。
  • 它说有。 Javadoc:The format consists of: [...] The {@link ZoneOffset#getId() offset ID} without colons or seconds. An offset of zero uses "GMT. ,虽然作为时区的文本识别,只识别GMT,而不是各种美国时区的规范可能性。在问题的情况下,使用基于 GMT 的数字偏移量,而不是这样的文本时区。
【解决方案4】:

改用Message-ID: 标头

下次我运行该作业时,我不会再次检索相同的邮件

为避免下载相同的邮件,请使用Message-ID: 标头而不是Date:。这就是它的目的,唯一地标识每条消息。无需解析任何东西。

见fields described here。

例子:

Message-ID: <f6a363400703050910y7d591d42raf015fcef16f95ea@mail.gmail.com>
Date: Mon, 5 Mar 2007 09:10:41 -0800
From: UserName <address@gmail.com>
To: OtherUserName <address@system.com>
Subject: Subject Line
MIME-Version: 1.0

将此字符串用作您的唯一标识符:

f6a363400703050910y7d591d42raf015fcef16f95ea@mail.gmail.com

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-06
    • 2014-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-12
    • 2016-04-17
    相关资源
    最近更新 更多