HTTP头部中使用的日期/时间格式

65

哪个RFC描述了现代HTTP头部中的日期/时间格式,比如"Last-Modified"和"If-Modified-Since",以及如何在PHP中按照这种格式生成日期/时间字符串?

一些来源指向RFC 2822,正如DateTime类所示,它使用D,d M Y H:i:s O格式,但是从我的测试中,这种格式最终产生+0000而不是GMT。我尝试过其他时区说明符,但没有一个似乎能将GMT放在末尾,最接近的结果是使用UTC。然而,正如Firebug所显示的那样,所有站点都在HTTP头部中使用GMT而不是+0000UTC

那么到底使用什么格式,如何以与其他站点相同的方式格式化日期/时间?


1
https://tools.ietf.org/html/rfc7231#section-7.1.1.1 - Fraser
5个回答

81
As you can see here, Last-Modified header has datetimes in RFC2616 format.

In section 14.29 Last-Modified, you can see that the date format should be:

"Last-Modified" ":" HTTP-date

其使用示例为:
Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT

RFC2616中的另一段引用阅读更多

所有HTTP日期/时间戳必须以格林威治标准时间(GMT)表示,毫无例外。

在PHP中,如果您使用gmdate()函数,则可以使用格式D,d M Y H:i:s T来返回带有GMT偏移/时区的日期时间:

echo gmdate('D, d M Y H:i:s T');

如果您想使用 DateTime 扩展:
$dt = new DateTime('UTC');
#$dt = new DateTime('2013-01-01 12:00:00', new DateTimezone('UTC'));
echo $dt->format('D, d M Y H:i:s \G\M\T');

但是你引用的页面上,大多数其他日期字符串都使用了GMT格式(7个示例使用了GMT,只有1个示例使用了+0000)。例如,美国今日网站的响应头如下:Last-Modified: Tue, 14 Jan 2014 18:48:38 GMT; Expires: Tue, 14 Jan 2014 18:50:58 GMT; Date: Tue, 14 Jan 2014 18:50:38 GMT,所以全部都使用了GMT。 - Desmond Hume
2
GMT 是 _Greenwich Mean Time_,它是绝对的。 - Maciej A. Czyzewski
1
好的,显然 gmdate("D, d M Y H:i:s T", 123456) 产生的字符串带有 GMT,所以还是谢谢。 - Desmond Hume
你引用了错误的规范。相关的是http://greenbytes.de/tech/webdav/rfc2616.html#rfc.section.3.3.1(或者将要取代它的规范:http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p2-semantics-25.html#rfc.section.7.1.1.1) - Julian Reschke
1
在PHP 7.0.19中添加了DATE_RFC7231常量,此提交 - sudoqux

21
好的,让我们来看一下定义 HTTP 1.1 的 RFC 2616: https://www.rfc-editor.org/rfc/rfc2616#section-3.3

HTTP applications have historically allowed three different formats for the representation of date/time stamps:

 Sun, 06 Nov 1994 08:49:37 GMT  ; RFC 822, updated by RFC 1123
 Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
 Sun Nov  6 08:49:37 1994       ; ANSI C's asctime() format

The first format is preferred as an Internet standard and represents a fixed-length subset of that defined by RFC 1123 [8] (an update to RFC 822 [9]).

(...)

All HTTP date/time stamps MUST be represented in Greenwich Mean Time (GMT), without exception.

因此,DateTime::COOKIEDatetime::RFC850使用有效的格式。按照RFC的首选项应该是D, d M Y H:i:s T,但在DateTime类中没有定义任何常量。

为了确保使用GMT时间,下面的代码就足够了:

gmdate('D, d M Y H:i:s T');

有一个常量用于首选格式 DateTime::RFC1123/DATE_RFC1123 - Courtney Miles
5
很接近但不完全相同。它使用结尾为“O”的字母,而不是“T”,这将返回“+0000”,而不是标准所需的“GMT”。 - hanzi

4
我相信这里现在的正确答案是 rfc7231 - section 7.1.1.1。它规定了日期/时间格式,并定义了 HTTP-date 的语义。
HTTP-date    = IMF-fixdate / obs-date

