From b0ab61d31806962542b89f9be2063a6d46010f5a Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Sun, 16 Aug 2026 21:20:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20ZonedDateTime=20=E6=97=B6=E5=8C=BA?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E6=94=AF=E6=8C=81=20=C2=B1HH=20=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E5=81=8F=E7=A7=BB=E5=89=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_builtins/src/temporal.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crates/oxide_builtins/src/temporal.rs b/crates/oxide_builtins/src/temporal.rs index 6da5f0c4..1a4f0392 100644 --- a/crates/oxide_builtins/src/temporal.rs +++ b/crates/oxide_builtins/src/temporal.rs @@ -1037,6 +1037,19 @@ fn canonical_time_zone(value: &str) -> Option<(String, i32)> { if let Some(offset) = parse_offset_minutes(input) { return Some((input.to_string(), offset)); } + + // ±HH 基本偏移("+01" / "-05"):3 字符,hour ≤ 23,分钟恒 0。仅放宽构造器时区接受面。 + if input.len() == 3 + && matches!(input.as_bytes()[0], b'+' | b'-') + && input.as_bytes()[1..3].iter().all(u8::is_ascii_digit) + { + let hour = (input.as_bytes()[1] - b'0') as i32 * 10 + (input.as_bytes()[2] - b'0') as i32; + if hour <= 23 { + let sign = if input.as_bytes()[0] == b'-' { -1 } else { 1 }; + return Some((input.to_string(), sign * hour * 60)); + } + return None; + } if input.starts_with("-000000") { return None; }