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 OptionalInt32 {
|
||||
sint32 val = 1;
|
||||
}
|
||||
|
||||
message BackendInit {
|
||||
repeated string preferred_langs = 1;
|
||||
string locale_folder_path = 2;
|
||||
|
@ -163,10 +167,10 @@ message TemplateRequirementAny {
|
|||
|
||||
message SchedTimingTodayIn {
|
||||
int64 created_secs = 1;
|
||||
sint32 created_mins_west = 2;
|
||||
int64 now_secs = 3;
|
||||
sint32 now_mins_west = 4;
|
||||
sint32 rollover_hour = 5;
|
||||
int64 now_secs = 2;
|
||||
OptionalInt32 created_mins_west = 3;
|
||||
OptionalInt32 now_mins_west = 4;
|
||||
OptionalInt32 rollover_hour = 5;
|
||||
}
|
||||
|
||||
message SchedTimingTodayOut {
|
||||
|
|
|
@ -30,6 +30,7 @@ from anki.fluent_pb2 import FluentString as TR
|
|||
from anki.models import AllTemplateReqs
|
||||
from anki.sound import AVTag, SoundOrVideoTag, TTSTag
|
||||
from anki.types import assert_impossible_literal
|
||||
from anki.utils import intTime
|
||||
|
||||
assert ankirspy.buildhash() == anki.buildinfo.buildhash
|
||||
|
||||
|
@ -276,19 +277,33 @@ class RustBackend:
|
|||
def sched_timing_today(
|
||||
self,
|
||||
created_secs: int,
|
||||
created_mins_west: int,
|
||||
now_secs: int,
|
||||
now_mins_west: int,
|
||||
rollover: 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(
|
||||
pb.BackendInput(
|
||||
sched_timing_today=pb.SchedTimingTodayIn(
|
||||
created_secs=created_secs,
|
||||
created_mins_west=created_mins_west,
|
||||
now_secs=now_secs,
|
||||
now_mins_west=now_mins_west,
|
||||
rollover_hour=rollover,
|
||||
now_secs=intTime(),
|
||||
created_mins_west=crt_west,
|
||||
now_mins_west=now_west,
|
||||
rollover_hour=roll,
|
||||
)
|
||||
)
|
||||
).sched_timing_today
|
||||
|
|
|
@ -867,10 +867,9 @@ did = ?, queue = %s, due = ?, usn = ? where id = ?"""
|
|||
|
||||
def _updateCutoff(self) -> None:
|
||||
oldToday = self.today
|
||||
# days since col created
|
||||
self.today = int((time.time() - self.col.crt) // 86400)
|
||||
# end of day cutoff
|
||||
self.dayCutoff = self.col.crt + (self.today + 1) * 86400
|
||||
timing = self._timing_today()
|
||||
self.today = timing.days_elapsed
|
||||
self.dayCutoff = timing.next_day_at
|
||||
if oldToday != self.today:
|
||||
self.col.log(self.today, self.dayCutoff)
|
||||
# update all daily counts, but don't save decks to prevent needless
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
import itertools
|
||||
import random
|
||||
import time
|
||||
|
@ -1353,13 +1352,8 @@ where id = ?
|
|||
def _updateCutoff(self) -> None:
|
||||
oldToday = self.today
|
||||
timing = self._timing_today()
|
||||
|
||||
if self._new_timezone_enabled():
|
||||
self.today = timing.days_elapsed
|
||||
self.dayCutoff = timing.next_day_at
|
||||
else:
|
||||
self.today = self._daysSinceCreation()
|
||||
self.dayCutoff = self._dayCutoff()
|
||||
self.today = timing.days_elapsed
|
||||
self.dayCutoff = timing.next_day_at
|
||||
|
||||
if oldToday != self.today:
|
||||
self.col.log(self.today, self.dayCutoff)
|
||||
|
@ -1385,51 +1379,28 @@ where id = ?
|
|||
if time.time() > self.dayCutoff:
|
||||
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:
|
||||
return self.col.conf.get("rollover", 4)
|
||||
|
||||
# New timezone handling
|
||||
##########################################################################
|
||||
|
||||
def _new_timezone_enabled(self) -> bool:
|
||||
return self.col.conf.get("creationOffset") is not None
|
||||
|
||||
def _timing_today(self) -> SchedTimingToday:
|
||||
return self.col.backend.sched_timing_today(
|
||||
self.col.crt,
|
||||
self._creation_timezone_offset(),
|
||||
intTime(),
|
||||
self._current_timezone_offset(),
|
||||
self._rolloverHour(),
|
||||
)
|
||||
|
||||
def _current_timezone_offset(self) -> int:
|
||||
def _current_timezone_offset(self) -> Optional[int]:
|
||||
if self.col.server:
|
||||
return self.col.conf.get("localOffset", 0)
|
||||
return self.col.conf.get("localOffset", None)
|
||||
else:
|
||||
return self.col.backend.local_minutes_west(intTime())
|
||||
return None
|
||||
|
||||
def _creation_timezone_offset(self) -> int:
|
||||
return self.col.conf.get("creationOffset", 0)
|
||||
def _creation_timezone_offset(self) -> Optional[int]:
|
||||
return self.col.conf.get("creationOffset", None)
|
||||
|
||||
def set_creation_offset(self):
|
||||
"""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::sync::MediaSyncProgress;
|
||||
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::search::{search_cards, search_notes, SortMode};
|
||||
use crate::template::{
|
||||
|
@ -350,12 +350,12 @@ impl Backend {
|
|||
}
|
||||
|
||||
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_mins_west,
|
||||
input.now_secs as i64,
|
||||
input.now_mins_west,
|
||||
input.rollover_hour as i8,
|
||||
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,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// 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};
|
||||
|
||||
#[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.
|
||||
pub(crate) fn sched_timing_today(
|
||||
created_secs: i64,
|
||||
now_secs: i64,
|
||||
created_mins_west: Option<i32>,
|
||||
now_mins_west: Option<i32>,
|
||||
rollover_hour: Option<i8>,
|
||||
) -> SchedTimingToday {
|
||||
let now = i64_unix_secs();
|
||||
|
||||
match (rollover_hour, created_mins_west) {
|
||||
(None, _) => {
|
||||
// if rollover unset, v1 scheduler
|
||||
sched_timing_today_v1(created_secs, now)
|
||||
sched_timing_today_v1(created_secs, now_secs)
|
||||
}
|
||||
(Some(roll), None) => {
|
||||
// if creation offset unset, v2 legacy cutoff using local timezone
|
||||
let offset = local_minutes_west_for_stamp(now);
|
||||
sched_timing_today_v2_legacy(created_secs, roll, now, offset)
|
||||
let offset = local_minutes_west_for_stamp(now_secs);
|
||||
sched_timing_today_v2_legacy(created_secs, roll, now_secs, offset)
|
||||
}
|
||||
(Some(roll), Some(crt_west)) => {
|
||||
// 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));
|
||||
sched_timing_today_v2_new(created_secs, crt_west, now, now_west, roll)
|
||||
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_secs, now_west, roll)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -324,6 +324,7 @@ impl StorageContext<'_> {
|
|||
|
||||
self.timing_today = Some(sched_timing_today(
|
||||
crt,
|
||||
i64_unix_secs(),
|
||||
conf.creation_offset,
|
||||
now_offset,
|
||||
conf.rollover,
|
||||
|
|
Loading…
Reference in a new issue