Skip to content

Commit

Permalink
Skip IANA TZ names when parsing %Z specifier (#473)
Browse files Browse the repository at this point in the history
  • Loading branch information
abashurov committed Aug 21, 2020
1 parent 709e10e commit f4c42b4
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 3 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 10 additions & 2 deletions src/format/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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",
Expand All @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions src/format/scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()), ()))
}
11 changes: 10 additions & 1 deletion src/format/strftime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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. |
Expand Down Expand Up @@ -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")]
Expand Down

0 comments on commit f4c42b4

Please sign in to comment.