【问题标题】:Getting Date in HTTP format in Java在 Java 中以 HTTP 格式获取日期
【发布时间】:2011-12-04 04:28:58
【问题描述】:

我正在尝试以 HTTP 1.1 中指定的格式在 Java 中获取日期字符串。据我所知,是:

格林威治标准时间 1999 年 12 月 31 日星期五 23:59:59

时间总是格林威治标准时间。

从日期/日历/获取此信息的最简单方法是什么?

【问题讨论】:

  • @BasilBourque 如果您考虑该月的前 9 天,它不符合要求。 Rfc 1123 支持 1-2 位数字,但 http 1.1 要求它是两位数的日期。
  • @jontejj 感谢您的澄清。我删除了我的 cmets,因为它们没有帮助。

标签: java http date time


【解决方案1】:

java.time

编辑:

DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH).withZone(ZoneId.of("GMT"))

是使用纯 java.time 的方式。 HTTP 1.1 与RFC 1123 不是 100% 匹配,因此使用 java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME 格式化程序将在小于 10 天的月份失败。(感谢@PavanKamar 和 @ankon 指出出)

注意:要向后兼容,您还需要支持RFC 2616指定的其他两种格式

【讨论】:

  • 很高兴在 Java 8 中看到这一点,但这对我来说不太有效,我不得不使用 ZonedDateTime.now() 而不是 Instant.now()
  • 我用这个除了 ZonedDateTime.now(ZoneId.of("GMT"))。感谢您的回答。
  • 这仅适用于 10 日或之后的日期。对于一位数日期,RFC 5322 要求日期为两位数,但此代码行生成一位数日期字段。 tools.ietf.org/html/rfc5322#section-3.3
  • @PavanKumar:好点,但我认为参考是错误的 :) RFC 5322,第 3.3 节说 day = ([FWS] 1*2DIGIT FWS) / obs-day1*2DIGIT 表示“至少一个,最多两个 DIGIT”(tools.ietf.org/html/rfc5234#section-3.6 由 RFC 5322 引用)。但是对于 HTTP/1.1 的目的:RFC 2616,第 3.3 节,引用了 RFC 1123 的“固定长度”格式(使用相同的定义 1*2DIGIT),将日期定义为 2DIGIT。这是一团糟:)
  • @jontejj 您可以将 ZoneId.of("GMT") 替换为预定义的常量 ZoneOffset.UTC
【解决方案2】:

如果其他人会尝试在这里找到答案(就像我一样),这就是诀窍:

String getServerTime() {
    Calendar calendar = Calendar.getInstance();
    SimpleDateFormat dateFormat = new SimpleDateFormat(
        "EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
    dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
    return dateFormat.format(calendar.getTime());
}

为了将服务器设置为说英语并在 GMT 时区给出时间。

【讨论】:

  • 这段代码是人们讨厌 Java 的一个典型例子。我接受了@jontejj 的回答。
  • 应该注意SimpleDateFormat 的使用不是线程安全的,dateFormat 必须是非共享的,如果共享则必须正确同步。最好使用 Java 8 或 Joda Time 类。
  • 这是 2011 年的一个很好的答案。它只是穿着...... :-) 当然同意现在进一步查看答案列表。
  • 这个答案现在已经过时了,它使用了麻烦的旧日期时间类,这些类已被 Java 8 及更高版本中内置的 java.time 类所取代。
【解决方案3】:

如果您使用Joda-Time(我强烈建议您在 Java 中处理任何日期和时间),您可以这样做:

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

...

private static final DateTimeFormatter RFC1123_DATE_TIME_FORMATTER = 
    DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'")
    .withZoneUTC().withLocale(Locale.US);

...

RFC1123_DATE_TIME_FORMATTER.print(new DateTime())

【讨论】:

  • 这很好用。但是,为了确保英语语言环境,我必须添加:private static final DateTimeFormatter RFC1123_DATE_TIME_FORMATTER = DateTimeFormat.forPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'").withZoneUTC().withLocale(Locale.US);
  • Joda-Time 项目现在处于维护模式。该团队建议迁移到 Java 8 及更高版本中内置的 java.time 类。
【解决方案4】:

两位数的日期

根据RFC7231,某些应用程序要求格式包含两位数的日期。 Java 8 DateTimeFormatter.RFC_1123_DATE_TIME 使用单个数字:

System.out.println(DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now(ZoneOffset.UTC)));

