mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
_localOffsetForDate() was broken
It was including the elapsed time of day when calculating the offset, leading to incorrect results
This commit is contained in:
parent
fa56477205
commit
12c60f20fe
6 changed files with 43 additions and 27 deletions
|
@ -15,6 +15,7 @@ message BackendInput {
|
|||
FindCardsIn find_cards = 19;
|
||||
BrowserRowsIn browser_rows = 20;
|
||||
RenderCardIn render_card = 21;
|
||||
int64 local_minutes_west = 22;
|
||||
|
||||
PlusOneIn plus_one = 2046; // temporary, for testing
|
||||
}
|
||||
|
@ -28,6 +29,7 @@ message BackendOutput {
|
|||
FindCardsOut find_cards = 19;
|
||||
BrowserRowsOut browser_rows = 20;
|
||||
RenderCardOut render_card = 21;
|
||||
sint32 local_minutes_west = 22;
|
||||
|
||||
PlusOneOut plus_one = 2046; // temporary, for testing
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ class _Collection:
|
|||
elif ver == 2:
|
||||
self.sched = V2Scheduler(self)
|
||||
if not self.server:
|
||||
self.conf["localOffset"] = self.sched.currentTimezoneOffset()
|
||||
self.conf["localOffset"] = self.sched._current_timezone_offset()
|
||||
elif self.server.minutes_west is not None:
|
||||
self.conf["localOffset"] = self.server.minutes_west
|
||||
|
||||
|
@ -162,7 +162,7 @@ class _Collection:
|
|||
if isinstance(self.sched, V1Scheduler):
|
||||
return None
|
||||
else:
|
||||
return self.sched.currentTimezoneOffset()
|
||||
return self.sched._current_timezone_offset()
|
||||
|
||||
# DB-related
|
||||
##########################################################################
|
||||
|
|
|
@ -143,3 +143,8 @@ class RustBackend:
|
|||
anodes = proto_replacement_list_to_native(out.answer_nodes) # type: ignore
|
||||
|
||||
return (qnodes, anodes)
|
||||
|
||||
def local_minutes_west(self, stamp: int) -> int:
|
||||
return self._run_command(
|
||||
pb.BackendInput(local_minutes_west=stamp)
|
||||
).local_minutes_west
|
||||
|
|
|
@ -1340,9 +1340,9 @@ where id = ?
|
|||
|
||||
def _updateCutoff(self) -> None:
|
||||
oldToday = self.today
|
||||
timing = self._timingToday()
|
||||
timing = self._timing_today()
|
||||
|
||||
if self._newTimezoneEnabled():
|
||||
if self._new_timezone_enabled():
|
||||
self.today = timing.days_elapsed
|
||||
self.dayCutoff = timing.next_day_at
|
||||
else:
|
||||
|
@ -1398,41 +1398,40 @@ where id = ?
|
|||
# New timezone handling
|
||||
##########################################################################
|
||||
|
||||
def _newTimezoneEnabled(self) -> bool:
|
||||
def _new_timezone_enabled(self) -> bool:
|
||||
return self.col.conf.get("creationOffset") is not None
|
||||
|
||||
def _timingToday(self) -> SchedTimingToday:
|
||||
def _timing_today(self) -> SchedTimingToday:
|
||||
return self.col.backend.sched_timing_today(
|
||||
self.col.crt,
|
||||
self.creationTimezoneOffset(),
|
||||
self._creation_timezone_offset(),
|
||||
intTime(),
|
||||
self.currentTimezoneOffset(),
|
||||
self._current_timezone_offset(),
|
||||
self._rolloverHour(),
|
||||
)
|
||||
|
||||
def currentTimezoneOffset(self) -> int:
|
||||
def _current_timezone_offset(self) -> int:
|
||||
if self.col.server:
|
||||
return self.col.conf.get("localOffset", 0)
|
||||
else:
|
||||
return self._localOffsetForDate(datetime.datetime.today())
|
||||
return self.col.backend.local_minutes_west(intTime())
|
||||
|
||||
def creationTimezoneOffset(self) -> int:
|
||||
def _creation_timezone_offset(self) -> int:
|
||||
return self.col.conf.get("creationOffset", 0)
|
||||
|
||||
def setCreationOffset(self):
|
||||
def set_creation_offset(self):
|
||||
"""Save the UTC west offset at the time of creation into the DB.
|
||||
|
||||
Once stored, this activates the new timezone handling code.
|
||||
"""
|
||||
mins_west = self._localOffsetForDate(
|
||||
datetime.datetime.fromtimestamp(self.col.crt)
|
||||
)
|
||||
mins_west = self.col.backend.local_minutes_west(self.col.crt)
|
||||
self.col.conf["creationOffset"] = mins_west
|
||||
self.col.setMod()
|
||||
|
||||
def _localOffsetForDate(self, date: datetime.datetime) -> int:
|
||||
"Minutes west of UTC for a given datetime in the local timezone."
|
||||
return date.astimezone().utcoffset().seconds // -60
|
||||
def clear_creation_offset(self):
|
||||
if "creationOffset" in self.col.conf:
|
||||
del self.col.conf["creationOffset"]
|
||||
self.col.setMod()
|
||||
|
||||
# Deck finished state
|
||||
##########################################################################
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::backend_proto as pt;
|
|||
use crate::backend_proto::backend_input::Value;
|
||||
use crate::backend_proto::RenderedTemplateReplacement;
|
||||
use crate::err::{AnkiError, Result};
|
||||
use crate::sched::sched_timing_today;
|
||||
use crate::sched::{local_minutes_west_for_stamp, sched_timing_today};
|
||||
use crate::template::{
|
||||
render_card, without_legacy_template_directives, FieldMap, FieldRequirements, ParsedTemplate,
|
||||
RenderedNode,
|
||||
|
@ -96,6 +96,9 @@ impl Backend {
|
|||
Value::FindCards(_) => todo!(),
|
||||
Value::BrowserRows(_) => todo!(),
|
||||
Value::RenderCard(input) => OValue::RenderCard(self.render_template(input)?),
|
||||
Value::LocalMinutesWest(stamp) => {
|
||||
OValue::LocalMinutesWest(local_minutes_west_for_stamp(stamp))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -82,21 +82,21 @@ fn fixed_offset_from_minutes(minutes_west: i32) -> FixedOffset {
|
|||
FixedOffset::west(bounded_minutes * 60)
|
||||
}
|
||||
|
||||
/// Relative to the local timezone, the number of minutes UTC differs by.
|
||||
/// For the given timestamp, return minutes west of UTC in the
|
||||
/// local timezone.
|
||||
/// eg, Australia at +10 hours is -600.
|
||||
/// Includes the daylight savings offset if applicable.
|
||||
#[allow(dead_code)]
|
||||
fn utc_minus_local_mins() -> i32 {
|
||||
Local::now().offset().utc_minus_local() / 60
|
||||
pub fn local_minutes_west_for_stamp(stamp: i64) -> i32 {
|
||||
Local.timestamp(stamp, 0).offset().utc_minus_local() / 60
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::sched::{
|
||||
fixed_offset_from_minutes, normalized_rollover_hour, sched_timing_today,
|
||||
utc_minus_local_mins,
|
||||
fixed_offset_from_minutes, local_minutes_west_for_stamp, normalized_rollover_hour,
|
||||
sched_timing_today,
|
||||
};
|
||||
use chrono::{FixedOffset, Local, TimeZone};
|
||||
use chrono::{FixedOffset, Local, TimeZone, Utc};
|
||||
|
||||
#[test]
|
||||
fn test_rollover() {
|
||||
|
@ -121,9 +121,16 @@ mod test {
|
|||
today.days_elapsed
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_local_minutes_west() {
|
||||
// -480 throughout the year
|
||||
std::env::set_var("TZ", "Australia/Perth");
|
||||
assert_eq!(local_minutes_west_for_stamp(Utc::now().timestamp()), -480);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_days_elapsed() {
|
||||
let local_offset = utc_minus_local_mins();
|
||||
let local_offset = local_minutes_west_for_stamp(Utc::now().timestamp());
|
||||
|
||||
let created_dt = FixedOffset::west(local_offset * 60)
|
||||
.ymd(2019, 12, 1)
|
||||
|
|
Loading…
Reference in a new issue