Skip to content

Commit 462c698

Browse files
Copilotjgarzik
andcommitted
Fix POSIX compliance: handle empty TZ and escaped %%Z correctly
Co-authored-by: jgarzik <494411+jgarzik@users.noreply.github.com>
1 parent 089762f commit 462c698

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

datetime/date.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ fn get_timezone_abbreviation(dt: &DateTime<Local>) -> String {
2424
// Try to get TZ environment variable
2525
if let Ok(tz_str) = env::var("TZ") {
2626
// Handle special cases for UTC
27-
if tz_str == "UTC" || tz_str == "UTC0" || tz_str.is_empty() {
27+
if tz_str == "UTC" || tz_str == "UTC0" {
2828
return "UTC".to_string();
2929
}
3030

@@ -80,9 +80,27 @@ fn parse_format_string_with_tz(formatstr: &str, tz_abbr: &str) -> String {
8080
result
8181
}
8282

83+
/// Check if a format string contains an unescaped %Z
84+
fn contains_unescaped_tz(formatstr: &str) -> bool {
85+
let mut chars = formatstr.chars().peekable();
86+
while let Some(ch) = chars.next() {
87+
if ch == '%' {
88+
if let Some(&next_ch) = chars.peek() {
89+
if next_ch == 'Z' {
90+
return true;
91+
} else if next_ch == '%' {
92+
// Skip escaped %%
93+
chars.next();
94+
}
95+
}
96+
}
97+
}
98+
false
99+
}
100+
83101
/// Format a datetime string, replacing %Z with proper timezone abbreviation
84102
fn format_with_timezone_local(formatstr: &str, dt: &DateTime<Local>) -> String {
85-
if formatstr.contains("%Z") {
103+
if contains_unescaped_tz(formatstr) {
86104
let tz_abbr = get_timezone_abbreviation(dt);
87105
let modified_format = parse_format_string_with_tz(formatstr, &tz_abbr);
88106
dt.format(&modified_format).to_string()
@@ -93,7 +111,7 @@ fn format_with_timezone_local(formatstr: &str, dt: &DateTime<Local>) -> String {
93111

94112
/// Format a datetime string for UTC, replacing %Z with "UTC"
95113
fn format_with_timezone_utc(formatstr: &str, dt: &DateTime<Utc>) -> String {
96-
if formatstr.contains("%Z") {
114+
if contains_unescaped_tz(formatstr) {
97115
let modified_format = parse_format_string_with_tz(formatstr, "UTC");
98116
dt.format(&modified_format).to_string()
99117
} else {

0 commit comments

Comments
 (0)