Skip to content

Commit

Permalink
use implementation from chrono#883 for begin-of-day
Browse files Browse the repository at this point in the history
  • Loading branch information
Ekleog committed Jan 27, 2023
1 parent 276ad28 commit 1a43970
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 35 deletions.
27 changes: 27 additions & 0 deletions risuto-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,30 @@ pub fn validate_time(s: &Time) -> Result<(), Error> {
Ok(())
}
}

// See https://github.com/chronotope/chrono/issues/948
pub fn midnight_on<Tz>(date: chrono::NaiveDate, tz: &Tz) -> chrono::DateTime<Tz>
where
Tz: Clone + std::fmt::Debug + chrono::TimeZone,
{
let base = chrono::NaiveTime::MIN;
for multiple in 0..=24 {
let start_time = base + chrono::Duration::minutes(multiple * 15);
match date.and_time(start_time).and_local_timezone(tz.clone()) {
chrono::LocalResult::None => continue,
chrono::LocalResult::Single(dt) => return dt,
chrono::LocalResult::Ambiguous(dt1, dt2) => {
if dt1.naive_utc() < dt2.naive_utc() {
return dt1;
} else {
return dt2;
}
}
}
}

panic!(
"Unable to calculate start time for date {} and time zone {:?}",
date, tz
)
}
3 changes: 1 addition & 2 deletions risuto-api/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ impl TimeQuery {
.map(|d| chrono::naive::Days::new(d as u64))
.and_then(|offset| date.checked_sub_days(offset)),
};
date.and_then(|d| d.and_hms_opt(0, 0, 0))
.and_then(|d| d.and_local_timezone(*timezone).single())
date.map(|d| crate::midnight_on(d, timezone))
.map(|d| d.with_timezone(&chrono::Utc))
.ok_or(Error::IntegerOutOfRange(*day_offset))
}
Expand Down
36 changes: 18 additions & 18 deletions risuto-client/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
};

use pest::{iterators::Pairs, pratt_parser::PrattParser, Parser as PestParser};
use risuto_api::Error;
use risuto_api::{midnight_on, Error};

pub trait QueryExt {
fn from_search(db: &DbDump, tz: &chrono_tz::Tz, search: &str) -> Query;
Expand Down Expand Up @@ -292,13 +292,12 @@ fn parse_date_cmp(
let timequery = match timequery.as_rule() {
Rule::abstimeq => TimeQuery::Absolute(
// TODO: for safety, see (currently open) https://github.com/chronotope/chrono/pull/927
chrono::NaiveDate::parse_from_str(timequery.as_str(), "%Y-%m-%d")
.expect("parsing date cmp with ill-formed absolute date")
.and_hms_opt(0, 0, 0)
.expect("failed adding hms 000 to date")
.and_local_timezone(tz.clone())
.unwrap()
.with_timezone(&chrono::Utc),
midnight_on(
chrono::NaiveDate::parse_from_str(timequery.as_str(), "%Y-%m-%d")
.expect("parsing date cmp with ill-formed absolute date"),
tz,
)
.with_timezone(&chrono::Utc),
),
Rule::reltimeq => {
let mut reader = timequery.into_inner();
Expand Down Expand Up @@ -341,7 +340,10 @@ fn parse_date_cmp(
}
}

fn start_of_next_day(tz: &impl chrono::TimeZone, day: TimeQuery) -> TimeQuery {
fn start_of_next_day<Tz>(tz: &Tz, day: TimeQuery) -> TimeQuery
where
Tz: Clone + std::fmt::Debug + chrono::TimeZone,
{
match day {
TimeQuery::DayRelative {
timezone,
Expand All @@ -351,15 +353,13 @@ fn start_of_next_day(tz: &impl chrono::TimeZone, day: TimeQuery) -> TimeQuery {
day_offset: day_offset + 1,
},
TimeQuery::Absolute(t) => TimeQuery::Absolute(
// TODO: for safety, see (currently open) https://github.com/chronotope/chrono/pull/927
t.date_naive()
.succ_opt()
.expect("failed figuring out a date for day+1")
.and_hms_opt(0, 0, 0)
.expect("failed setting hms to 000")
.and_local_timezone(tz.clone())
.unwrap()
.with_timezone(&chrono::Utc),
midnight_on(
t.date_naive()
.succ_opt()
.expect("failed figuring out a date for day+1"),
tz,
)
.with_timezone(&chrono::Utc),
),
}
}
Expand Down
Binary file not shown.
8 changes: 2 additions & 6 deletions risuto-server/src/query.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use risuto_api::{Query, Time, TimeQuery, Uuid};
use risuto_api::{midnight_on, Query, Time, TimeQuery, Uuid};

use crate::error::Error;

Expand Down Expand Up @@ -129,11 +129,7 @@ fn timeq_to_bind(q: &TimeQuery) -> Result<Bind, Error> {
.checked_sub_days(chrono::naive::Days::new((-day_offset) as u64))
.ok_or_else(|| Error::integer_out_of_range(*day_offset))?,
};
date.and_hms_opt(0, 0, 0)
.expect("naive_date and hms 000 failed")
.and_local_timezone(timezone.clone())
.unwrap()
.with_timezone(&chrono::Utc)
midnight_on(date, timezone).with_timezone(&chrono::Utc)
}
}))
}
13 changes: 4 additions & 9 deletions risuto-web/src/ui/task_list_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,15 +237,10 @@ fn timeset_button(p: &TimesetButtonProps) -> Html {
let timeset_label = current_date
.and_then(|d| {
let remaining = d.signed_duration_since(chrono::Utc::now());
// TODO: for safety, see (currently open) https://github.com/chronotope/chrono/pull/927
let since_beginning_of_day = d.signed_duration_since(
chrono::Utc::now()
.date_naive()
.and_hms_opt(0, 0, 0)
.expect("failed figuring out the start of day")
.and_local_timezone(util::local_tz())
.unwrap(),
);
let since_beginning_of_day = d.signed_duration_since(midnight_on(
chrono::Utc::now().date_naive(),
util::local_tz(),
));
match remaining {
r if r > chrono::Duration::days(365) => Some(format!("{}", d.year())),
r if r > chrono::Duration::days(1) => Some(format!("{}/{}", d.month(), d.day())),
Expand Down

0 comments on commit 1a43970

Please sign in to comment.