Skip to content

Commit

Permalink
fix ordinal week calculation
Browse files Browse the repository at this point in the history
* math is 0 based while ordinal is 1 based => fix as 1 based logic
* add extensive testing against the "date" command format
* format: test sample instead of every day
* 2007 starts with saturday
* Last day of the year is thus the 52 on Monday weekly calendar, 53 on Sunday weekly calendar.
* update %U expected value in test
* Was the goal was to have a different value than with %W at next line ? another date to pick ?
* update cfg("unix") into cfg(target_os = "linux")
* format tests/dateutils.rs
  • Loading branch information
raphaelroosz authored and djc committed Mar 4, 2023
1 parent f9f3c78 commit a9b1ec4
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 4 deletions.
4 changes: 2 additions & 2 deletions src/format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,10 +521,10 @@ fn format_inner(
use self::Numeric::*;

let week_from_sun = |d: &NaiveDate| {
(d.ordinal() as i32 - d.weekday().num_days_from_sunday() as i32 + 7) / 7
(d.ordinal() as i32 - d.weekday().num_days_from_sunday() as i32 + 6) / 7
};
let week_from_mon = |d: &NaiveDate| {
(d.ordinal() as i32 - d.weekday().num_days_from_monday() as i32 + 7) / 7
(d.ordinal() as i32 - d.weekday().num_days_from_monday() as i32 + 6) / 7
};

let (width, v) = match *spec {
Expand Down
2 changes: 1 addition & 1 deletion src/format/strftime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ fn test_strftime_docs() {
assert_eq!(dt.format("%A").to_string(), "Sunday");
assert_eq!(dt.format("%w").to_string(), "0");
assert_eq!(dt.format("%u").to_string(), "7");
assert_eq!(dt.format("%U").to_string(), "28");
assert_eq!(dt.format("%U").to_string(), "27");
assert_eq!(dt.format("%W").to_string(), "27");
assert_eq!(dt.format("%G").to_string(), "2001");
assert_eq!(dt.format("%g").to_string(), "01");
Expand Down
2 changes: 1 addition & 1 deletion src/naive/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2869,7 +2869,7 @@ mod tests {
// corner cases
assert_eq!(
NaiveDate::from_ymd_opt(2007, 12, 31).unwrap().format("%G,%g,%U,%W,%V").to_string(),
"2008,08,53,53,01"
"2008,08,52,53,01"
);
assert_eq!(
NaiveDate::from_ymd_opt(2010, 1, 3).unwrap().format("%G,%g,%U,%W,%V").to_string(),
Expand Down
55 changes: 55 additions & 0 deletions tests/dateutils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,58 @@ fn try_verify_against_date_command() {
date += chrono::Duration::hours(1);
}
}

#[cfg(target_os = "linux")]
fn verify_against_date_command_format_local(path: &'static str, dt: NaiveDateTime) {
let required_format =
"d%d D%D F%F H%H I%I j%j k%k l%l m%m M%M S%S T%T u%u U%U w%w W%W X%X y%y Y%Y z%:z";
// a%a - depends from localization
// A%A - depends from localization
// b%b - depends from localization
// B%B - depends from localization
// h%h - depends from localization
// c%c - depends from localization
// p%p - depends from localization
// r%r - depends from localization
// x%x - fails, date is dd/mm/yyyy, chrono is dd/mm/yy, same as %D
// Z%Z - too many ways to represent it, will most likely fail

let output = process::Command::new(path)
.arg("-d")
.arg(format!(
"{}-{:02}-{:02} {:02}:{:02}:{:02}",
dt.year(),
dt.month(),
dt.day(),
dt.hour(),
dt.minute(),
dt.second()
))
.arg(format!("+{}", required_format))
.output()
.unwrap();

let date_command_str = String::from_utf8(output.stdout).unwrap();
let date = NaiveDate::from_ymd_opt(dt.year(), dt.month(), dt.day()).unwrap();
let ldt = Local
.from_local_datetime(&date.and_hms_opt(dt.hour(), dt.minute(), dt.second()).unwrap())
.unwrap();
let formated_date = format!("{}\n", ldt.format(required_format));
assert_eq!(date_command_str, formated_date);
}

#[test]
#[cfg(target_os = "linux")]
fn try_verify_against_date_command_format() {
let date_path = "/usr/bin/date";

if !path::Path::new(date_path).exists() {
// date command not found, skipping
return;
}
let mut date = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap().and_hms_opt(12, 11, 13).unwrap();
while date.year() < 2008 {
verify_against_date_command_format_local(date_path, date);
date += chrono::Duration::days(55);
}
}

0 comments on commit a9b1ec4

Please sign in to comment.