diff --git a/spec/std/time/time_spec.cr b/spec/std/time/time_spec.cr index cb790f72e4e6..dbf80a91836f 100644 --- a/spec/std/time/time_spec.cr +++ b/spec/std/time/time_spec.cr @@ -360,6 +360,14 @@ describe Time do t.to_s("%s").should eq("1388631845") end + it "formats standard formats" do + time = Time.new(2016, 2, 15, kind: Time::Kind::Utc) + time.to_rfc3339.should eq "2016-02-15T00:00:00+00:00" + Time.parse_rfc3339(time.to_rfc3339).should eq time + time.to_rfc2822.should eq "Mon, 15 Feb 2016 00:00:00 +0000" + Time.parse_rfc2822(time.to_rfc2822).should eq time + end + it "parses empty" do t = Time.parse("", "") t.year.should eq(1) diff --git a/src/http/common.cr b/src/http/common.cr index eba44d262c5c..d6bca506d410 100644 --- a/src/http/common.cr +++ b/src/http/common.cr @@ -237,6 +237,7 @@ module HTTP # ``` # HTTP.rfc1123_date(Time.new(2016, 2, 15)) # => "Sun, 14 Feb 2016 21:00:00 GMT" # ``` + # DEPRECATED: Use `Time#to_rfc2822` instead. def self.rfc1123_date(time : Time) : String Time::Format::HTTP_DATE.format(time) end diff --git a/src/http/cookie.cr b/src/http/cookie.cr index 508c1ef28f02..13bb239a2943 100644 --- a/src/http/cookie.cr +++ b/src/http/cookie.cr @@ -31,7 +31,7 @@ module HTTP header << "#{URI.escape @name}=#{URI.escape value}" header << "; domain=#{domain}" if domain header << "; path=#{path}" if path - header << "; expires=#{HTTP.rfc1123_date(expires)}" if expires + header << "; expires=#{expires.to_utc.to_rfc2822}" if expires header << "; Secure" if @secure header << "; HttpOnly" if @http_only header << "; #{@extension}" if @extension diff --git a/src/time.cr b/src/time.cr index eb755f808ca8..53dcb176cb62 100644 --- a/src/time.cr +++ b/src/time.cr @@ -435,6 +435,56 @@ struct Time Format.new(format).format(self, io) end + # Format this time using the format specified by [RFC 3339](https://tools.ietf.org/html/rfc3339) ([ISO 8601](http://xml.coverpages.org/ISO-FDIS-8601.pdf) profile). + # + # ``` + # Time.new(2016, 2, 15).to_rfc3339 # => "2016-02-15T00:00:00+00:00" + # ``` + # + # ISO 8601 allows some freedom over the syntax and RFC 3339 exercises that + # freedom to rigidly define a fixed format intended for use in internet + # protocols and standards. + def to_rfc3339 + Format::RFC_3339.format(to_utc) + end + + # Format this time using the format specified by [RFC 3339](https://tools.ietf.org/html/rfc3339) ([ISO 8601](http://xml.coverpages.org/ISO-FDIS-8601.pdf) profile). + # into the given *io*. + def to_rfc3339(io : IO) + Format::RFC_3339.format(to_utc, io) + end + + # Parse time in format specified by [RFC 3339](https://tools.ietf.org/html/rfc3339) ([ISO 8601](http://xml.coverpages.org/ISO-FDIS-8601.pdf) profile). + def self.parse_rfc3339(time : String) + Format::RFC_3339.parse(time) + end + + # Format this time using the format specified by [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt). + # + # ``` + # Time.new(2016, 2, 15).to_rfc2822 # => "Mon, 15 Feb 2016 00:00:00 -0400" + # ``` + # + # This is also compatible to [RFC 882](https://tools.ietf.org/html/rfc882) and [RFC 1123](https://tools.ietf.org/html/rfc1123#page-55). + def to_rfc2822 + Format::RFC_2822.format(to_utc) + end + + # Format this time using the format specified by [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt) + # into the given *io*. + # + # This is also compatible to [RFC 882](https://tools.ietf.org/html/rfc882) and [RFC 1123](https://tools.ietf.org/html/rfc1123#page-55). + def to_rfc2822(io : IO) + Format::RFC_2822.format(to_utc, io) + end + + # Parse time in format specified by [RFC 2822](https://www.ietf.org/rfc/rfc2822.txt). + # + # This is also compatible to [RFC 882](https://tools.ietf.org/html/rfc882) and [RFC 1123](https://tools.ietf.org/html/rfc1123#page-55). + def self.parse_rfc2822(time : String) + Format::RFC_2822.parse(time) + end + # Parses a Time in the given *time* string, using the given *pattern* (see # `Time::Format`). # diff --git a/src/time/format.cr b/src/time/format.cr index 4758841aec03..86d11e6ebc51 100644 --- a/src/time/format.cr +++ b/src/time/format.cr @@ -59,6 +59,15 @@ struct Time::Format # :nodoc: DAY_NAMES = %w(Sunday Monday Tuesday Wednesday Thursday Friday Saturday) + # The [RFC 3339](https://tools.ietf.org/html/rfc3339)/[ISO 8601](http://xml.coverpages.org/ISO-FDIS-8601.pdf) datetime format. + # This is just `"%FT%X%:z"`. + RFC_3339 = new "%FT%X%:z" + + # The [RFC 2822](https://tools.ietf.org/html/rfc2822) datetime format. + # + # This is also compatible to [RFC 882](https://tools.ietf.org/html/rfc882) and [RFC 1123](https://tools.ietf.org/html/rfc1123#page-55). + RFC_2822 = new "%a, %d %b %Y %H:%M:%S %z" + # Error raised when an invalid pattern is used. class Error < ::Exception end