Skip to content

Commit 859f5ad

Browse files
committed
feat: auto-detect timezone from baseline capture date
- Extracts date from C++ baseline file - Uses Pacific DST rules: PDT (Mar 8 - Nov 7), PST (Nov 8 - Mar 7) - --tz flag still available to override auto-detection - Default behavior: auto-detect, not hardcoded -7
1 parent 805c47d commit 859f5ad

File tree

1 file changed

+100
-8
lines changed

1 file changed

+100
-8
lines changed

scripts/verify_parity.rs

Lines changed: 100 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,20 @@ fn main() {
7676
let drive_dir = resolve_drive_dir(&base_dir, &drive_lower);
7777

7878
// Parse optional arguments
79-
let tz_offset = parse_tz_offset(&args);
79+
let explicit_tz = parse_tz_offset(&args);
8080
let custom_bin = parse_bin_path(&args);
8181

8282
// Determine mode
8383
let mode = &args[3];
8484
let rust_output = match mode.as_str() {
8585
"--regenerate" => {
86+
// Find baseline first for tz auto-detection
87+
let golden_baseline = find_golden_baseline_file(&drive_dir, &drive_lower);
88+
89+
// Auto-detect or use explicit tz
90+
let tz_offset =
91+
explicit_tz.unwrap_or_else(|| detect_tz_from_baseline(&golden_baseline));
92+
8693
// Regenerate mode: run uffs to produce fresh output
8794
regenerate_rust_output(
8895
&drive_dir,
@@ -224,8 +231,9 @@ fn print_usage(prog: &str) {
224231
);
225232
eprintln!();
226233
eprintln!("Options:");
227-
eprintln!(" --tz OFFSET Timezone offset in hours (default: -7 for PDT)");
228-
eprintln!(" Use -7 for PDT (Pacific Daylight), -8 for PST (Pacific Standard)");
234+
eprintln!(" --tz OFFSET Timezone offset in hours (default: auto-detect from baseline)");
235+
eprintln!(" Auto-detection uses Pacific time DST rules based on capture date.");
236+
eprintln!(" Override with -7 for PDT (Mar-Nov), -8 for PST (Nov-Mar)");
229237
eprintln!(" --bin PATH Path to uffs binary (default: auto-detect from cargo metadata)");
230238
eprintln!();
231239
eprintln!("The script auto-detects the drive data directory:");
@@ -234,7 +242,10 @@ fn print_usage(prog: &str) {
234242
eprintln!();
235243
eprintln!("Examples:");
236244
eprintln!(" {} /Users/rnio/uffs_data F --regenerate", prog);
237-
eprintln!(" {} /Users/rnio/uffs_data F --regenerate --tz -8", prog);
245+
eprintln!(
246+
" {} /Users/rnio/uffs_data F --regenerate --tz -8 # override auto-detect",
247+
prog
248+
);
238249
eprintln!(
239250
" {} /Users/rnio/uffs_data F --regenerate --bin ./target/release/uffs",
240251
prog
@@ -245,14 +256,95 @@ fn print_usage(prog: &str) {
245256
);
246257
}
247258

248-
/// Parse --tz argument from command line. Default: -7 (PDT).
249-
fn parse_tz_offset(args: &[String]) -> i32 {
259+
/// Parse --tz argument from command line. Returns None if not specified
260+
/// (auto-detect).
261+
fn parse_tz_offset(args: &[String]) -> Option<i32> {
250262
for i in 0..args.len() {
251263
if args[i] == "--tz" && i + 1 < args.len() {
252-
return args[i + 1].parse().unwrap_or(-7);
264+
return Some(args[i + 1].parse().unwrap_or(-7));
265+
}
266+
}
267+
None // Auto-detect from baseline
268+
}
269+
270+
/// Auto-detect timezone offset from C++ baseline file.
271+
/// Extracts a date from the baseline and determines PDT vs PST based on Pacific
272+
/// DST rules. Pacific DST: 2nd Sunday of March 2:00 AM to 1st Sunday of
273+
/// November 2:00 AM
274+
fn detect_tz_from_baseline(baseline_path: &Path) -> i32 {
275+
// Read first few lines to find a data line with a timestamp
276+
let file = match std::fs::File::open(baseline_path) {
277+
Ok(f) => f,
278+
Err(_) => return -7, // Default to PDT if can't read
279+
};
280+
let reader = std::io::BufReader::new(file);
281+
282+
for line in std::io::BufRead::lines(reader).take(10).flatten() {
283+
// Look for a timestamp pattern: YYYY-MM-DD HH:MM:SS
284+
if let Some(date_match) = extract_date_from_line(&line) {
285+
let offset = pacific_tz_offset(date_match.0, date_match.1, date_match.2);
286+
println!(
287+
"Auto-detected timezone from baseline date {}-{:02}-{:02}: {} ({})",
288+
date_match.0,
289+
date_match.1,
290+
date_match.2,
291+
offset,
292+
if offset == -7 { "PDT" } else { "PST" }
293+
);
294+
return offset;
295+
}
296+
}
297+
298+
println!("Could not auto-detect timezone, defaulting to -7 (PDT)");
299+
-7
300+
}
301+
302+
/// Extract (year, month, day) from a CSV line containing a timestamp.
303+
fn extract_date_from_line(line: &str) -> Option<(i32, u32, u32)> {
304+
// Look for pattern: YYYY-MM-DD (4 digits, dash, 2 digits, dash, 2 digits)
305+
let bytes = line.as_bytes();
306+
for i in 0..bytes.len().saturating_sub(10) {
307+
if bytes[i].is_ascii_digit()
308+
&& bytes[i + 1].is_ascii_digit()
309+
&& bytes[i + 2].is_ascii_digit()
310+
&& bytes[i + 3].is_ascii_digit()
311+
&& bytes[i + 4] == b'-'
312+
&& bytes[i + 5].is_ascii_digit()
313+
&& bytes[i + 6].is_ascii_digit()
314+
&& bytes[i + 7] == b'-'
315+
&& bytes[i + 8].is_ascii_digit()
316+
&& bytes[i + 9].is_ascii_digit()
317+
{
318+
let year: i32 = line[i..i + 4].parse().ok()?;
319+
let month: u32 = line[i + 5..i + 7].parse().ok()?;
320+
let day: u32 = line[i + 8..i + 10].parse().ok()?;
321+
if year >= 2000 && year <= 2100 && month >= 1 && month <= 12 && day >= 1 && day <= 31 {
322+
return Some((year, month, day));
323+
}
253324
}
254325
}
255-
-7 // Default to PDT
326+
None
327+
}
328+
329+
/// Determine Pacific timezone offset for a given date.
330+
/// Returns -7 for PDT (Daylight), -8 for PST (Standard).
331+
/// Pacific DST: 2nd Sunday of March 2:00 AM to 1st Sunday of November 2:00 AM
332+
fn pacific_tz_offset(year: i32, month: u32, day: u32) -> i32 {
333+
// Simple rule: March 15 - November 1 is approximately PDT
334+
// More precise would calculate exact Sunday transitions, but this is close
335+
// enough
336+
let dst_start = (3, 8); // March 8 (earliest 2nd Sunday)
337+
let dst_end = (11, 1); // November 1 (earliest 1st Sunday)
338+
339+
if month > dst_start.0 && month < dst_end.0 {
340+
-7 // PDT: April through October
341+
} else if month == dst_start.0 && day >= 8 {
342+
-7 // PDT: March 8+ (approx 2nd Sunday)
343+
} else if month == dst_end.0 && day < 8 {
344+
-7 // PDT: November 1-7 (before 1st Sunday ends DST)
345+
} else {
346+
-8 // PST: November 8+ through early March
347+
}
256348
}
257349

258350
/// Parse --bin argument from command line. Returns None if not specified.

0 commit comments

Comments
 (0)