mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
Update Chrono Crate (#2242)
* Remove deprecated `and_hms()` * Update chrono * Update licenses and fix script * Remove deprecated Date struct * Remove chrono pin * Skip format check on .vscode Was failing for no reason. * Replace deprecated chrono functions * Add cargo-deny to update-licenses & pin versions (dae) * Remove time 0.1 dependency (dae) We don't need to wait for chrono 0.5; it was provided behind a legacy feature flag.
This commit is contained in:
parent
ef3cfc561c
commit
0e7f02bfb7
13 changed files with 602 additions and 324 deletions
|
@ -11,9 +11,6 @@ unmaintained = "warn"
|
||||||
yanked = "warn"
|
yanked = "warn"
|
||||||
notice = "warn"
|
notice = "warn"
|
||||||
ignore = [
|
ignore = [
|
||||||
# time 0.1, via chrono. Chrono no longer uses the vulnerable code path,
|
|
||||||
# and they plan to drop the dependency for the 0.5 release.
|
|
||||||
"RUSTSEC-2020-0071",
|
|
||||||
# atty: we don't use a custom allocator on Windows, and our deps haven't
|
# atty: we don't use a custom allocator on Windows, and our deps haven't
|
||||||
# updated to alternatives yet
|
# updated to alternatives yet
|
||||||
"RUSTSEC-2021-0145",
|
"RUSTSEC-2021-0145",
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
},
|
},
|
||||||
"includes": ["**/*.{ts,tsx,js,jsx,cjs,mjs,json,md,toml,svelte}"],
|
"includes": ["**/*.{ts,tsx,js,jsx,cjs,mjs,json,md,toml,svelte}"],
|
||||||
"excludes": [
|
"excludes": [
|
||||||
|
".vscode",
|
||||||
"**/node_modules",
|
"**/node_modules",
|
||||||
"out/**",
|
"out/**",
|
||||||
"**/*-lock.json",
|
"**/*-lock.json",
|
||||||
|
|
82
Cargo.lock
generated
82
Cargo.lock
generated
|
@ -407,16 +407,13 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.22"
|
version = "0.4.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
|
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"time 0.1.45",
|
|
||||||
"wasm-bindgen",
|
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -764,9 +761,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxx"
|
name = "cxx"
|
||||||
version = "1.0.82"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453"
|
checksum = "bdf07d07d6531bfcdbe9b8b739b104610c6508dcc4d63b410585faf338241daf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cxxbridge-flags",
|
"cxxbridge-flags",
|
||||||
|
@ -776,9 +773,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxx-build"
|
name = "cxx-build"
|
||||||
version = "1.0.82"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0"
|
checksum = "d2eb5b96ecdc99f72657332953d4d9c50135af1bac34277801cc3937906ebd39"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"codespan-reporting",
|
"codespan-reporting",
|
||||||
|
@ -791,15 +788,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxxbridge-flags"
|
name = "cxxbridge-flags"
|
||||||
version = "1.0.82"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71"
|
checksum = "ac040a39517fd1674e0f32177648334b0f4074625b5588a64519804ba0553b12"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cxxbridge-macro"
|
name = "cxxbridge-macro"
|
||||||
version = "1.0.82"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470"
|
checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1711,9 +1708,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.137"
|
version = "0.2.138"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsqlite3-sys"
|
name = "libsqlite3-sys"
|
||||||
|
@ -2041,9 +2038,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-format"
|
name = "num-format"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "54b862ff8df690cf089058c98b183676a7ed0f974cc08b426800093227cbff3b"
|
checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"itoa 1.0.4",
|
"itoa 1.0.4",
|
||||||
|
@ -2474,7 +2471,7 @@ dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"line-wrap",
|
"line-wrap",
|
||||||
"serde",
|
"serde",
|
||||||
"time 0.3.17",
|
"time",
|
||||||
"xml-rs",
|
"xml-rs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2847,7 +2844,7 @@ checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pem",
|
"pem",
|
||||||
"ring",
|
"ring",
|
||||||
"time 0.3.17",
|
"time",
|
||||||
"yasna",
|
"yasna",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -3170,9 +3167,9 @@ checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.148"
|
version = "1.0.149"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc"
|
checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
@ -3190,9 +3187,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.148"
|
version = "1.0.149"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c"
|
checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -3391,7 +3388,7 @@ dependencies = [
|
||||||
"slog",
|
"slog",
|
||||||
"term",
|
"term",
|
||||||
"thread_local",
|
"thread_local",
|
||||||
"time 0.3.17",
|
"time",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3513,9 +3510,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.104"
|
version = "1.0.105"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce"
|
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -3631,17 +3628,6 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time"
|
|
||||||
version = "0.1.45"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "time"
|
name = "time"
|
||||||
version = "0.3.17"
|
version = "0.3.17"
|
||||||
|
@ -3736,9 +3722,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "1.8.0"
|
version = "1.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
|
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -3879,7 +3865,7 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"p12",
|
"p12",
|
||||||
"rcgen",
|
"rcgen",
|
||||||
"time 0.3.17",
|
"time",
|
||||||
"tugger-common",
|
"tugger-common",
|
||||||
"tugger-windows",
|
"tugger-windows",
|
||||||
"yasna",
|
"yasna",
|
||||||
|
@ -3896,9 +3882,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.15.0"
|
version = "1.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
|
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unic-char-property"
|
name = "unic-char-property"
|
||||||
|
@ -4112,12 +4098,6 @@ version = "0.9.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasi"
|
|
||||||
version = "0.10.0+wasi-snapshot-preview1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
@ -4409,7 +4389,7 @@ dependencies = [
|
||||||
"sha2",
|
"sha2",
|
||||||
"snafu",
|
"snafu",
|
||||||
"syn",
|
"syn",
|
||||||
"time 0.3.17",
|
"time",
|
||||||
"time-macros",
|
"time-macros",
|
||||||
"tokio",
|
"tokio",
|
||||||
"url",
|
"url",
|
||||||
|
@ -4449,7 +4429,7 @@ version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "346d34a236c9d3e5f3b9b74563f238f955bbd05fa0b8b4efa53c130c43982f4c"
|
checksum = "346d34a236c9d3e5f3b9b74563f238f955bbd05fa0b8b4efa53c130c43982f4c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"time 0.3.17",
|
"time",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4468,7 +4448,7 @@ dependencies = [
|
||||||
"hmac",
|
"hmac",
|
||||||
"pbkdf2",
|
"pbkdf2",
|
||||||
"sha1",
|
"sha1",
|
||||||
"time 0.3.17",
|
"time",
|
||||||
"zstd 0.11.2+zstd.1.5.2",
|
"zstd 0.11.2+zstd.1.5.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
cargo-license --features rustls native-tls --json --manifest-path ../rslib/Cargo.toml > licenses.json
|
cargo install cargo-license@0.5.1
|
||||||
|
cargo-license --features rustls --features native-tls --json --manifest-path ../rslib/Cargo.toml >licenses.json
|
||||||
|
|
||||||
|
cargo install cargo-deny@0.13.5
|
||||||
|
(cd .. && cargo deny check -A duplicate)
|
||||||
|
|
|
@ -48,15 +48,13 @@ pct-str = { git = "https://github.com/timothee-haudebourg/pct-str.git", rev = "4
|
||||||
# pinned as any changes could invalidate sqlite indexes
|
# pinned as any changes could invalidate sqlite indexes
|
||||||
unicase = "=2.6.0"
|
unicase = "=2.6.0"
|
||||||
|
|
||||||
# pinned until the deprecation warnings can be addressed
|
|
||||||
chrono = "=0.4.22"
|
|
||||||
|
|
||||||
criterion = { version = "0.4.0", optional = true }
|
criterion = { version = "0.4.0", optional = true }
|
||||||
|
|
||||||
ammonia = "3.3.0"
|
ammonia = "3.3.0"
|
||||||
async-trait = "0.1.59"
|
async-trait = "0.1.59"
|
||||||
blake3 = "1.3.3"
|
blake3 = "1.3.3"
|
||||||
bytes = "1.3.0"
|
bytes = "1.3.0"
|
||||||
|
chrono = { version = "0.4.23", default-features = false, features = ["std", "clock"] }
|
||||||
coarsetime = "0.1.22"
|
coarsetime = "0.1.22"
|
||||||
convert_case = "0.6.0"
|
convert_case = "0.6.0"
|
||||||
dissimilar = "1.0.4"
|
dissimilar = "1.0.4"
|
||||||
|
|
|
@ -104,7 +104,7 @@ fn thin_backups<P: AsRef<Path>>(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let backups =
|
let backups =
|
||||||
read_dir(backup_folder)?.filter_map(|entry| entry.ok().and_then(Backup::from_entry));
|
read_dir(backup_folder)?.filter_map(|entry| entry.ok().and_then(Backup::from_entry));
|
||||||
let obsolete_backups = BackupFilter::new(Local::today(), limits).obsolete_backups(backups);
|
let obsolete_backups = BackupFilter::new(Local::now(), limits).obsolete_backups(backups);
|
||||||
for backup in obsolete_backups {
|
for backup in obsolete_backups {
|
||||||
if let Err(error) = remove_file(&backup.path) {
|
if let Err(error) = remove_file(&backup.path) {
|
||||||
error!(log, "failed to remove {:?}: {error:?}", &backup.path);
|
error!(log, "failed to remove {:?}: {error:?}", &backup.path);
|
||||||
|
@ -176,7 +176,7 @@ enum BackupStage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackupFilter {
|
impl BackupFilter {
|
||||||
fn new(today: Date<Local>, limits: BackupLimits) -> Self {
|
fn new(today: DateTime<Local>, limits: BackupLimits) -> Self {
|
||||||
Self {
|
Self {
|
||||||
yesterday: today.num_days_from_ce() - 1,
|
yesterday: today.num_days_from_ce() - 1,
|
||||||
last_kept_day: i32::MAX,
|
last_kept_day: i32::MAX,
|
||||||
|
@ -262,7 +262,10 @@ mod test {
|
||||||
Backup {
|
Backup {
|
||||||
datetime: Local
|
datetime: Local
|
||||||
.from_local_datetime(
|
.from_local_datetime(
|
||||||
&NaiveDate::from_num_days_from_ce($num_days_from_ce).and_hms(0, 0, 0),
|
&NaiveDate::from_num_days_from_ce_opt($num_days_from_ce)
|
||||||
|
.unwrap()
|
||||||
|
.and_hms_opt(0, 0, 0)
|
||||||
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.latest()
|
.latest()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
@ -271,13 +274,19 @@ mod test {
|
||||||
};
|
};
|
||||||
($year:expr, $month:expr, $day:expr) => {
|
($year:expr, $month:expr, $day:expr) => {
|
||||||
Backup {
|
Backup {
|
||||||
datetime: Local.ymd($year, $month, $day).and_hms(0, 0, 0),
|
datetime: Local
|
||||||
|
.with_ymd_and_hms($year, $month, $day, 0, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap(),
|
||||||
path: PathBuf::new(),
|
path: PathBuf::new(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($year:expr, $month:expr, $day:expr, $hour:expr, $min:expr, $sec:expr) => {
|
($year:expr, $month:expr, $day:expr, $hour:expr, $min:expr, $sec:expr) => {
|
||||||
Backup {
|
Backup {
|
||||||
datetime: Local.ymd($year, $month, $day).and_hms($hour, $min, $sec),
|
datetime: Local
|
||||||
|
.with_ymd_and_hms($year, $month, $day, $hour, $min, $sec)
|
||||||
|
.latest()
|
||||||
|
.unwrap(),
|
||||||
path: PathBuf::new(),
|
path: PathBuf::new(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -285,7 +294,10 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn thinning_manual() {
|
fn thinning_manual() {
|
||||||
let today = Local.ymd(2022, 2, 22);
|
let today = Local
|
||||||
|
.with_ymd_and_hms(2022, 2, 22, 0, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap();
|
||||||
let limits = BackupLimits {
|
let limits = BackupLimits {
|
||||||
daily: 3,
|
daily: 3,
|
||||||
weekly: 2,
|
weekly: 2,
|
||||||
|
@ -328,7 +340,10 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn thinning_generic() {
|
fn thinning_generic() {
|
||||||
let today = Local.ymd(2022, 1, 1);
|
let today = Local
|
||||||
|
.with_ymd_and_hms(2022, 1, 1, 0, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap();
|
||||||
let today_ce_days = today.num_days_from_ce();
|
let today_ce_days = today.num_days_from_ce();
|
||||||
let limits = BackupLimits {
|
let limits = BackupLimits {
|
||||||
// config defaults
|
// config defaults
|
||||||
|
@ -357,7 +372,9 @@ mod test {
|
||||||
// monthly backups from the last day of the month
|
// monthly backups from the last day of the month
|
||||||
for _ in 0..limits.monthly {
|
for _ in 0..limits.monthly {
|
||||||
for backup in backup_iter.by_ref() {
|
for backup in backup_iter.by_ref() {
|
||||||
if backup.datetime.date().month() != backup.datetime.date().succ().month() {
|
if backup.datetime.month()
|
||||||
|
!= backup.datetime.date_naive().succ_opt().unwrap().month()
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
expected.push(backup.clone())
|
expected.push(backup.clone())
|
||||||
|
|
|
@ -89,7 +89,7 @@ impl Collection {
|
||||||
|
|
||||||
if s.new_timezone {
|
if s.new_timezone {
|
||||||
if self.get_creation_utc_offset().is_none() {
|
if self.get_creation_utc_offset().is_none() {
|
||||||
self.set_creation_utc_offset(Some(local_minutes_west_for_stamp(created.0)))?;
|
self.set_creation_utc_offset(Some(local_minutes_west_for_stamp(created)?))?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.set_creation_utc_offset(None)?;
|
self.set_creation_utc_offset(None)?;
|
||||||
|
|
|
@ -71,13 +71,13 @@ impl Collection {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(sched_timing_today(
|
sched_timing_today(
|
||||||
self.storage.creation_stamp()?,
|
self.storage.creation_stamp()?,
|
||||||
now,
|
now,
|
||||||
self.creation_utc_offset(),
|
self.creation_utc_offset(),
|
||||||
current_utc_offset,
|
current_utc_offset,
|
||||||
rollover_hour,
|
rollover_hour,
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// In the client case, return the current local timezone offset,
|
/// In the client case, return the current local timezone offset,
|
||||||
|
@ -88,7 +88,7 @@ impl Collection {
|
||||||
let config_tz = self
|
let config_tz = self
|
||||||
.get_configured_utc_offset()
|
.get_configured_utc_offset()
|
||||||
.and_then(|v| FixedOffset::west_opt(v * 60))
|
.and_then(|v| FixedOffset::west_opt(v * 60))
|
||||||
.unwrap_or_else(|| FixedOffset::west(0));
|
.unwrap_or_else(|| FixedOffset::west_opt(0).unwrap());
|
||||||
|
|
||||||
let local_tz = TimestampSecs::now().local_utc_offset()?;
|
let local_tz = TimestampSecs::now().local_utc_offset()?;
|
||||||
|
|
||||||
|
@ -113,9 +113,7 @@ impl Collection {
|
||||||
|
|
||||||
pub fn rollover_for_current_scheduler(&self) -> Result<u8> {
|
pub fn rollover_for_current_scheduler(&self) -> Result<u8> {
|
||||||
match self.scheduler_version() {
|
match self.scheduler_version() {
|
||||||
SchedulerVersion::V1 => Ok(v1_rollover_from_creation_stamp(
|
SchedulerVersion::V1 => v1_rollover_from_creation_stamp(self.storage.creation_stamp()?),
|
||||||
self.storage.creation_stamp()?.0,
|
|
||||||
)),
|
|
||||||
SchedulerVersion::V2 => Ok(self.get_v2_rollover().unwrap_or(4)),
|
SchedulerVersion::V2 => Ok(self.get_v2_rollover().unwrap_or(4)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +121,7 @@ impl Collection {
|
||||||
pub(crate) fn set_rollover_for_current_scheduler(&mut self, hour: u8) -> Result<()> {
|
pub(crate) fn set_rollover_for_current_scheduler(&mut self, hour: u8) -> Result<()> {
|
||||||
match self.scheduler_version() {
|
match self.scheduler_version() {
|
||||||
SchedulerVersion::V1 => self.set_creation_stamp(TimestampSecs(
|
SchedulerVersion::V1 => self.set_creation_stamp(TimestampSecs(
|
||||||
v1_creation_date_adjusted_to_hour(self.storage.creation_stamp()?.0, hour),
|
v1_creation_date_adjusted_to_hour(self.storage.creation_stamp()?, hour)?,
|
||||||
)),
|
)),
|
||||||
SchedulerVersion::V2 => self.set_v2_rollover(hour as u32),
|
SchedulerVersion::V2 => self.set_v2_rollover(hour as u32),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// 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 chrono::{Date, Duration, FixedOffset, Local, TimeZone, Timelike};
|
use chrono::{DateTime, Datelike, Duration, FixedOffset, Timelike};
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
@ -26,14 +26,13 @@ pub fn sched_timing_today_v2_new(
|
||||||
current_secs: TimestampSecs,
|
current_secs: TimestampSecs,
|
||||||
current_utc_offset: FixedOffset,
|
current_utc_offset: FixedOffset,
|
||||||
rollover_hour: u8,
|
rollover_hour: u8,
|
||||||
) -> SchedTimingToday {
|
) -> Result<SchedTimingToday> {
|
||||||
// get date(times) based on timezone offsets
|
// get date(times) based on timezone offsets
|
||||||
let created_date = creation_secs.datetime(creation_utc_offset).date();
|
let created_datetime = creation_secs.datetime(creation_utc_offset)?;
|
||||||
let now_datetime = current_secs.datetime(current_utc_offset);
|
let now_datetime = current_secs.datetime(current_utc_offset)?;
|
||||||
let today = now_datetime.date();
|
|
||||||
|
|
||||||
// rollover
|
// rollover
|
||||||
let rollover_today_datetime = today.and_hms(rollover_hour as u32, 0, 0);
|
let rollover_today_datetime = rollover_datetime(now_datetime, rollover_hour);
|
||||||
let rollover_passed = rollover_today_datetime <= now_datetime;
|
let rollover_passed = rollover_today_datetime <= now_datetime;
|
||||||
let next_day_at = TimestampSecs(if rollover_passed {
|
let next_day_at = TimestampSecs(if rollover_passed {
|
||||||
(rollover_today_datetime + Duration::days(1)).timestamp()
|
(rollover_today_datetime + Duration::days(1)).timestamp()
|
||||||
|
@ -42,22 +41,33 @@ pub fn sched_timing_today_v2_new(
|
||||||
});
|
});
|
||||||
|
|
||||||
// day count
|
// day count
|
||||||
let days_elapsed = days_elapsed(created_date, today, rollover_passed);
|
let days_elapsed = days_elapsed(created_datetime, now_datetime, rollover_passed);
|
||||||
|
|
||||||
SchedTimingToday {
|
Ok(SchedTimingToday {
|
||||||
now: current_secs,
|
now: current_secs,
|
||||||
days_elapsed,
|
days_elapsed,
|
||||||
next_day_at,
|
next_day_at,
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rollover_datetime(date: DateTime<FixedOffset>, rollover_hour: u8) -> DateTime<FixedOffset> {
|
||||||
|
date.with_hour((rollover_hour % 24) as u32)
|
||||||
|
.unwrap()
|
||||||
|
.with_minute(0)
|
||||||
|
.unwrap()
|
||||||
|
.with_second(0)
|
||||||
|
.unwrap()
|
||||||
|
.with_nanosecond(0)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The number of times the day rolled over between two dates.
|
/// The number of times the day rolled over between two dates.
|
||||||
fn days_elapsed(
|
fn days_elapsed(
|
||||||
start_date: Date<FixedOffset>,
|
start_date: DateTime<FixedOffset>,
|
||||||
end_date: Date<FixedOffset>,
|
end_date: DateTime<FixedOffset>,
|
||||||
rollover_passed: bool,
|
rollover_passed: bool,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
let days = (end_date - start_date).num_days();
|
let days = end_date.num_days_from_ce() - start_date.num_days_from_ce();
|
||||||
|
|
||||||
// current day doesn't count before rollover time
|
// current day doesn't count before rollover time
|
||||||
let days = if rollover_passed { days } else { days - 1 };
|
let days = if rollover_passed { days } else { days - 1 };
|
||||||
|
@ -69,33 +79,33 @@ fn days_elapsed(
|
||||||
/// Build a FixedOffset struct, capping minutes_west if out of bounds.
|
/// Build a FixedOffset struct, capping minutes_west if out of bounds.
|
||||||
pub(crate) fn fixed_offset_from_minutes(minutes_west: i32) -> FixedOffset {
|
pub(crate) 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);
|
||||||
FixedOffset::west(bounded_minutes * 60)
|
FixedOffset::west_opt(bounded_minutes * 60).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For the given timestamp, return minutes west of UTC in the
|
/// For the given timestamp, return minutes west of UTC in the
|
||||||
/// local timezone.
|
/// local timezone.
|
||||||
/// eg, Australia at +10 hours is -600.
|
/// eg, Australia at +10 hours is -600.
|
||||||
/// Includes the daylight savings offset if applicable.
|
/// Includes the daylight savings offset if applicable.
|
||||||
pub fn local_minutes_west_for_stamp(stamp: i64) -> i32 {
|
pub fn local_minutes_west_for_stamp(stamp: TimestampSecs) -> Result<i32> {
|
||||||
Local.timestamp(stamp, 0).offset().utc_minus_local() / 60
|
Ok(stamp.local_datetime()?.offset().utc_minus_local() / 60)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Legacy code
|
// Legacy code
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
|
|
||||||
pub(crate) fn v1_rollover_from_creation_stamp(crt: i64) -> u8 {
|
pub(crate) fn v1_rollover_from_creation_stamp(crt: TimestampSecs) -> Result<u8> {
|
||||||
Local.timestamp(crt, 0).hour() as u8
|
crt.local_datetime().map(|dt| dt.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).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn v1_creation_date_inner(now: TimestampSecs, mins_west: i32) -> i64 {
|
fn v1_creation_date_inner(now: TimestampSecs, mins_west: i32) -> i64 {
|
||||||
let offset = fixed_offset_from_minutes(mins_west);
|
let offset = fixed_offset_from_minutes(mins_west);
|
||||||
let now_dt = offset.timestamp(now.0, 0);
|
let now_dt = now.datetime(offset).unwrap();
|
||||||
let four_am_dt = now_dt.date().and_hms(4, 0, 0);
|
let four_am_dt = rollover_datetime(now_dt, 4);
|
||||||
let four_am_stamp = four_am_dt.timestamp();
|
let four_am_stamp = four_am_dt.timestamp();
|
||||||
|
|
||||||
if four_am_dt > now_dt {
|
if four_am_dt > now_dt {
|
||||||
|
@ -105,17 +115,17 @@ fn v1_creation_date_inner(now: TimestampSecs, mins_west: i32) -> i64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn v1_creation_date_adjusted_to_hour(crt: i64, hour: u8) -> i64 {
|
pub(crate) fn v1_creation_date_adjusted_to_hour(crt: TimestampSecs, hour: u8) -> Result<i64> {
|
||||||
let offset = fixed_offset_from_minutes(local_minutes_west_for_stamp(crt));
|
let offset = fixed_offset_from_minutes(local_minutes_west_for_stamp(crt)?);
|
||||||
v1_creation_date_adjusted_to_hour_inner(crt, hour, offset)
|
v1_creation_date_adjusted_to_hour_inner(crt, hour, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn v1_creation_date_adjusted_to_hour_inner(crt: i64, hour: u8, offset: FixedOffset) -> i64 {
|
fn v1_creation_date_adjusted_to_hour_inner(
|
||||||
offset
|
crt: TimestampSecs,
|
||||||
.timestamp(crt, 0)
|
hour: u8,
|
||||||
.date()
|
offset: FixedOffset,
|
||||||
.and_hms(hour as u32, 0, 0)
|
) -> Result<i64> {
|
||||||
.timestamp()
|
Ok(rollover_datetime(crt.datetime(offset)?, hour).timestamp())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sched_timing_today_v1(crt: TimestampSecs, now: TimestampSecs) -> SchedTimingToday {
|
fn sched_timing_today_v1(crt: TimestampSecs, now: TimestampSecs) -> SchedTimingToday {
|
||||||
|
@ -133,29 +143,22 @@ fn sched_timing_today_v2_legacy(
|
||||||
rollover: u8,
|
rollover: u8,
|
||||||
now: TimestampSecs,
|
now: TimestampSecs,
|
||||||
current_utc_offset: FixedOffset,
|
current_utc_offset: FixedOffset,
|
||||||
) -> SchedTimingToday {
|
) -> Result<SchedTimingToday> {
|
||||||
let crt_at_rollover = crt
|
let crt_at_rollover =
|
||||||
.datetime(current_utc_offset)
|
rollover_datetime(crt.datetime(current_utc_offset)?, rollover).timestamp();
|
||||||
.date()
|
|
||||||
.and_hms(rollover as u32, 0, 0)
|
|
||||||
.timestamp();
|
|
||||||
let days_elapsed = (now.0 - crt_at_rollover) / 86_400;
|
let days_elapsed = (now.0 - crt_at_rollover) / 86_400;
|
||||||
|
|
||||||
let mut next_day_at = TimestampSecs(
|
let mut next_day_at =
|
||||||
now.datetime(current_utc_offset)
|
TimestampSecs(rollover_datetime(now.datetime(current_utc_offset)?, rollover).timestamp());
|
||||||
.date()
|
|
||||||
.and_hms(rollover as u32, 0, 0)
|
|
||||||
.timestamp(),
|
|
||||||
);
|
|
||||||
if next_day_at < now {
|
if next_day_at < now {
|
||||||
next_day_at = next_day_at.adding_secs(86_400);
|
next_day_at = next_day_at.adding_secs(86_400);
|
||||||
}
|
}
|
||||||
|
|
||||||
SchedTimingToday {
|
Ok(SchedTimingToday {
|
||||||
now,
|
now,
|
||||||
days_elapsed: days_elapsed as u32,
|
days_elapsed: days_elapsed as u32,
|
||||||
next_day_at,
|
next_day_at,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
|
@ -168,11 +171,11 @@ pub(crate) fn sched_timing_today(
|
||||||
creation_utc_offset: Option<FixedOffset>,
|
creation_utc_offset: Option<FixedOffset>,
|
||||||
current_utc_offset: FixedOffset,
|
current_utc_offset: FixedOffset,
|
||||||
rollover_hour: Option<u8>,
|
rollover_hour: Option<u8>,
|
||||||
) -> SchedTimingToday {
|
) -> Result<SchedTimingToday> {
|
||||||
match (rollover_hour, creation_utc_offset) {
|
match (rollover_hour, creation_utc_offset) {
|
||||||
(None, _) => {
|
(None, _) => {
|
||||||
// if rollover unset, v1 scheduler
|
// if rollover unset, v1 scheduler
|
||||||
sched_timing_today_v1(creation_secs, current_secs)
|
Ok(sched_timing_today_v1(creation_secs, current_secs))
|
||||||
}
|
}
|
||||||
(Some(rollover), None) => {
|
(Some(rollover), None) => {
|
||||||
// if creationOffset unset, v2 scheduler with legacy cutoff handling
|
// if creationOffset unset, v2 scheduler with legacy cutoff handling
|
||||||
|
@ -193,7 +196,7 @@ pub(crate) fn sched_timing_today(
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use chrono::{FixedOffset, Local, TimeZone, Utc};
|
use chrono::{FixedOffset, Local, TimeZone};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -213,7 +216,7 @@ mod test {
|
||||||
const AEST_MINS_WEST: i32 = -600;
|
const AEST_MINS_WEST: i32 = -600;
|
||||||
|
|
||||||
fn aest_offset() -> FixedOffset {
|
fn aest_offset() -> FixedOffset {
|
||||||
FixedOffset::west(AEST_MINS_WEST * 60)
|
FixedOffset::west_opt(AEST_MINS_WEST * 60).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -226,19 +229,21 @@ mod test {
|
||||||
fn elap(start: i64, end: i64, start_west: i32, end_west: i32, rollhour: u8) -> u32 {
|
fn elap(start: i64, end: i64, start_west: i32, end_west: i32, rollhour: u8) -> u32 {
|
||||||
let start = TimestampSecs(start);
|
let start = TimestampSecs(start);
|
||||||
let end = TimestampSecs(end);
|
let end = TimestampSecs(end);
|
||||||
let start_west = FixedOffset::west(start_west * 60);
|
let start_west = FixedOffset::west_opt(start_west * 60).unwrap();
|
||||||
let end_west = FixedOffset::west(end_west * 60);
|
let end_west = FixedOffset::west_opt(end_west * 60).unwrap();
|
||||||
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).unwrap();
|
||||||
today.days_elapsed
|
today.days_elapsed
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn days_elapsed() {
|
fn days_elapsed() {
|
||||||
let local_offset = local_minutes_west_for_stamp(Utc::now().timestamp());
|
let local_offset = local_minutes_west_for_stamp(TimestampSecs::now()).unwrap();
|
||||||
|
|
||||||
let created_dt = FixedOffset::west(local_offset * 60)
|
let created_dt = FixedOffset::west_opt(local_offset * 60)
|
||||||
.ymd(2019, 12, 1)
|
.unwrap()
|
||||||
.and_hms(2, 0, 0);
|
.with_ymd_and_hms(2019, 12, 1, 2, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap();
|
||||||
let crt = created_dt.timestamp();
|
let crt = created_dt.timestamp();
|
||||||
|
|
||||||
// days can't be negative
|
// days can't be negative
|
||||||
|
@ -261,33 +266,60 @@ mod test {
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|
||||||
let mdt = FixedOffset::west(6 * 60 * 60);
|
let mdt = FixedOffset::west_opt(6 * 60 * 60).unwrap();
|
||||||
let mdt_offset = mdt.utc_minus_local() / 60;
|
let mdt_offset = mdt.utc_minus_local() / 60;
|
||||||
let mst = FixedOffset::west(7 * 60 * 60);
|
let mst = FixedOffset::west_opt(7 * 60 * 60).unwrap();
|
||||||
let mst_offset = mst.utc_minus_local() / 60;
|
let mst_offset = mst.utc_minus_local() / 60;
|
||||||
|
|
||||||
// a collection created @ midnight in MDT in the past
|
// a collection created @ midnight in MDT in the past
|
||||||
let crt = mdt.ymd(2018, 8, 6).and_hms(0, 0, 0).timestamp();
|
let crt = mdt
|
||||||
|
.with_ymd_and_hms(2018, 8, 6, 0, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap()
|
||||||
|
.timestamp();
|
||||||
// with the current time being MST
|
// with the current time being MST
|
||||||
let now = mst.ymd(2019, 12, 26).and_hms(20, 0, 0).timestamp();
|
let now = mst
|
||||||
|
.with_ymd_and_hms(2019, 12, 26, 20, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap()
|
||||||
|
.timestamp();
|
||||||
assert_eq!(elap(crt, now, mdt_offset, mst_offset, 4), 507);
|
assert_eq!(elap(crt, now, mdt_offset, mst_offset, 4), 507);
|
||||||
// the previous implementation generated a different elapsed number of days with a change
|
// the previous implementation generated a different elapsed number of days with a change
|
||||||
// to DST, but the number shouldn't change
|
// to DST, but the number shouldn't change
|
||||||
assert_eq!(elap(crt, now, mdt_offset, mdt_offset, 4), 507);
|
assert_eq!(elap(crt, now, mdt_offset, mdt_offset, 4), 507);
|
||||||
|
|
||||||
// collection created at 3am on the 6th, so day 1 starts at 4am on the 7th, and day 3 on the 9th.
|
// collection created at 3am on the 6th, so day 1 starts at 4am on the 7th, and day 3 on the 9th.
|
||||||
let crt = mdt.ymd(2018, 8, 6).and_hms(3, 0, 0).timestamp();
|
let crt = mdt
|
||||||
let now = mst.ymd(2018, 8, 9).and_hms(1, 59, 59).timestamp();
|
.with_ymd_and_hms(2018, 8, 6, 3, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap()
|
||||||
|
.timestamp();
|
||||||
|
let now = mst
|
||||||
|
.with_ymd_and_hms(2018, 8, 9, 1, 59, 59)
|
||||||
|
.latest()
|
||||||
|
.unwrap()
|
||||||
|
.timestamp();
|
||||||
assert_eq!(elap(crt, now, mdt_offset, mst_offset, 4), 2);
|
assert_eq!(elap(crt, now, mdt_offset, mst_offset, 4), 2);
|
||||||
let now = mst.ymd(2018, 8, 9).and_hms(3, 59, 59).timestamp();
|
let now = mst
|
||||||
|
.with_ymd_and_hms(2018, 8, 9, 3, 59, 59)
|
||||||
|
.latest()
|
||||||
|
.unwrap()
|
||||||
|
.timestamp();
|
||||||
assert_eq!(elap(crt, now, mdt_offset, mst_offset, 4), 2);
|
assert_eq!(elap(crt, now, mdt_offset, mst_offset, 4), 2);
|
||||||
let now = mst.ymd(2018, 8, 9).and_hms(4, 0, 0).timestamp();
|
let now = mst
|
||||||
|
.with_ymd_and_hms(2018, 8, 9, 4, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap()
|
||||||
|
.timestamp();
|
||||||
assert_eq!(elap(crt, now, mdt_offset, mst_offset, 4), 3);
|
assert_eq!(elap(crt, now, mdt_offset, mst_offset, 4), 3);
|
||||||
|
|
||||||
// try a bunch of combinations of creation time, current time, and rollover hour
|
// try a bunch of combinations of creation time, current time, and rollover hour
|
||||||
let hours_of_interest = &[0, 1, 4, 12, 22, 23];
|
let hours_of_interest = &[0, 1, 4, 12, 22, 23];
|
||||||
for creation_hour in hours_of_interest {
|
for creation_hour in hours_of_interest {
|
||||||
let crt_dt = mdt.ymd(2018, 8, 6).and_hms(*creation_hour, 0, 0);
|
let crt_dt = mdt
|
||||||
|
.with_ymd_and_hms(2018, 8, 6, *creation_hour, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap();
|
||||||
let crt_stamp = crt_dt.timestamp();
|
let crt_stamp = crt_dt.timestamp();
|
||||||
let crt_offset = mdt_offset;
|
let crt_offset = mdt_offset;
|
||||||
|
|
||||||
|
@ -295,8 +327,9 @@ mod test {
|
||||||
for current_hour in hours_of_interest {
|
for current_hour in hours_of_interest {
|
||||||
for rollover_hour in hours_of_interest {
|
for rollover_hour in hours_of_interest {
|
||||||
let end_dt = mdt
|
let end_dt = mdt
|
||||||
.ymd(2018, 8, 6 + current_day)
|
.with_ymd_and_hms(2018, 8, 6 + current_day, *current_hour, 0, 0)
|
||||||
.and_hms(*current_hour, 0, 0);
|
.latest()
|
||||||
|
.unwrap();
|
||||||
let end_stamp = end_dt.timestamp();
|
let end_stamp = end_dt.timestamp();
|
||||||
let end_offset = mdt_offset;
|
let end_offset = mdt_offset;
|
||||||
let elap_day = if *current_hour < *rollover_hour {
|
let elap_day = if *current_hour < *rollover_hour {
|
||||||
|
@ -324,42 +357,66 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
fn next_day_at() {
|
fn next_day_at() {
|
||||||
let rollhour = 4;
|
let rollhour = 4;
|
||||||
let crt = Local.ymd(2019, 1, 1).and_hms(2, 0, 0);
|
let crt = Local
|
||||||
|
.with_ymd_and_hms(2019, 1, 1, 2, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// before the rollover, the next day should be later on the same day
|
// before the rollover, the next day should be later on the same day
|
||||||
let now = Local.ymd(2019, 1, 3).and_hms(2, 0, 0);
|
let now = Local
|
||||||
let next_day_at = Local.ymd(2019, 1, 3).and_hms(rollhour, 0, 0);
|
.with_ymd_and_hms(2019, 1, 3, 2, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap();
|
||||||
|
let next_day_at = Local
|
||||||
|
.with_ymd_and_hms(2019, 1, 3, rollhour, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap();
|
||||||
let today = sched_timing_today_v2_new(
|
let today = sched_timing_today_v2_new(
|
||||||
TimestampSecs(crt.timestamp()),
|
TimestampSecs(crt.timestamp()),
|
||||||
*crt.offset(),
|
*crt.offset(),
|
||||||
TimestampSecs(now.timestamp()),
|
TimestampSecs(now.timestamp()),
|
||||||
*now.offset(),
|
*now.offset(),
|
||||||
rollhour as u8,
|
rollhour as u8,
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(today.next_day_at.0, next_day_at.timestamp());
|
assert_eq!(today.next_day_at.0, next_day_at.timestamp());
|
||||||
|
|
||||||
// after the rollover, the next day should be the next day
|
// after the rollover, the next day should be the next day
|
||||||
let now = Local.ymd(2019, 1, 3).and_hms(rollhour, 0, 0);
|
let now = Local
|
||||||
let next_day_at = Local.ymd(2019, 1, 4).and_hms(rollhour, 0, 0);
|
.with_ymd_and_hms(2019, 1, 3, rollhour, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap();
|
||||||
|
let next_day_at = Local
|
||||||
|
.with_ymd_and_hms(2019, 1, 4, rollhour, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap();
|
||||||
let today = sched_timing_today_v2_new(
|
let today = sched_timing_today_v2_new(
|
||||||
TimestampSecs(crt.timestamp()),
|
TimestampSecs(crt.timestamp()),
|
||||||
*crt.offset(),
|
*crt.offset(),
|
||||||
TimestampSecs(now.timestamp()),
|
TimestampSecs(now.timestamp()),
|
||||||
*now.offset(),
|
*now.offset(),
|
||||||
rollhour as u8,
|
rollhour as u8,
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(today.next_day_at.0, next_day_at.timestamp());
|
assert_eq!(today.next_day_at.0, next_day_at.timestamp());
|
||||||
|
|
||||||
// after the rollover, the next day should be the next day
|
// after the rollover, the next day should be the next day
|
||||||
let now = Local.ymd(2019, 1, 3).and_hms(rollhour + 3, 0, 0);
|
let now = Local
|
||||||
let next_day_at = Local.ymd(2019, 1, 4).and_hms(rollhour, 0, 0);
|
.with_ymd_and_hms(2019, 1, 3, rollhour + 3, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap();
|
||||||
|
let next_day_at = Local
|
||||||
|
.with_ymd_and_hms(2019, 1, 4, rollhour, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap();
|
||||||
let today = sched_timing_today_v2_new(
|
let today = sched_timing_today_v2_new(
|
||||||
TimestampSecs(crt.timestamp()),
|
TimestampSecs(crt.timestamp()),
|
||||||
*crt.offset(),
|
*crt.offset(),
|
||||||
TimestampSecs(now.timestamp()),
|
TimestampSecs(now.timestamp()),
|
||||||
*now.offset(),
|
*now.offset(),
|
||||||
rollhour as u8,
|
rollhour as u8,
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(today.next_day_at.0, next_day_at.timestamp());
|
assert_eq!(today.next_day_at.0, next_day_at.timestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,20 +435,20 @@ mod test {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sched_timing_today_v2_legacy(TimestampSecs(1533564000), 0, now, aest_offset()),
|
sched_timing_today_v2_legacy(TimestampSecs(1533564000), 0, now, aest_offset()),
|
||||||
SchedTimingToday {
|
Ok(SchedTimingToday {
|
||||||
now,
|
now,
|
||||||
days_elapsed: 589,
|
days_elapsed: 589,
|
||||||
next_day_at: TimestampSecs(1584540000)
|
next_day_at: TimestampSecs(1584540000)
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sched_timing_today_v2_legacy(TimestampSecs(1524038400), 4, now, aest_offset()),
|
sched_timing_today_v2_legacy(TimestampSecs(1524038400), 4, now, aest_offset()),
|
||||||
SchedTimingToday {
|
Ok(SchedTimingToday {
|
||||||
now,
|
now,
|
||||||
days_elapsed: 700,
|
days_elapsed: 700,
|
||||||
next_day_at: TimestampSecs(1584554400)
|
next_day_at: TimestampSecs(1584554400)
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,26 +456,49 @@ mod test {
|
||||||
fn legacy_creation_stamp() {
|
fn legacy_creation_stamp() {
|
||||||
let offset = fixed_offset_from_minutes(AEST_MINS_WEST);
|
let offset = fixed_offset_from_minutes(AEST_MINS_WEST);
|
||||||
|
|
||||||
let now = TimestampSecs(offset.ymd(2020, 5, 10).and_hms(9, 30, 30).timestamp());
|
let now = TimestampSecs(
|
||||||
|
offset
|
||||||
|
.with_ymd_and_hms(2020, 5, 10, 9, 30, 30)
|
||||||
|
.latest()
|
||||||
|
.unwrap()
|
||||||
|
.timestamp(),
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
v1_creation_date_inner(now, AEST_MINS_WEST),
|
v1_creation_date_inner(now, AEST_MINS_WEST),
|
||||||
offset.ymd(2020, 5, 10).and_hms(4, 0, 0).timestamp()
|
offset
|
||||||
|
.with_ymd_and_hms(2020, 5, 10, 4, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap()
|
||||||
|
.timestamp()
|
||||||
);
|
);
|
||||||
|
|
||||||
let now = TimestampSecs(offset.ymd(2020, 5, 10).and_hms(1, 30, 30).timestamp());
|
let now = TimestampSecs(
|
||||||
|
offset
|
||||||
|
.with_ymd_and_hms(2020, 5, 10, 1, 30, 30)
|
||||||
|
.latest()
|
||||||
|
.unwrap()
|
||||||
|
.timestamp(),
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
v1_creation_date_inner(now, AEST_MINS_WEST),
|
v1_creation_date_inner(now, AEST_MINS_WEST),
|
||||||
offset.ymd(2020, 5, 9).and_hms(4, 0, 0).timestamp()
|
offset
|
||||||
|
.with_ymd_and_hms(2020, 5, 9, 4, 0, 0)
|
||||||
|
.latest()
|
||||||
|
.unwrap()
|
||||||
|
.timestamp()
|
||||||
);
|
);
|
||||||
|
|
||||||
let crt = v1_creation_date_inner(now, AEST_MINS_WEST);
|
let crt = TimestampSecs(v1_creation_date_inner(now, AEST_MINS_WEST));
|
||||||
assert_eq!(crt, v1_creation_date_adjusted_to_hour_inner(crt, 4, offset));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
crt + 3600,
|
Ok(crt.0),
|
||||||
|
v1_creation_date_adjusted_to_hour_inner(crt, 4, offset)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Ok(crt.0 + 3600),
|
||||||
v1_creation_date_adjusted_to_hour_inner(crt, 5, offset)
|
v1_creation_date_adjusted_to_hour_inner(crt, 5, offset)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
crt - 3600 * 4,
|
Ok(crt.0 - 3600 * 4),
|
||||||
v1_creation_date_adjusted_to_hour_inner(crt, 0, offset)
|
v1_creation_date_adjusted_to_hour_inner(crt, 0, offset)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ impl Collection {
|
||||||
// enable new timezone code by default
|
// enable new timezone code by default
|
||||||
let created = self.storage.creation_stamp()?;
|
let created = self.storage.creation_stamp()?;
|
||||||
if self.get_creation_utc_offset().is_none() {
|
if self.get_creation_utc_offset().is_none() {
|
||||||
self.set_creation_utc_offset(Some(local_minutes_west_for_stamp(created.0)))?;
|
self.set_creation_utc_offset(Some(local_minutes_west_for_stamp(created)?))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// force full sync
|
// force full sync
|
||||||
|
|
|
@ -14,11 +14,10 @@ use super::{
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
config::schema11::schema11_config_as_string,
|
config::schema11::schema11_config_as_string,
|
||||||
error::{AnkiError, DbErrorKind, Result},
|
error::DbErrorKind,
|
||||||
i18n::I18n,
|
prelude::*,
|
||||||
scheduler::timing::{local_minutes_west_for_stamp, v1_creation_date},
|
scheduler::timing::{local_minutes_west_for_stamp, v1_creation_date},
|
||||||
text::without_combining,
|
text::without_combining,
|
||||||
timestamp::TimestampMillis,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fn unicase_compare(s1: &str, s2: &str) -> Ordering {
|
fn unicase_compare(s1: &str, s2: &str) -> Ordering {
|
||||||
|
@ -231,11 +230,11 @@ impl SqliteStorage {
|
||||||
if create {
|
if create {
|
||||||
db.execute_batch(include_str!("schema11.sql"))?;
|
db.execute_batch(include_str!("schema11.sql"))?;
|
||||||
// start at schema 11, then upgrade below
|
// start at schema 11, then upgrade below
|
||||||
let crt = v1_creation_date();
|
let crt = TimestampSecs(v1_creation_date());
|
||||||
let offset = if server {
|
let offset = if server {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(local_minutes_west_for_stamp(crt))
|
Some(local_minutes_west_for_stamp(crt)?)
|
||||||
};
|
};
|
||||||
db.execute(
|
db.execute(
|
||||||
"update col set crt=?, scm=?, ver=?, conf=?",
|
"update col set crt=?, scm=?, ver=?, conf=?",
|
||||||
|
|
|
@ -31,17 +31,11 @@ impl TimestampSecs {
|
||||||
TimestampMillis(self.0 * 1000)
|
TimestampMillis(self.0 * 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
pub(crate) fn local_datetime(self) -> Result<DateTime<Local>> {
|
pub(crate) fn local_datetime(self) -> Result<DateTime<Local>> {
|
||||||
std::panic::catch_unwind(|| Local.timestamp(self.0, 0))
|
Local
|
||||||
// discard error as it doesn't satisfiy trait bounds
|
.timestamp_opt(self.0, 0)
|
||||||
.ok()
|
.latest()
|
||||||
.or_invalid("invalid date")
|
.or_invalid("invalid timestamp")
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
pub(crate) fn local_datetime(self) -> Result<DateTime<Local>> {
|
|
||||||
Ok(Local.timestamp(self.0, 0))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// YYYY-mm-dd
|
/// YYYY-mm-dd
|
||||||
|
@ -62,8 +56,11 @@ impl TimestampSecs {
|
||||||
Ok(*self.local_datetime()?.offset())
|
Ok(*self.local_datetime()?.offset())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn datetime(self, utc_offset: FixedOffset) -> DateTime<FixedOffset> {
|
pub fn datetime(self, utc_offset: FixedOffset) -> Result<DateTime<FixedOffset>> {
|
||||||
utc_offset.timestamp(self.0, 0)
|
utc_offset
|
||||||
|
.timestamp_opt(self.0, 0)
|
||||||
|
.latest()
|
||||||
|
.or_invalid("invalid timestamp")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn adding_secs(self, secs: i64) -> Self {
|
pub fn adding_secs(self, secs: i64) -> Self {
|
||||||
|
|
Loading…
Reference in a new issue