输出:Wed, 1 Aug 2018 14:56:46 GMT

有些应用程序不喜欢这样。在您使用使用 Joda-time 或 pre-java8 SimpleDateFormat 的旧答案之前,这里有一个有效的 Java-8 DateTimeFormatter

DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss O")

现在,当你这样做时:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss O");
System.out.println(formatter.format(ZonedDateTime.now(ZoneOffset.UTC)));

您会得到Wed, 01 Aug 2018 14:56:46 GMT - 请注意日期字段中的前导零。

【讨论】:

  • 您还需要记住在格式化程序中设置英语语言环境
  • @JacekObarymski 我该怎么做? withLocale(Locale.US) 给出相同的结果。
  • @pjanssen DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss O", Locale.ENGLISH)。如果您的默认语言环境是英语,那么您可能看不到区别,但恕我直言,这仍然是一个很好的做法。
  • @JacekObarymski 啊,我以为你的意思是在RFC_1123_DATE_TIME 上设置区域设置会添加前导零。
  • 不,我的意思是,如果您使用该模式 "EEE, dd MMM yyyy HH:mm:ss O" 并且没有设置英文语言环境,那么缩写的月份名称 'MMM' 将使用您所在地区的语言,显然不再符合 RFC_1123
【解决方案5】:

如果您像我一样尝试格式化 Java 8 java.time.Instant,则需要将时区显式添加到格式化程序。像这样:

Instant instant = Instant.now();
String formatted = DateTimeFormatter.RFC_1123_DATE_TIME
        .withZone(ZoneOffset.UTC)
        .format(instant);
System.out.println(formatted);

哪些打印:

格林威治标准时间 2016 年 3 月 15 日星期二 14:45:34

【讨论】:

  • 好答案。替代语法:OffsetDateTime.now( ZoneOffset.UTC ).format( DateTimeFormatter.RFC_1123_DATE_TIME )
  • 当 GMT 偏移量是格式化的要求时,我当然喜欢将偏移量作为格式化程序属性的想法。立即投票。
【解决方案6】:

如果不怕额外依赖,可以使用apache DateUtils:

import org.apache.http.impl.cookie.DateUtils;
DateUtils.formatDate(new Date(System.currentTimeMillis()));
// Tue, 17 Apr 2012 18:59:02 GMT

这会将您的日期格式化为 RFC 822 RFC1123

【讨论】:

  • RFC 822 实际上声明了 2 位数的年份,但是,取代 RFC 822 的 RFC 1123 将其更改为 4 位数的年份。
  • 看起来org.apache.http.impl.cookie.DateUtils 已被弃用。 formatDate 方法现在位于 org.apache.http.client.utils.DateUtils 中。
【解决方案7】:
Calendar calendar = Calendar.getInstance();
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
System.out.println("Date: " + dateFormat.format(calendar.getTime()));

你可以玩它。文档在这里: http://download.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

【讨论】:

  • 格林威治标准时间的要求如何?
  • 我也认为上面的示例返回系统时区中的日期,而不是 GMT(当然,如果您在 Locale 中将系统时区设置为 GMT,它会起作用,但不是每个人都愿意这样做)所以 -任何人 - 完整的答案是什么?
【解决方案8】:

我知道这是一个较晚的响应,但只是想添加它以确保完整性。

你没有提到你需要这个字符串做什么。但如果您需要它作为 HTTP 响应标头,则可以使用 HttpServletResponse.setDateHeader()。它会为您完成所有格式设置。

【讨论】:

猜你喜欢
  • 2013-03-10
  • 1970-01-01
  • 2014-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-18
  • 2023-01-11
  • 1970-01-01
相关资源
最近更新 更多