mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
fetch timing_today() params in backend
This commit is contained in:
parent
eee0d7e92f
commit
ea4f150455
9 changed files with 81 additions and 149 deletions
|
@ -29,7 +29,7 @@ message I18nBackendInit {
|
||||||
|
|
||||||
message BackendInput {
|
message BackendInput {
|
||||||
oneof value {
|
oneof value {
|
||||||
SchedTimingTodayIn sched_timing_today = 17;
|
Empty sched_timing_today = 17;
|
||||||
DeckTreeIn deck_tree = 18;
|
DeckTreeIn deck_tree = 18;
|
||||||
SearchCardsIn search_cards = 19;
|
SearchCardsIn search_cards = 19;
|
||||||
SearchNotesIn search_notes = 20;
|
SearchNotesIn search_notes = 20;
|
||||||
|
@ -101,7 +101,6 @@ message BackendInput {
|
||||||
message BackendOutput {
|
message BackendOutput {
|
||||||
oneof value {
|
oneof value {
|
||||||
// infallible commands
|
// infallible commands
|
||||||
SchedTimingTodayOut sched_timing_today = 17;
|
|
||||||
sint32 local_minutes_west = 22;
|
sint32 local_minutes_west = 22;
|
||||||
string strip_av_tags = 23;
|
string strip_av_tags = 23;
|
||||||
ExtractAVTagsOut extract_av_tags = 24;
|
ExtractAVTagsOut extract_av_tags = 24;
|
||||||
|
@ -114,6 +113,7 @@ message BackendOutput {
|
||||||
AllStockNotetypesOut all_stock_notetypes = 60;
|
AllStockNotetypesOut all_stock_notetypes = 60;
|
||||||
|
|
||||||
// fallible commands
|
// fallible commands
|
||||||
|
SchedTimingTodayOut sched_timing_today = 17;
|
||||||
DeckTreeNode deck_tree = 18;
|
DeckTreeNode deck_tree = 18;
|
||||||
SearchCardsOut search_cards = 19;
|
SearchCardsOut search_cards = 19;
|
||||||
SearchNotesOut search_notes = 20;
|
SearchNotesOut search_notes = 20;
|
||||||
|
@ -237,14 +237,6 @@ message MediaSyncUploadProgress {
|
||||||
uint32 deletions = 2;
|
uint32 deletions = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SchedTimingTodayIn {
|
|
||||||
int64 created_secs = 1;
|
|
||||||
int64 now_secs = 2;
|
|
||||||
OptionalInt32 created_mins_west = 3;
|
|
||||||
OptionalInt32 now_mins_west = 4;
|
|
||||||
OptionalInt32 rollover_hour = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
message SchedTimingTodayOut {
|
message SchedTimingTodayOut {
|
||||||
uint32 days_elapsed = 1;
|
uint32 days_elapsed = 1;
|
||||||
int64 next_day_at = 2;
|
int64 next_day_at = 2;
|
||||||
|
|
|
@ -287,38 +287,9 @@ class RustBackend:
|
||||||
release_gil=True,
|
release_gil=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def sched_timing_today(
|
def sched_timing_today(self,) -> SchedTimingToday:
|
||||||
self,
|
|
||||||
created_secs: int,
|
|
||||||
created_mins_west: Optional[int],
|
|
||||||
now_mins_west: Optional[int],
|
|
||||||
rollover: Optional[int],
|
|
||||||
) -> SchedTimingToday:
|
|
||||||
if created_mins_west is not None:
|
|
||||||
crt_west = pb.OptionalInt32(val=created_mins_west)
|
|
||||||
else:
|
|
||||||
crt_west = None
|
|
||||||
|
|
||||||
if now_mins_west is not None:
|
|
||||||
now_west = pb.OptionalInt32(val=now_mins_west)
|
|
||||||
else:
|
|
||||||
now_west = None
|
|
||||||
|
|
||||||
if rollover is not None:
|
|
||||||
roll = pb.OptionalInt32(val=rollover)
|
|
||||||
else:
|
|
||||||
roll = None
|
|
||||||
|
|
||||||
return self._run_command(
|
return self._run_command(
|
||||||
pb.BackendInput(
|
pb.BackendInput(sched_timing_today=pb.Empty())
|
||||||
sched_timing_today=pb.SchedTimingTodayIn(
|
|
||||||
created_secs=created_secs,
|
|
||||||
now_secs=intTime(),
|
|
||||||
created_mins_west=crt_west,
|
|
||||||
now_mins_west=now_west,
|
|
||||||
rollover_hour=roll,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
).sched_timing_today
|
).sched_timing_today
|
||||||
|
|
||||||
def render_card(
|
def render_card(
|
||||||
|
|
|
@ -1374,28 +1374,8 @@ where id = ?
|
||||||
if time.time() > self.dayCutoff:
|
if time.time() > self.dayCutoff:
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def _rolloverHour(self) -> int:
|
|
||||||
return self.col.conf.get("rollover", 4)
|
|
||||||
|
|
||||||
def _timing_today(self) -> SchedTimingToday:
|
def _timing_today(self) -> SchedTimingToday:
|
||||||
roll: Optional[int] = None
|
return self.col.backend.sched_timing_today()
|
||||||
if self.col.schedVer() > 1:
|
|
||||||
roll = self._rolloverHour()
|
|
||||||
return self.col.backend.sched_timing_today(
|
|
||||||
self.col.crt,
|
|
||||||
self._creation_timezone_offset(),
|
|
||||||
self._current_timezone_offset(),
|
|
||||||
roll,
|
|
||||||
)
|
|
||||||
|
|
||||||
def _current_timezone_offset(self) -> Optional[int]:
|
|
||||||
if self.col.server:
|
|
||||||
return self.col.conf.get("localOffset", 0)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def _creation_timezone_offset(self) -> Optional[int]:
|
|
||||||
return self.col.conf.get("creationOffset", None)
|
|
||||||
|
|
||||||
# New timezone handling - GUI helpers
|
# New timezone handling - GUI helpers
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
|
@ -106,6 +106,7 @@ def test_export_anki_due():
|
||||||
f["Front"] = "foo"
|
f["Front"] = "foo"
|
||||||
deck.addNote(f)
|
deck.addNote(f)
|
||||||
deck.crt -= 86400 * 10
|
deck.crt -= 86400 * 10
|
||||||
|
deck.flush()
|
||||||
deck.sched.reset()
|
deck.sched.reset()
|
||||||
c = deck.sched.getCard()
|
c = deck.sched.getCard()
|
||||||
deck.sched.answerCard(c, 3)
|
deck.sched.answerCard(c, 3)
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::{
|
||||||
media::MediaManager,
|
media::MediaManager,
|
||||||
notes::{Note, NoteID},
|
notes::{Note, NoteID},
|
||||||
notetype::{all_stock_notetypes, NoteType, NoteTypeID, NoteTypeSchema11},
|
notetype::{all_stock_notetypes, NoteType, NoteTypeID, NoteTypeSchema11},
|
||||||
sched::cutoff::{local_minutes_west_for_stamp, sched_timing_today},
|
sched::cutoff::local_minutes_west_for_stamp,
|
||||||
sched::timespan::{answer_button_time, learning_congrats, studied_today, time_span},
|
sched::timespan::{answer_button_time, learning_congrats, studied_today, time_span},
|
||||||
search::SortMode,
|
search::SortMode,
|
||||||
template::{render_card, RenderedNode},
|
template::{render_card, RenderedNode},
|
||||||
|
@ -214,9 +214,7 @@ impl Backend {
|
||||||
) -> Result<pb::backend_output::Value> {
|
) -> Result<pb::backend_output::Value> {
|
||||||
use pb::backend_output::Value as OValue;
|
use pb::backend_output::Value as OValue;
|
||||||
Ok(match ival {
|
Ok(match ival {
|
||||||
Value::SchedTimingToday(input) => {
|
Value::SchedTimingToday(_) => OValue::SchedTimingToday(self.sched_timing_today()?),
|
||||||
OValue::SchedTimingToday(self.sched_timing_today(input))
|
|
||||||
}
|
|
||||||
Value::DeckTree(input) => OValue::DeckTree(self.deck_tree(input)?),
|
Value::DeckTree(input) => OValue::DeckTree(self.deck_tree(input)?),
|
||||||
Value::RenderCard(input) => OValue::RenderCard(self.render_template(input)?),
|
Value::RenderCard(input) => OValue::RenderCard(self.render_template(input)?),
|
||||||
Value::LocalMinutesWest(stamp) => {
|
Value::LocalMinutesWest(stamp) => {
|
||||||
|
@ -436,18 +434,8 @@ impl Backend {
|
||||||
self.progress_callback = progress_cb;
|
self.progress_callback = progress_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sched_timing_today(&self, input: pb::SchedTimingTodayIn) -> pb::SchedTimingTodayOut {
|
fn sched_timing_today(&self) -> Result<pb::SchedTimingTodayOut> {
|
||||||
let today = sched_timing_today(
|
self.with_col(|col| col.timing_today().map(Into::into))
|
||||||
TimestampSecs(input.created_secs),
|
|
||||||
TimestampSecs(input.now_secs),
|
|
||||||
input.created_mins_west.map(|v| v.val),
|
|
||||||
input.now_mins_west.map(|v| v.val),
|
|
||||||
input.rollover_hour.map(|v| v.val as i8),
|
|
||||||
);
|
|
||||||
pb::SchedTimingTodayOut {
|
|
||||||
days_elapsed: today.days_elapsed,
|
|
||||||
next_day_at: today.next_day_at,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deck_tree(&self, input: pb::DeckTreeIn) -> Result<pb::DeckTreeNode> {
|
fn deck_tree(&self, input: pb::DeckTreeIn) -> Result<pb::DeckTreeNode> {
|
||||||
|
@ -1269,3 +1257,12 @@ fn pbcard_to_native(c: pb::Card) -> Result<Card> {
|
||||||
data: c.data,
|
data: c.data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<crate::sched::cutoff::SchedTimingToday> for pb::SchedTimingTodayOut {
|
||||||
|
fn from(t: crate::sched::cutoff::SchedTimingToday) -> pb::SchedTimingTodayOut {
|
||||||
|
pb::SchedTimingTodayOut {
|
||||||
|
days_elapsed: t.days_elapsed,
|
||||||
|
next_day_at: t.next_day_at,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,12 +4,10 @@
|
||||||
use crate::err::{AnkiError, Result};
|
use crate::err::{AnkiError, Result};
|
||||||
use crate::i18n::I18n;
|
use crate::i18n::I18n;
|
||||||
use crate::log::Logger;
|
use crate::log::Logger;
|
||||||
use crate::timestamp::TimestampSecs;
|
|
||||||
use crate::types::Usn;
|
use crate::types::Usn;
|
||||||
use crate::{
|
use crate::{
|
||||||
decks::{Deck, DeckID},
|
decks::{Deck, DeckID},
|
||||||
notetype::{NoteType, NoteTypeID},
|
notetype::{NoteType, NoteTypeID},
|
||||||
sched::cutoff::{sched_timing_today, SchedTimingToday},
|
|
||||||
storage::SqliteStorage,
|
storage::SqliteStorage,
|
||||||
undo::UndoManager,
|
undo::UndoManager,
|
||||||
};
|
};
|
||||||
|
@ -51,7 +49,6 @@ pub fn open_test_collection() -> Collection {
|
||||||
pub struct CollectionState {
|
pub struct CollectionState {
|
||||||
task_state: CollectionTaskState,
|
task_state: CollectionTaskState,
|
||||||
pub(crate) undo: UndoManager,
|
pub(crate) undo: UndoManager,
|
||||||
timing_today: Option<SchedTimingToday>,
|
|
||||||
pub(crate) notetype_cache: HashMap<NoteTypeID, Arc<NoteType>>,
|
pub(crate) notetype_cache: HashMap<NoteTypeID, Arc<NoteType>>,
|
||||||
pub(crate) deck_cache: HashMap<DeckID, Arc<Deck>>,
|
pub(crate) deck_cache: HashMap<DeckID, Arc<Deck>>,
|
||||||
}
|
}
|
||||||
|
@ -142,37 +139,6 @@ impl Collection {
|
||||||
self.storage.close(downgrade)
|
self.storage.close(downgrade)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fixme: invalidate when config changes
|
|
||||||
pub fn timing_today(&mut self) -> Result<SchedTimingToday> {
|
|
||||||
if let Some(timing) = &self.state.timing_today {
|
|
||||||
if timing.next_day_at > TimestampSecs::now().0 {
|
|
||||||
return Ok(*timing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let local_offset = if self.server {
|
|
||||||
self.get_local_mins_west()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let timing = sched_timing_today(
|
|
||||||
self.storage.creation_stamp()?,
|
|
||||||
TimestampSecs::now(),
|
|
||||||
self.get_creation_mins_west(),
|
|
||||||
local_offset,
|
|
||||||
self.get_rollover(),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.state.timing_today = Some(timing);
|
|
||||||
|
|
||||||
Ok(timing)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn learn_cutoff(&self) -> u32 {
|
|
||||||
TimestampSecs::now().0 as u32 + self.learn_ahead_secs()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn usn(&self) -> Result<Usn> {
|
pub(crate) fn usn(&self) -> Result<Usn> {
|
||||||
// if we cache this in the future, must make sure to invalidate cache when usn bumped in sync.finish()
|
// if we cache this in the future, must make sure to invalidate cache when usn bumped in sync.finish()
|
||||||
self.storage.usn(self.server)
|
self.storage.usn(self.server)
|
||||||
|
|
|
@ -138,8 +138,9 @@ impl Collection {
|
||||||
self.set_config(ConfigKey::LocalOffset, &mins)
|
self.set_config(ConfigKey::LocalOffset, &mins)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_rollover(&self) -> Option<i8> {
|
pub(crate) fn get_rollover(&self) -> Option<u8> {
|
||||||
self.get_config_optional(ConfigKey::Rollover)
|
self.get_config_optional::<u8, _>(ConfigKey::Rollover)
|
||||||
|
.map(|r| r.min(23))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
use crate::timestamp::TimestampSecs;
|
use crate::timestamp::TimestampSecs;
|
||||||
use chrono::{Date, Duration, FixedOffset, Local, TimeZone};
|
use chrono::{Date, Duration, FixedOffset, Local, TimeZone, Timelike};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
pub struct SchedTimingToday {
|
pub struct SchedTimingToday {
|
||||||
|
@ -24,7 +24,7 @@ pub fn sched_timing_today_v2_new(
|
||||||
created_mins_west: i32,
|
created_mins_west: i32,
|
||||||
now_secs: i64,
|
now_secs: i64,
|
||||||
now_mins_west: i32,
|
now_mins_west: i32,
|
||||||
rollover_hour: i8,
|
rollover_hour: u8,
|
||||||
) -> SchedTimingToday {
|
) -> SchedTimingToday {
|
||||||
// get date(times) based on timezone offsets
|
// get date(times) based on timezone offsets
|
||||||
let created_date = fixed_offset_from_minutes(created_mins_west)
|
let created_date = fixed_offset_from_minutes(created_mins_west)
|
||||||
|
@ -34,7 +34,6 @@ pub fn sched_timing_today_v2_new(
|
||||||
let today = now_datetime.date();
|
let today = now_datetime.date();
|
||||||
|
|
||||||
// rollover
|
// rollover
|
||||||
let rollover_hour = normalized_rollover_hour(rollover_hour);
|
|
||||||
let rollover_today_datetime = today.and_hms(rollover_hour as u32, 0, 0);
|
let rollover_today_datetime = today.and_hms(rollover_hour as u32, 0, 0);
|
||||||
let rollover_passed = rollover_today_datetime <= now_datetime;
|
let rollover_passed = rollover_today_datetime <= now_datetime;
|
||||||
let next_day_at = if rollover_passed {
|
let next_day_at = if rollover_passed {
|
||||||
|
@ -67,17 +66,6 @@ fn days_elapsed(
|
||||||
days.max(0) as u32
|
days.max(0) as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Negative rollover hours are relative to the next day, eg -1 = 23.
|
|
||||||
/// Cap hour to 23.
|
|
||||||
fn normalized_rollover_hour(hour: i8) -> u8 {
|
|
||||||
let capped_hour = hour.max(-23).min(23);
|
|
||||||
if capped_hour < 0 {
|
|
||||||
(24 + capped_hour) as u8
|
|
||||||
} else {
|
|
||||||
capped_hour as u8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Build a FixedOffset struct, capping minutes_west if out of bounds.
|
/// Build a FixedOffset struct, capping minutes_west if out of bounds.
|
||||||
fn fixed_offset_from_minutes(minutes_west: i32) -> FixedOffset {
|
fn fixed_offset_from_minutes(minutes_west: i32) -> FixedOffset {
|
||||||
let bounded_minutes = minutes_west.max(-23 * 60).min(23 * 60);
|
let bounded_minutes = minutes_west.max(-23 * 60).min(23 * 60);
|
||||||
|
@ -95,6 +83,10 @@ pub fn local_minutes_west_for_stamp(stamp: i64) -> i32 {
|
||||||
// Legacy code
|
// Legacy code
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
|
|
||||||
|
pub(crate) fn v1_rollover_from_creation_stamp(crt: i64) -> u8 {
|
||||||
|
Local.timestamp(crt, 0).hour() as u8
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn v1_creation_date() -> i64 {
|
pub(crate) fn v1_creation_date() -> i64 {
|
||||||
let now = TimestampSecs::now();
|
let now = TimestampSecs::now();
|
||||||
v1_creation_date_inner(now, local_minutes_west_for_stamp(now.0))
|
v1_creation_date_inner(now, local_minutes_west_for_stamp(now.0))
|
||||||
|
@ -124,24 +116,23 @@ fn sched_timing_today_v1(crt: i64, now: i64) -> SchedTimingToday {
|
||||||
|
|
||||||
fn sched_timing_today_v2_legacy(
|
fn sched_timing_today_v2_legacy(
|
||||||
crt: i64,
|
crt: i64,
|
||||||
rollover: i8,
|
rollover: u8,
|
||||||
now: i64,
|
now: i64,
|
||||||
mins_west: i32,
|
mins_west: i32,
|
||||||
) -> SchedTimingToday {
|
) -> SchedTimingToday {
|
||||||
let normalized_rollover = normalized_rollover_hour(rollover);
|
|
||||||
let offset = fixed_offset_from_minutes(mins_west);
|
let offset = fixed_offset_from_minutes(mins_west);
|
||||||
|
|
||||||
let crt_at_rollover = offset
|
let crt_at_rollover = offset
|
||||||
.timestamp(crt, 0)
|
.timestamp(crt, 0)
|
||||||
.date()
|
.date()
|
||||||
.and_hms(normalized_rollover as u32, 0, 0)
|
.and_hms(rollover as u32, 0, 0)
|
||||||
.timestamp();
|
.timestamp();
|
||||||
let days_elapsed = (now - crt_at_rollover) / 86_400;
|
let days_elapsed = (now - crt_at_rollover) / 86_400;
|
||||||
|
|
||||||
let mut next_day_at = offset
|
let mut next_day_at = offset
|
||||||
.timestamp(now, 0)
|
.timestamp(now, 0)
|
||||||
.date()
|
.date()
|
||||||
.and_hms(normalized_rollover as u32, 0, 0)
|
.and_hms(rollover as u32, 0, 0)
|
||||||
.timestamp();
|
.timestamp();
|
||||||
if next_day_at < now {
|
if next_day_at < now {
|
||||||
next_day_at += 86_400;
|
next_day_at += 86_400;
|
||||||
|
@ -161,7 +152,7 @@ pub(crate) fn sched_timing_today(
|
||||||
now_secs: TimestampSecs,
|
now_secs: TimestampSecs,
|
||||||
created_mins_west: Option<i32>,
|
created_mins_west: Option<i32>,
|
||||||
now_mins_west: Option<i32>,
|
now_mins_west: Option<i32>,
|
||||||
rollover_hour: Option<i8>,
|
rollover_hour: Option<u8>,
|
||||||
) -> SchedTimingToday {
|
) -> SchedTimingToday {
|
||||||
let now_west = now_mins_west.unwrap_or_else(|| local_minutes_west_for_stamp(now_secs.0));
|
let now_west = now_mins_west.unwrap_or_else(|| local_minutes_west_for_stamp(now_secs.0));
|
||||||
match (rollover_hour, created_mins_west) {
|
match (rollover_hour, created_mins_west) {
|
||||||
|
@ -188,17 +179,6 @@ mod test {
|
||||||
// static timezone for tests
|
// static timezone for tests
|
||||||
const AEST_MINS_WEST: i32 = -600;
|
const AEST_MINS_WEST: i32 = -600;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn rollover() {
|
|
||||||
assert_eq!(normalized_rollover_hour(4), 4);
|
|
||||||
assert_eq!(normalized_rollover_hour(23), 23);
|
|
||||||
assert_eq!(normalized_rollover_hour(24), 23);
|
|
||||||
assert_eq!(normalized_rollover_hour(-1), 23);
|
|
||||||
assert_eq!(normalized_rollover_hour(-2), 22);
|
|
||||||
assert_eq!(normalized_rollover_hour(-23), 1);
|
|
||||||
assert_eq!(normalized_rollover_hour(-24), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fixed_offset() {
|
fn fixed_offset() {
|
||||||
let offset = fixed_offset_from_minutes(AEST_MINS_WEST);
|
let offset = fixed_offset_from_minutes(AEST_MINS_WEST);
|
||||||
|
@ -206,7 +186,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper
|
// helper
|
||||||
fn elap(start: i64, end: i64, start_west: i32, end_west: i32, rollhour: i8) -> u32 {
|
fn elap(start: i64, end: i64, start_west: i32, end_west: i32, rollhour: u8) -> u32 {
|
||||||
let today = sched_timing_today_v2_new(start, start_west, end, end_west, rollhour);
|
let today = sched_timing_today_v2_new(start, start_west, end, end_west, rollhour);
|
||||||
today.days_elapsed
|
today.days_elapsed
|
||||||
}
|
}
|
||||||
|
@ -300,7 +280,7 @@ mod test {
|
||||||
end_stamp,
|
end_stamp,
|
||||||
crt_offset,
|
crt_offset,
|
||||||
end_offset,
|
end_offset,
|
||||||
*rollover_hour as i8
|
*rollover_hour as u8
|
||||||
),
|
),
|
||||||
elap_day
|
elap_day
|
||||||
);
|
);
|
||||||
|
@ -323,7 +303,7 @@ mod test {
|
||||||
crt.offset().utc_minus_local() / 60,
|
crt.offset().utc_minus_local() / 60,
|
||||||
now.timestamp(),
|
now.timestamp(),
|
||||||
now.offset().utc_minus_local() / 60,
|
now.offset().utc_minus_local() / 60,
|
||||||
rollhour as i8,
|
rollhour as u8,
|
||||||
);
|
);
|
||||||
assert_eq!(today.next_day_at, next_day_at.timestamp());
|
assert_eq!(today.next_day_at, next_day_at.timestamp());
|
||||||
|
|
||||||
|
@ -335,7 +315,7 @@ mod test {
|
||||||
crt.offset().utc_minus_local() / 60,
|
crt.offset().utc_minus_local() / 60,
|
||||||
now.timestamp(),
|
now.timestamp(),
|
||||||
now.offset().utc_minus_local() / 60,
|
now.offset().utc_minus_local() / 60,
|
||||||
rollhour as i8,
|
rollhour as u8,
|
||||||
);
|
);
|
||||||
assert_eq!(today.next_day_at, next_day_at.timestamp());
|
assert_eq!(today.next_day_at, next_day_at.timestamp());
|
||||||
|
|
||||||
|
@ -347,7 +327,7 @@ mod test {
|
||||||
crt.offset().utc_minus_local() / 60,
|
crt.offset().utc_minus_local() / 60,
|
||||||
now.timestamp(),
|
now.timestamp(),
|
||||||
now.offset().utc_minus_local() / 60,
|
now.offset().utc_minus_local() / 60,
|
||||||
rollhour as i8,
|
rollhour as u8,
|
||||||
);
|
);
|
||||||
assert_eq!(today.next_day_at, next_day_at.timestamp());
|
assert_eq!(today.next_day_at, next_day_at.timestamp());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,46 @@
|
||||||
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
collection::Collection, config::SchedulerVersion, err::Result, timestamp::TimestampSecs,
|
||||||
|
};
|
||||||
|
|
||||||
pub mod cutoff;
|
pub mod cutoff;
|
||||||
pub mod timespan;
|
pub mod timespan;
|
||||||
|
|
||||||
|
use cutoff::{sched_timing_today, v1_rollover_from_creation_stamp, SchedTimingToday};
|
||||||
|
|
||||||
|
impl Collection {
|
||||||
|
pub fn timing_today(&mut self) -> Result<SchedTimingToday> {
|
||||||
|
self.timing_for_timestamp(TimestampSecs::now())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn timing_for_timestamp(&mut self, now: TimestampSecs) -> Result<SchedTimingToday> {
|
||||||
|
let local_offset = if self.server {
|
||||||
|
self.get_local_mins_west()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(sched_timing_today(
|
||||||
|
self.storage.creation_stamp()?,
|
||||||
|
now,
|
||||||
|
self.get_creation_mins_west(),
|
||||||
|
local_offset,
|
||||||
|
self.get_rollover(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rollover_for_current_scheduler(&self) -> Result<u8> {
|
||||||
|
match self.sched_ver() {
|
||||||
|
SchedulerVersion::V1 => Ok(v1_rollover_from_creation_stamp(
|
||||||
|
self.storage.creation_stamp()?.0,
|
||||||
|
)),
|
||||||
|
SchedulerVersion::V2 => Ok(self.get_rollover().unwrap_or(4)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn learn_cutoff(&self) -> u32 {
|
||||||
|
TimestampSecs::now().0 as u32 + self.learn_ahead_secs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue