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:
Damien Elmes 2020-03-22 14:15:02 +10:00
parent c5629e96df
commit 69d8cdd9ed
7 changed files with 53 additions and 65 deletions

View file

@ -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 {

View file

@ -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

View file

@ -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

View file

@ -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()
if self._new_timezone_enabled():
self.today = timing.days_elapsed self.today = timing.days_elapsed
self.dayCutoff = timing.next_day_at 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.

View file

@ -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,

View file

@ -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)
} }
} }
} }

View file

@ -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,