Skip IANA TZ names when parsing %Z specifier (#473)

This commit is contained in:
Aleksandr Bashurov 2020-08-21 22:56:10 +07:00 committed by GitHub
parent 709e10ed26
commit f4c42b4f14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 3 deletions

View File

@ -10,6 +10,11 @@ Versions with only mechanical changes will be omitted from the following list.
## 0.4.16 (unreleased)
### Features
* Add %Z specifier to the `FromStr`, similar to the glibc strptime
(does not set the offset from the timezone name)
## 0.4.15
### Fixes

View File

@ -407,7 +407,9 @@ where
parsed.set_nanosecond(nano).map_err(|e| (s, e))?;
}
&TimezoneName => return Err((s, BAD_FORMAT)),
&TimezoneName => {
try_consume!(scan::timezone_name_skip(s));
}
&TimezoneOffsetColon | &TimezoneOffset => {
let offset = try_consume!(scan::timezone_offset(
@ -752,7 +754,7 @@ fn test_parse() {
check!("z", [internal_fix!(TimezoneOffsetPermissive)]; offset: 0);
check!("+12:00", [internal_fix!(TimezoneOffsetPermissive)]; offset: 12 * 60 * 60);
check!("+12", [internal_fix!(TimezoneOffsetPermissive)]; offset: 12 * 60 * 60);
check!("???", [fix!(TimezoneName)]; BAD_FORMAT); // not allowed
check!("CEST 5", [fix!(TimezoneName), lit!(" "), num!(Day)]; day: 5);
// some practical examples
check!("2015-02-04T14:37:05+09:00",
@ -771,6 +773,12 @@ fn test_parse() {
num!(Minute), lit!(":"), num!(Second), sp!(" "), lit!("GMT")];
year: 2013, month: 6, day: 10, weekday: Weekday::Mon,
hour_div_12: 0, hour_mod_12: 9, minute: 32, second: 37);
check!("Sun Aug 02 13:39:15 CEST 2020",
[fix!(ShortWeekdayName), sp!(" "), fix!(ShortMonthName), sp!(" "),
num!(Day), sp!(" "), num!(Hour), lit!(":"), num!(Minute), lit!(":"),
num!(Second), sp!(" "), fix!(TimezoneName), sp!(" "), num!(Year)];
year: 2020, month: 8, day: 2, weekday: Weekday::Sun,
hour_div_12: 1, hour_mod_12: 1, minute: 39, second: 15);
check!("20060102150405",
[num!(Year), num!(Month), num!(Day), num!(Hour), num!(Minute), num!(Second)];
year: 2006, month: 1, day: 2, hour_div_12: 1, hour_mod_12: 3, minute: 4, second: 5);

View File

@ -342,3 +342,9 @@ pub fn timezone_offset_2822(s: &str) -> ParseResult<(&str, Option<i32>)> {
Ok((s_, Some(offset)))
}
}
/// Tries to consume everyting until next whitespace-like symbol.
/// Does not provide any offset information from the consumed data.
pub fn timezone_name_skip(s: &str) -> ParseResult<(&str, ())> {
Ok((s.trim_left_matches(|c: char| !c.is_whitespace()), ()))
}

View File

@ -68,7 +68,7 @@ The following specifiers are available both to formatting and parsing.
| `%r` | `12:34:60 AM` | Hour-minute-second format in 12-hour clocks. Same as `%I:%M:%S %p`. |
| | | |
| | | **TIME ZONE SPECIFIERS:** |
| `%Z` | `ACST` | *Formatting only:* Local time zone name. |
| `%Z` | `ACST` | Local time zone name. Skips all non-whitespace characters during parsing. [^9] |
| `%z` | `+0930` | Offset from the local time to UTC (with UTC being `+0000`). |
| `%:z` | `+09:30` | Same as `%z` but with a colon. |
| `%#z` | `+09` | *Parsing only:* Same as `%z` but allows minutes to be missing or present. |
@ -157,6 +157,15 @@ Notes:
and parsing `07`, `070000` etc. will yield the same.
Note that they can read nothing if the fractional part is zero.
[^9]: `%Z`:
Offset will not be populated from the parsed data, nor will it be validated.
Timezone is completely ignored. Similar to the glibc `strptime` treatment of
this format code.
<br>
<br>
It is not possible to reliably convert from an abbreviation to an offset,
for example CDT can mean either Central Daylight Time (North America) or
China Daylight Time.
*/
#[cfg(feature = "unstable-locales")]