此外,我们可以看到:
当发送方生成一个包含一个或多个时间戳的头字段时,这些时间戳定义为HTTP-date,发送方必须IMF-fixdate格式生成这些时间戳。
因此,对于发送“现代时间HTTP标头”的服务器 - 其中值是HTTP-date,格式等同于IMF-fixdate格式。
所以,回答实际问题:
描述现代时间HTTP标头中日期/时间使用的RFC是哪个?
您需要了解IMF-fixdate的定义 - 它在rfc7231中。它还提供了obs-date的定义,即rfc850-date / asctime-date
     IMF-fixdate  = day-name "," SP date1 SP time-of-day SP GMT
     ; fixed length/zone/capitalization subset of the format
     ; see Section 3.3 of [RFC5322]

     day-name     = %x4D.6F.6E ; "Mon", case-sensitive
                  / %x54.75.65 ; "Tue", case-sensitive
                  / %x57.65.64 ; "Wed", case-sensitive
                  / %x54.68.75 ; "Thu", case-sensitive
                  / %x46.72.69 ; "Fri", case-sensitive
                  / %x53.61.74 ; "Sat", case-sensitive
                  / %x53.75.6E ; "Sun", case-sensitive


     date1        = day SP month SP year
                  ; e.g., 02 Jun 1982

     day          = 2DIGIT
     month        = %x4A.61.6E ; "Jan", case-sensitive
                  / %x46.65.62 ; "Feb", case-sensitive
                  / %x4D.61.72 ; "Mar", case-sensitive
                  / %x41.70.72 ; "Apr", case-sensitive
                  / %x4D.61.79 ; "May", case-sensitive
                  / %x4A.75.6E ; "Jun", case-sensitive
                  / %x4A.75.6C ; "Jul", case-sensitive
                  / %x41.75.67 ; "Aug", case-sensitive
                  / %x53.65.70 ; "Sep", case-sensitive
                  / %x4F.63.74 ; "Oct", case-sensitive
                  / %x4E.6F.76 ; "Nov", case-sensitive
                  / %x44.65.63 ; "Dec", case-sensitive
     year         = 4DIGIT

     GMT          = %x47.4D.54 ; "GMT", case-sensitive

     time-of-day  = hour ":" minute ":" second
                  ; 00:00:00 - 23:59:60 (leap second)

     hour         = 2DIGIT
     minute       = 2DIGIT
     second       = 2DIGIT

   Obsolete formats:

     obs-date     = rfc850-date / asctime-date

     rfc850-date  = day-name-l "," SP date2 SP time-of-day SP GMT
     date2        = day "-" month "-" 2DIGIT
                  ; e.g., 02-Jun-82

     day-name-l   = %x4D.6F.6E.64.61.79    ; "Monday", case-sensitive
            / %x54.75.65.73.64.61.79       ; "Tuesday", case-sensitive
            / %x57.65.64.6E.65.73.64.61.79 ; "Wednesday", case-sensitive
            / %x54.68.75.72.73.64.61.79    ; "Thursday", case-sensitive
            / %x46.72.69.64.61.79          ; "Friday", case-sensitive
            / %x53.61.74.75.72.64.61.79    ; "Saturday", case-sensitive
            / %x53.75.6E.64.61.79          ; "Sunday", case-sensitive


     asctime-date = day-name SP date3 SP time-of-day SP year
     date3        = month SP ( 2DIGIT / ( SP 1DIGIT ))
                  ; e.g., Jun  2

4

使用DateTime扩展,您可以使用RFC7231常量,该常量指的是RFC7231超文本传输协议(HTTP/1.1):语义和内容,第7.1.1.1章日期/时间格式

$httpDate = $dateTime->format(DateTimeInterface::RFC7231);

常量值实际上是其他答案中提出的相同字符串 D, d M Y H:i:s \G\M\T


-3
通过Carbon:
Carbon::now()->setTimezone('GMT')->format("D, d M Y H:i:s T")

请在您的答案中添加一些解释。问题是“使用哪种格式”,而不是如何生成它。 - Nico Haase

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接