@@ -76,16 +76,17 @@ fn two_digits(b1: u8, b2: u8) -> Result<u64, Error> {
7676
7777/// Parse RFC3339 timestamp `2018-02-14T00:28:07Z`
7878///
79- /// Supported feature: any precision of fractional
80- /// digits `2018-02-14T00:28:07.133Z`.
79+ /// Supported features:
80+ /// - Any precision of fractional digits `2018-02-14T00:28:07.133Z`.
81+ /// - The UTC timezone can be indicated with `Z` or `+00:00`.
8182///
8283/// Unsupported feature: localized timestamps. Only UTC is supported.
8384pub fn parse_rfc3339 ( s : & str ) -> Result < SystemTime , Error > {
8485 if s. len ( ) < "2018-02-14T00:28:07Z" . len ( ) {
8586 return Err ( Error :: InvalidFormat ) ;
8687 }
8788 let b = s. as_bytes ( ) ;
88- if b[ 10 ] != b'T' || b. last ( ) != Some ( & b'Z' ) {
89+ if b[ 10 ] != b'T' || ( b. last ( ) != Some ( & b'Z' ) && !s . ends_with ( "+00:00" ) ) {
8990 return Err ( Error :: InvalidFormat ) ;
9091 }
9192 parse_rfc3339_weak ( s)
@@ -96,7 +97,7 @@ pub fn parse_rfc3339(s: &str) -> Result<SystemTime, Error> {
9697/// Supported features:
9798///
9899/// 1. Any precision of fractional digits `2018-02-14 00:28:07.133`.
99- /// 2. Supports timestamp with or without either of `T` or `Z`
100+ /// 2. Supports timestamp with or without either of `T`, `Z` or `+00:00`.
100101/// 3. Anything valid for [`parse_rfc3339`](parse_rfc3339) is valid for this function
101102///
102103/// Unsupported feature: localized timestamps. Only UTC is supported, even if
@@ -171,14 +172,19 @@ pub fn parse_rfc3339_weak(s: &str) -> Result<SystemTime, Error> {
171172 if idx == b. len ( ) - 1 {
172173 break ;
173174 }
174-
175+ return Err ( Error :: InvalidDigit ) ;
176+ } else if b[ idx] == b'+' {
177+ // start of "+00:00", which must be at the end
178+ if idx == b. len ( ) - 6 {
179+ break ;
180+ }
175181 return Err ( Error :: InvalidDigit ) ;
176182 }
177183
178184 nanos += mult * ( b[ idx] as char ) . to_digit ( 10 ) . ok_or ( Error :: InvalidDigit ) ?;
179185 mult /= 10 ;
180186 }
181- } else if b. len ( ) != 19 && ( b. len ( ) > 20 || b[ 19 ] != b'Z' ) {
187+ } else if b. len ( ) != 19 && ( b. len ( ) > 25 || ( b[ 19 ] != b'Z' && ( & b [ 19 .. ] != b"+00:00" ) ) ) {
182188 return Err ( Error :: InvalidFormat ) ;
183189 }
184190
@@ -679,4 +685,59 @@ mod test {
679685 ) ;
680686 parse_rfc3339 ( "1970-01-01 00:00:00Z" ) . unwrap_err ( ) ;
681687 }
688+
689+ #[ test]
690+ fn parse_offset_00 ( ) {
691+ assert_eq ! (
692+ parse_rfc3339( "1970-01-01T00:00:00+00:00" ) . unwrap( ) ,
693+ UNIX_EPOCH + Duration :: new( 0 , 0 )
694+ ) ;
695+ assert_eq ! (
696+ parse_rfc3339( "1970-01-01T00:00:01+00:00" ) . unwrap( ) ,
697+ UNIX_EPOCH + Duration :: new( 1 , 0 )
698+ ) ;
699+ assert_eq ! (
700+ parse_rfc3339( "2018-02-13T23:08:32+00:00" ) . unwrap( ) ,
701+ UNIX_EPOCH + Duration :: new( 1_518_563_312 , 0 )
702+ ) ;
703+ assert_eq ! (
704+ parse_rfc3339( "2012-01-01T00:00:00+00:00" ) . unwrap( ) ,
705+ UNIX_EPOCH + Duration :: new( 1_325_376_000 , 0 )
706+ ) ;
707+
708+ // invalid
709+ assert_eq ! (
710+ parse_rfc3339( "2012-01-01T00:00:00 +00:00" ) ,
711+ Err ( super :: Error :: InvalidFormat )
712+ ) ;
713+ assert_eq ! (
714+ parse_rfc3339( "2012-01-01T00:00:00+00" ) ,
715+ Err ( super :: Error :: InvalidFormat )
716+ ) ;
717+ }
718+
719+ #[ test]
720+ fn weak_parse_offset_00 ( ) {
721+ assert_eq ! (
722+ parse_rfc3339_weak( "1970-01-01 00:00:00+00:00" ) . unwrap( ) ,
723+ UNIX_EPOCH + Duration :: new( 0 , 0 )
724+ ) ;
725+ assert_eq ! (
726+ parse_rfc3339_weak( "1970-01-01 00:00:00.000123+00:00" ) . unwrap( ) ,
727+ UNIX_EPOCH + Duration :: new( 0 , 123_000 )
728+ ) ;
729+ assert_eq ! (
730+ parse_rfc3339_weak( "1970-01-01T00:00:00.000123+00:00" ) . unwrap( ) ,
731+ UNIX_EPOCH + Duration :: new( 0 , 123_000 )
732+ ) ;
733+
734+ // invalid
735+ parse_rfc3339 ( "2012-01-01T+00:00:00" ) . unwrap_err ( ) ;
736+ parse_rfc3339 ( "1970-01-01 00:00:00.00+0123" ) . unwrap_err ( ) ;
737+ parse_rfc3339 ( "1970-01-01 00:00:00.0000123+00:00" ) . unwrap_err ( ) ;
738+ parse_rfc3339 ( "1970-01-01 00:00:00.0000123+00:00abcd" ) . unwrap_err ( ) ;
739+ parse_rfc3339 ( "1970-01-01 00:00:00.0000123+02:00" ) . unwrap_err ( ) ;
740+ parse_rfc3339 ( "1970-01-01 00:00:00.0000123+00" ) . unwrap_err ( ) ;
741+ parse_rfc3339 ( "1970-01-01 00:00:00.0000123+" ) . unwrap_err ( ) ;
742+ }
682743}
0 commit comments