mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
use backend for v1 and v2 cutoff calculations
this should also fix the CI failures, which were happening because the datetime module wasn't matching the shifted time.time()
This commit is contained in:
parent
c5629e96df
commit
69d8cdd9ed
7 changed files with 53 additions and 65 deletions
|
@ -6,6 +6,10 @@ package backend_proto;
|
||||||
|
|
||||||
message Empty {}
|
message Empty {}
|
||||||
|
|
||||||
|
message OptionalInt32 {
|
||||||
|
sint32 val = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message BackendInit {
|
message BackendInit {
|
||||||
repeated string preferred_langs = 1;
|
repeated string preferred_langs = 1;
|
||||||
string locale_folder_path = 2;
|
string locale_folder_path = 2;
|
||||||
|
@ -163,10 +167,10 @@ message TemplateRequirementAny {
|
||||||
|
|
||||||
message SchedTimingTodayIn {
|
message SchedTimingTodayIn {
|
||||||
int64 created_secs = 1;
|
int64 created_secs = 1;
|
||||||
sint32 created_mins_west = 2;
|
int64 now_secs = 2;
|
||||||
int64 now_secs = 3;
|
OptionalInt32 created_mins_west = 3;
|
||||||
sint32 now_mins_west = 4;
|
OptionalInt32 now_mins_west = 4;
|
||||||
sint32 rollover_hour = 5;
|
OptionalInt32 rollover_hour = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message SchedTimingTodayOut {
|
message SchedTimingTodayOut {
|
||||||
|
|
|
@ -30,6 +30,7 @@ from anki.fluent_pb2 import FluentString as TR
|
||||||
from anki.models import AllTemplateReqs
|
from anki.models import AllTemplateReqs
|
||||||
from anki.sound import AVTag, SoundOrVideoTag, TTSTag
|
from anki.sound import AVTag, SoundOrVideoTag, TTSTag
|
||||||
from anki.types import assert_impossible_literal
|
from anki.types import assert_impossible_literal
|
||||||
|
from anki.utils import intTime
|
||||||
|
|
||||||
assert ankirspy.buildhash() == anki.buildinfo.buildhash
|
assert ankirspy.buildhash() == anki.buildinfo.buildhash
|
||||||
|
|
||||||
|
@ -276,19 +277,33 @@ class RustBackend:
|
||||||
def sched_timing_today(
|
def sched_timing_today(
|
||||||
self,
|
self,
|
||||||
created_secs: int,
|
created_secs: int,
|
||||||
created_mins_west: int,
|
created_mins_west: Optional[int],
|
||||||
now_secs: int,
|
now_mins_west: Optional[int],
|
||||||
now_mins_west: int,
|
rollover: Optional[int],
|
||||||
rollover: int,
|
|
||||||
) -> SchedTimingToday:
|
) -> 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.SchedTimingTodayIn(
|
sched_timing_today=pb.SchedTimingTodayIn(
|
||||||
created_secs=created_secs,
|
created_secs=created_secs,
|
||||||
created_mins_west=created_mins_west,
|
now_secs=intTime(),
|
||||||
now_secs=now_secs,
|
created_mins_west=crt_west,
|
||||||
now_mins_west=now_mins_west,
|
now_mins_west=now_west,
|
||||||
rollover_hour=rollover,
|
rollover_hour=roll,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).sched_timing_today
|
).sched_timing_today
|
||||||
|
|
|
@ -867,10 +867,9 @@ did = ?, queue = %s, due = ?, usn = ? where id = ?"""
|
||||||
|
|
||||||
def _updateCutoff(self) -> None:
|
def _updateCutoff(self) -> None:
|
||||||
oldToday = self.today
|
oldToday = self.today
|
||||||
# days since col created
|
timing = self._timing_today()
|
||||||
self.today = int((time.time() - self.col.crt) // 86400)
|
self.today = timing.days_elapsed
|
||||||
# end of day cutoff
|
self.dayCutoff = timing.next_day_at
|
||||||
self.dayCutoff = self.col.crt + (self.today + 1) * 86400
|
|
||||||
if oldToday != self.today:
|
if oldToday != self.today:
|
||||||
self.col.log(self.today, self.dayCutoff)
|
self.col.log(self.today, self.dayCutoff)
|
||||||
# update all daily counts, but don't save decks to prevent needless
|
# update all daily counts, but don't save decks to prevent needless
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import datetime
|
|
||||||
import itertools
|
import itertools
|
||||||
import random
|
import random
|
||||||
import time
|
import time
|
||||||
|
@ -1353,13 +1352,8 @@ where id = ?
|
||||||
def _updateCutoff(self) -> None:
|
def _updateCutoff(self) -> None:
|
||||||
oldToday = self.today
|
oldToday = self.today
|
||||||
timing = self._timing_today()
|
timing = self._timing_today()
|
||||||
|
self.today = timing.days_elapsed
|
||||||
if self._new_timezone_enabled():
|
self.dayCutoff = timing.next_day_at
|
||||||
self.today = timing.days_elapsed
|
|
||||||
self.dayCutoff = timing.next_day_at
|
|
||||||
else:
|
|
||||||
self.today = self._daysSinceCreation()
|
|
||||||
self.dayCutoff = self._dayCutoff()
|
|
||||||
|
|
||||||
if oldToday != self.today:
|
if oldToday != self.today:
|
||||||
self.col.log(self.today, self.dayCutoff)
|
self.col.log(self.today, self.dayCutoff)
|
||||||
|
@ -1385,51 +1379,28 @@ where id = ?
|
||||||
if time.time() > self.dayCutoff:
|
if time.time() > self.dayCutoff:
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def _dayCutoff(self) -> int:
|
|
||||||
rolloverTime = self.col.conf.get("rollover", 4)
|
|
||||||
if rolloverTime < 0:
|
|
||||||
rolloverTime = 24 + rolloverTime
|
|
||||||
date = datetime.datetime.today()
|
|
||||||
date = date.replace(hour=rolloverTime, minute=0, second=0, microsecond=0)
|
|
||||||
if date < datetime.datetime.today():
|
|
||||||
date = date + datetime.timedelta(days=1)
|
|
||||||
|
|
||||||
stamp = int(time.mktime(date.timetuple()))
|
|
||||||
return stamp
|
|
||||||
|
|
||||||
def _daysSinceCreation(self) -> int:
|
|
||||||
startDate = datetime.datetime.fromtimestamp(self.col.crt)
|
|
||||||
startDate = startDate.replace(
|
|
||||||
hour=self._rolloverHour(), minute=0, second=0, microsecond=0
|
|
||||||
)
|
|
||||||
return int((time.time() - time.mktime(startDate.timetuple())) // 86400)
|
|
||||||
|
|
||||||
def _rolloverHour(self) -> int:
|
def _rolloverHour(self) -> int:
|
||||||
return self.col.conf.get("rollover", 4)
|
return self.col.conf.get("rollover", 4)
|
||||||
|
|
||||||
# New timezone handling
|
# New timezone handling
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
def _new_timezone_enabled(self) -> bool:
|
|
||||||
return self.col.conf.get("creationOffset") is not None
|
|
||||||
|
|
||||||
def _timing_today(self) -> SchedTimingToday:
|
def _timing_today(self) -> SchedTimingToday:
|
||||||
return self.col.backend.sched_timing_today(
|
return self.col.backend.sched_timing_today(
|
||||||
self.col.crt,
|
self.col.crt,
|
||||||
self._creation_timezone_offset(),
|
self._creation_timezone_offset(),
|
||||||
intTime(),
|
|
||||||
self._current_timezone_offset(),
|
self._current_timezone_offset(),
|
||||||
self._rolloverHour(),
|
self._rolloverHour(),
|
||||||
)
|
)
|
||||||
|
|
||||||
def _current_timezone_offset(self) -> int:
|
def _current_timezone_offset(self) -> Optional[int]:
|
||||||
if self.col.server:
|
if self.col.server:
|
||||||
return self.col.conf.get("localOffset", 0)
|
return self.col.conf.get("localOffset", None)
|
||||||
else:
|
else:
|
||||||
return self.col.backend.local_minutes_west(intTime())
|
return None
|
||||||
|
|
||||||
def _creation_timezone_offset(self) -> int:
|
def _creation_timezone_offset(self) -> Optional[int]:
|
||||||
return self.col.conf.get("creationOffset", 0)
|
return self.col.conf.get("creationOffset", None)
|
||||||
|
|
||||||
def set_creation_offset(self):
|
def set_creation_offset(self):
|
||||||
"""Save the UTC west offset at the time of creation into the DB.
|
"""Save the UTC west offset at the time of creation into the DB.
|
||||||
|
|
|
@ -13,7 +13,7 @@ use crate::log::{default_logger, Logger};
|
||||||
use crate::media::check::MediaChecker;
|
use crate::media::check::MediaChecker;
|
||||||
use crate::media::sync::MediaSyncProgress;
|
use crate::media::sync::MediaSyncProgress;
|
||||||
use crate::media::MediaManager;
|
use crate::media::MediaManager;
|
||||||
use crate::sched::cutoff::{local_minutes_west_for_stamp, sched_timing_today_v2_new};
|
use crate::sched::cutoff::{local_minutes_west_for_stamp, sched_timing_today};
|
||||||
use crate::sched::timespan::{answer_button_time, learning_congrats, studied_today, time_span};
|
use crate::sched::timespan::{answer_button_time, learning_congrats, studied_today, time_span};
|
||||||
use crate::search::{search_cards, search_notes, SortMode};
|
use crate::search::{search_cards, search_notes, SortMode};
|
||||||
use crate::template::{
|
use crate::template::{
|
||||||
|
@ -350,12 +350,12 @@ impl Backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sched_timing_today(&self, input: pb::SchedTimingTodayIn) -> pb::SchedTimingTodayOut {
|
fn sched_timing_today(&self, input: pb::SchedTimingTodayIn) -> pb::SchedTimingTodayOut {
|
||||||
let today = sched_timing_today_v2_new(
|
let today = sched_timing_today(
|
||||||
input.created_secs as i64,
|
input.created_secs as i64,
|
||||||
input.created_mins_west,
|
|
||||||
input.now_secs as i64,
|
input.now_secs as i64,
|
||||||
input.now_mins_west,
|
input.created_mins_west.map(|v| v.val),
|
||||||
input.rollover_hour as i8,
|
input.now_mins_west.map(|v| v.val),
|
||||||
|
input.rollover_hour.map(|v| v.val as i8),
|
||||||
);
|
);
|
||||||
pb::SchedTimingTodayOut {
|
pb::SchedTimingTodayOut {
|
||||||
days_elapsed: today.days_elapsed,
|
days_elapsed: today.days_elapsed,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright: Ankitects Pty Ltd and contributors
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
// 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::time::i64_unix_secs;
|
|
||||||
use chrono::{Date, Duration, FixedOffset, Local, TimeZone};
|
use chrono::{Date, Duration, FixedOffset, Local, TimeZone};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
|
@ -140,26 +139,25 @@ fn sched_timing_today_v2_legacy(
|
||||||
/// Based on provided input, get timing info from the relevant function.
|
/// Based on provided input, get timing info from the relevant function.
|
||||||
pub(crate) fn sched_timing_today(
|
pub(crate) fn sched_timing_today(
|
||||||
created_secs: i64,
|
created_secs: i64,
|
||||||
|
now_secs: i64,
|
||||||
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<i8>,
|
||||||
) -> SchedTimingToday {
|
) -> SchedTimingToday {
|
||||||
let now = i64_unix_secs();
|
|
||||||
|
|
||||||
match (rollover_hour, created_mins_west) {
|
match (rollover_hour, created_mins_west) {
|
||||||
(None, _) => {
|
(None, _) => {
|
||||||
// if rollover unset, v1 scheduler
|
// if rollover unset, v1 scheduler
|
||||||
sched_timing_today_v1(created_secs, now)
|
sched_timing_today_v1(created_secs, now_secs)
|
||||||
}
|
}
|
||||||
(Some(roll), None) => {
|
(Some(roll), None) => {
|
||||||
// if creation offset unset, v2 legacy cutoff using local timezone
|
// if creation offset unset, v2 legacy cutoff using local timezone
|
||||||
let offset = local_minutes_west_for_stamp(now);
|
let offset = local_minutes_west_for_stamp(now_secs);
|
||||||
sched_timing_today_v2_legacy(created_secs, roll, now, offset)
|
sched_timing_today_v2_legacy(created_secs, roll, now_secs, offset)
|
||||||
}
|
}
|
||||||
(Some(roll), Some(crt_west)) => {
|
(Some(roll), Some(crt_west)) => {
|
||||||
// new cutoff code, using provided current timezone, falling back on local timezone
|
// new cutoff code, using provided current timezone, falling back on local timezone
|
||||||
let now_west = now_mins_west.unwrap_or_else(|| local_minutes_west_for_stamp(now));
|
let now_west = now_mins_west.unwrap_or_else(|| local_minutes_west_for_stamp(now_secs));
|
||||||
sched_timing_today_v2_new(created_secs, crt_west, now, now_west, roll)
|
sched_timing_today_v2_new(created_secs, crt_west, now_secs, now_west, roll)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,6 +324,7 @@ impl StorageContext<'_> {
|
||||||
|
|
||||||
self.timing_today = Some(sched_timing_today(
|
self.timing_today = Some(sched_timing_today(
|
||||||
crt,
|
crt,
|
||||||
|
i64_unix_secs(),
|
||||||
conf.creation_offset,
|
conf.creation_offset,
|
||||||
now_offset,
|
now_offset,
|
||||||
conf.rollover,
|
conf.rollover,
|
||||||
|
|
Loading…
Reference in a new issue