Fix Memories Week span sorting
This commit is contained in:
131
src/memories.rs
131
src/memories.rs
@@ -1,9 +1,7 @@
|
|||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use actix_web::{HttpRequest, HttpResponse, Responder, get, web};
|
use actix_web::{HttpRequest, HttpResponse, Responder, get, web};
|
||||||
use chrono::LocalResult::{Ambiguous, Single};
|
use chrono::LocalResult::{Ambiguous, Single};
|
||||||
use chrono::{
|
use chrono::{DateTime, Datelike, FixedOffset, Local, LocalResult, NaiveDate, TimeZone, Utc};
|
||||||
DateTime, Datelike, FixedOffset, Local, LocalResult, NaiveDate, TimeZone, Timelike, Utc,
|
|
||||||
};
|
|
||||||
use log::{debug, trace, warn};
|
use log::{debug, trace, warn};
|
||||||
use opentelemetry::KeyValue;
|
use opentelemetry::KeyValue;
|
||||||
use opentelemetry::trace::{Span, Status, TraceContextExt, Tracer};
|
use opentelemetry::trace::{Span, Status, TraceContextExt, Tracer};
|
||||||
@@ -541,7 +539,7 @@ pub async fn list_memories(
|
|||||||
match span_mode {
|
match span_mode {
|
||||||
// Sort by absolute time for a more 'overview'
|
// Sort by absolute time for a more 'overview'
|
||||||
MemoriesSpan::Month => memories_with_dates.sort_by(|a, b| a.1.cmp(&b.1)),
|
MemoriesSpan::Month => memories_with_dates.sort_by(|a, b| a.1.cmp(&b.1)),
|
||||||
// For week span, sort by day of month, then time of day, then year (oldest first)
|
// For week span, sort by day of month, then by full timestamp (oldest first)
|
||||||
MemoriesSpan::Week => {
|
MemoriesSpan::Week => {
|
||||||
memories_with_dates.sort_by(|a, b| {
|
memories_with_dates.sort_by(|a, b| {
|
||||||
// First, sort by day of month
|
// First, sort by day of month
|
||||||
@@ -550,45 +548,12 @@ pub async fn list_memories(
|
|||||||
return day_cmp;
|
return day_cmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then sort by time of day
|
// Then sort by full created timestamp (oldest to newest)
|
||||||
match (a.0.created, b.0.created) {
|
match (a.0.created, b.0.created) {
|
||||||
(Some(a_time), Some(b_time)) => {
|
(Some(a_time), Some(b_time)) => a_time.cmp(&b_time),
|
||||||
// Convert timestamps to DateTime
|
|
||||||
let a_dt_utc = DateTime::<Utc>::from_timestamp(a_time, 0).unwrap();
|
|
||||||
let b_dt_utc = DateTime::<Utc>::from_timestamp(b_time, 0).unwrap();
|
|
||||||
|
|
||||||
// Extract time of day in the appropriate timezone
|
|
||||||
let a_time_of_day = if let Some(ref tz) = client_timezone {
|
|
||||||
let dt = a_dt_utc.with_timezone(tz);
|
|
||||||
(dt.hour(), dt.minute(), dt.second())
|
|
||||||
} else {
|
|
||||||
let dt = a_dt_utc.with_timezone(&Local);
|
|
||||||
(dt.hour(), dt.minute(), dt.second())
|
|
||||||
};
|
|
||||||
|
|
||||||
let b_time_of_day = if let Some(ref tz) = client_timezone {
|
|
||||||
let dt = b_dt_utc.with_timezone(tz);
|
|
||||||
(dt.hour(), dt.minute(), dt.second())
|
|
||||||
} else {
|
|
||||||
let dt = b_dt_utc.with_timezone(&Local);
|
|
||||||
(dt.hour(), dt.minute(), dt.second())
|
|
||||||
};
|
|
||||||
|
|
||||||
// Compare time of day
|
|
||||||
let time_cmp = a_time_of_day.cmp(&b_time_of_day);
|
|
||||||
if time_cmp != std::cmp::Ordering::Equal {
|
|
||||||
return time_cmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, sort by year (oldest first)
|
|
||||||
a.1.year().cmp(&b.1.year())
|
|
||||||
}
|
|
||||||
(Some(_), None) => std::cmp::Ordering::Less,
|
(Some(_), None) => std::cmp::Ordering::Less,
|
||||||
(None, Some(_)) => std::cmp::Ordering::Greater,
|
(None, Some(_)) => std::cmp::Ordering::Greater,
|
||||||
(None, None) => {
|
(None, None) => std::cmp::Ordering::Equal,
|
||||||
// If no timestamps, just sort by year (oldest first)
|
|
||||||
a.1.year().cmp(&b.1.year())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1017,4 +982,90 @@ mod tests {
|
|||||||
// keep.jpg doesn't match any rule
|
// keep.jpg doesn't match any rule
|
||||||
assert!(!excluder.is_excluded(&keep));
|
assert!(!excluder.is_excluded(&keep));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_week_span_sorting_chronological_by_day() {
|
||||||
|
// Test that Week span sorts by:
|
||||||
|
// 1. Day of month (ascending)
|
||||||
|
// 2. Full timestamp oldest to newest (year + time combined)
|
||||||
|
|
||||||
|
// Create test data:
|
||||||
|
// - Jan 15, 2024 at 9:00 AM
|
||||||
|
// - Jan 15, 2020 at 10:00 AM
|
||||||
|
// - Jan 16, 2021 at 8:00 AM
|
||||||
|
|
||||||
|
let jan_15_2024_9am = NaiveDate::from_ymd_opt(2024, 1, 15)
|
||||||
|
.unwrap()
|
||||||
|
.and_hms_opt(9, 0, 0)
|
||||||
|
.unwrap()
|
||||||
|
.and_utc()
|
||||||
|
.timestamp();
|
||||||
|
|
||||||
|
let jan_15_2020_10am = NaiveDate::from_ymd_opt(2020, 1, 15)
|
||||||
|
.unwrap()
|
||||||
|
.and_hms_opt(10, 0, 0)
|
||||||
|
.unwrap()
|
||||||
|
.and_utc()
|
||||||
|
.timestamp();
|
||||||
|
|
||||||
|
let jan_16_2021_8am = NaiveDate::from_ymd_opt(2021, 1, 16)
|
||||||
|
.unwrap()
|
||||||
|
.and_hms_opt(8, 0, 0)
|
||||||
|
.unwrap()
|
||||||
|
.and_utc()
|
||||||
|
.timestamp();
|
||||||
|
|
||||||
|
let mut memories_with_dates = vec![
|
||||||
|
(
|
||||||
|
MemoryItem {
|
||||||
|
path: "photo1.jpg".to_string(),
|
||||||
|
created: Some(jan_15_2024_9am),
|
||||||
|
modified: Some(jan_15_2024_9am),
|
||||||
|
},
|
||||||
|
NaiveDate::from_ymd_opt(2024, 1, 15).unwrap(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
MemoryItem {
|
||||||
|
path: "photo2.jpg".to_string(),
|
||||||
|
created: Some(jan_15_2020_10am),
|
||||||
|
modified: Some(jan_15_2020_10am),
|
||||||
|
},
|
||||||
|
NaiveDate::from_ymd_opt(2020, 1, 15).unwrap(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
MemoryItem {
|
||||||
|
path: "photo3.jpg".to_string(),
|
||||||
|
created: Some(jan_16_2021_8am),
|
||||||
|
modified: Some(jan_16_2021_8am),
|
||||||
|
},
|
||||||
|
NaiveDate::from_ymd_opt(2021, 1, 16).unwrap(),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Sort using Week span logic
|
||||||
|
memories_with_dates.sort_by(|a, b| {
|
||||||
|
// First, sort by day of month
|
||||||
|
let day_cmp = a.1.day().cmp(&b.1.day());
|
||||||
|
if day_cmp != std::cmp::Ordering::Equal {
|
||||||
|
return day_cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then sort by full created timestamp (oldest to newest)
|
||||||
|
match (a.0.created, b.0.created) {
|
||||||
|
(Some(a_time), Some(b_time)) => a_time.cmp(&b_time),
|
||||||
|
(Some(_), None) => std::cmp::Ordering::Less,
|
||||||
|
(None, Some(_)) => std::cmp::Ordering::Greater,
|
||||||
|
(None, None) => std::cmp::Ordering::Equal,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Expected order:
|
||||||
|
// 1. Jan 15, 2020 at 10:00 AM (oldest Jan 15 photo)
|
||||||
|
// 2. Jan 15, 2024 at 9:00 AM (newer Jan 15 photo)
|
||||||
|
// 3. Jan 16, 2021 at 8:00 AM (all Jan 16 photos after Jan 15)
|
||||||
|
|
||||||
|
assert_eq!(memories_with_dates[0].0.created.unwrap(), jan_15_2020_10am);
|
||||||
|
assert_eq!(memories_with_dates[1].0.created.unwrap(), jan_15_2024_9am);
|
||||||
|
assert_eq!(memories_with_dates[2].0.created.unwrap(), jan_16_2021_8am);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user