chore: use jiff instead of chrono where possible
`chrono` can't fully be removed until `sunrise` supports `jiff`. Also updates `sunrise` and adapts to changes by handling polar days.
This commit is contained in:
parent
2019f1c33c
commit
91e14abe49
7 changed files with 124 additions and 43 deletions
63
Cargo.lock
generated
63
Cargo.lock
generated
|
|
@ -1482,7 +1482,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cosmic-comp-config"
|
name = "cosmic-comp-config"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
source = "git+https://github.com/pop-os/cosmic-comp?branch=action-on-typing#df7819b2b24bb6b66ca97a2456572410f3e05521"
|
source = "git+https://github.com/pop-os/cosmic-comp#ef14b7e29469c4dc066e1c8cf096868d08213caf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cosmic-config",
|
"cosmic-config",
|
||||||
"input",
|
"input",
|
||||||
|
|
@ -1703,6 +1703,7 @@ dependencies = [
|
||||||
"indexmap 2.13.0",
|
"indexmap 2.13.0",
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
"itoa",
|
"itoa",
|
||||||
|
"jiff",
|
||||||
"libcosmic",
|
"libcosmic",
|
||||||
"locale1",
|
"locale1",
|
||||||
"locales-rs",
|
"locales-rs",
|
||||||
|
|
@ -4268,6 +4269,47 @@ version = "0.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84de9d95a6d2547d9b77ee3f25fa0ee32e3c3a6484d47a55adebc0439c077992"
|
checksum = "84de9d95a6d2547d9b77ee3f25fa0ee32e3c3a6484d47a55adebc0439c077992"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff"
|
||||||
|
version = "0.2.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c867c356cc096b33f4981825ab281ecba3db0acefe60329f044c1789d94c6543"
|
||||||
|
dependencies = [
|
||||||
|
"jiff-static",
|
||||||
|
"jiff-tzdb-platform",
|
||||||
|
"log",
|
||||||
|
"portable-atomic",
|
||||||
|
"portable-atomic-util",
|
||||||
|
"serde_core",
|
||||||
|
"windows-sys 0.61.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-static"
|
||||||
|
version = "0.2.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7946b4325269738f270bb55b3c19ab5c5040525f83fd625259422a9d25d9be5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.114",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-tzdb"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68971ebff725b9e2ca27a601c5eb38a4c5d64422c4cbab0c535f248087eda5c2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-tzdb-platform"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8"
|
||||||
|
dependencies = [
|
||||||
|
"jiff-tzdb",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jni"
|
name = "jni"
|
||||||
version = "0.21.1"
|
version = "0.21.1"
|
||||||
|
|
@ -6053,6 +6095,21 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3"
|
checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic-util"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5"
|
||||||
|
dependencies = [
|
||||||
|
"portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "potential_utf"
|
name = "potential_utf"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
|
@ -7261,9 +7318,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sunrise"
|
name = "sunrise"
|
||||||
version = "2.1.0"
|
version = "3.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0733c9f1eaa06ed6d103d88e21f784449d08a6733c2ca2b39381cbcbcfe89272"
|
checksum = "15eecb5ec59a060dd9fe8f88c48b701abecd6be9d9c28d55081b80bdda73981c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ default-members = ["cosmic-settings"]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
rust-version = "1.85"
|
rust-version = "1.90"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
cosmic-randr = { git = "https://github.com/pop-os/cosmic-randr" }
|
cosmic-randr = { git = "https://github.com/pop-os/cosmic-randr" }
|
||||||
|
|
@ -22,7 +22,6 @@ git = "https://github.com/pop-os/cosmic-bg"
|
||||||
|
|
||||||
[workspace.dependencies.cosmic-comp-config]
|
[workspace.dependencies.cosmic-comp-config]
|
||||||
git = "https://github.com/pop-os/cosmic-comp"
|
git = "https://github.com/pop-os/cosmic-comp"
|
||||||
branch = "action-on-typing"
|
|
||||||
features = ["output"]
|
features = ["output"]
|
||||||
|
|
||||||
[workspace.dependencies.cosmic-idle-config]
|
[workspace.dependencies.cosmic-idle-config]
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@ anyhow = "1.0"
|
||||||
ashpd = { version = "0.12", default-features = false, features = [
|
ashpd = { version = "0.12", default-features = false, features = [
|
||||||
"tokio",
|
"tokio",
|
||||||
], optional = true }
|
], optional = true }
|
||||||
chrono = "0.4.42"
|
chrono = "0.4"
|
||||||
|
jiff = "0.2"
|
||||||
clap = { version = "4.5.54", features = ["derive"] }
|
clap = { version = "4.5.54", features = ["derive"] }
|
||||||
color-eyre = "0.6.5"
|
color-eyre = "0.6.5"
|
||||||
cosmic-bg-config.workspace = true
|
cosmic-bg-config.workspace = true
|
||||||
|
|
@ -69,7 +70,7 @@ serde = { version = "1.0.228", features = ["derive"] }
|
||||||
slab = "0.4.11"
|
slab = "0.4.11"
|
||||||
slotmap = "1.1.1"
|
slotmap = "1.1.1"
|
||||||
static_init = "1.0.4"
|
static_init = "1.0.4"
|
||||||
sunrise = "2.1.0"
|
sunrise = "3.0.0"
|
||||||
timedate-zbus = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
|
timedate-zbus = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true }
|
||||||
tokio = { workspace = true, features = ["fs", "io-util", "process", "sync"] }
|
tokio = { workspace = true, features = ["fs", "io-util", "process", "sync"] }
|
||||||
tracing = "0.1.44"
|
tracing = "0.1.44"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use chrono::{Duration, TimeDelta};
|
|
||||||
use futures::{FutureExt, Stream, StreamExt, future::join_all};
|
use futures::{FutureExt, Stream, StreamExt, future::join_all};
|
||||||
|
use jiff::{Span, SpanRelativeTo, SpanRound, ToSpan, Unit};
|
||||||
use upower_dbus::{BatteryState, BatteryType, DeviceProxy};
|
use upower_dbus::{BatteryState, BatteryType, DeviceProxy};
|
||||||
use zbus::{Connection, zvariant::ObjectPath};
|
use zbus::{Connection, zvariant::ObjectPath};
|
||||||
|
|
||||||
|
|
@ -233,7 +233,7 @@ pub struct Battery {
|
||||||
pub is_present: bool,
|
pub is_present: bool,
|
||||||
pub percent: f64,
|
pub percent: f64,
|
||||||
pub is_charging: bool,
|
pub is_charging: bool,
|
||||||
pub remaining_duration: Duration,
|
pub remaining_duration: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
|
|
@ -302,7 +302,7 @@ async fn enumerate_devices<'a>() -> Result<Vec<upower_dbus::DeviceProxy<'a>>, zb
|
||||||
|
|
||||||
impl Battery {
|
impl Battery {
|
||||||
pub async fn from_device(proxy: &DeviceProxy<'_>) -> Self {
|
pub async fn from_device(proxy: &DeviceProxy<'_>) -> Self {
|
||||||
let mut remaining_duration: Duration = Duration::default();
|
let mut remaining_duration = Span::default();
|
||||||
|
|
||||||
let (is_present, percentage, battery_state) = futures::join!(
|
let (is_present, percentage, battery_state) = futures::join!(
|
||||||
proxy.is_present().map(Result::unwrap_or_default),
|
proxy.is_present().map(Result::unwrap_or_default),
|
||||||
|
|
@ -319,15 +319,11 @@ impl Battery {
|
||||||
&& (percent - 100.0_f64).abs() < f64::EPSILON;
|
&& (percent - 100.0_f64).abs() < f64::EPSILON;
|
||||||
|
|
||||||
if !is_charging {
|
if !is_charging {
|
||||||
if let Ok(time) = proxy.time_to_empty().await
|
if let Ok(time) = proxy.time_to_empty().await {
|
||||||
&& let Ok(dur) = Duration::from_std(std::time::Duration::from_secs(time as u64))
|
remaining_duration = time.seconds();
|
||||||
{
|
|
||||||
remaining_duration = dur;
|
|
||||||
}
|
}
|
||||||
} else if let Ok(time) = proxy.time_to_full().await
|
} else if let Ok(time) = proxy.time_to_full().await {
|
||||||
&& let Ok(dur) = Duration::from_std(std::time::Duration::from_secs(time as u64))
|
remaining_duration = time.seconds();
|
||||||
{
|
|
||||||
remaining_duration = dur;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let battery_percent = if percent > 95.0 {
|
let battery_percent = if percent > 95.0 {
|
||||||
|
|
@ -378,15 +374,22 @@ impl Battery {
|
||||||
Battery::default()
|
Battery::default()
|
||||||
}
|
}
|
||||||
pub fn remaining_time(&self) -> String {
|
pub fn remaining_time(&self) -> String {
|
||||||
if self.remaining_duration <= TimeDelta::zero() {
|
if !self.remaining_duration.is_positive() {
|
||||||
return String::new();
|
return String::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
let total_seconds = self.remaining_duration.num_seconds();
|
let balanced = self
|
||||||
|
.remaining_duration
|
||||||
|
.round(
|
||||||
|
SpanRound::new()
|
||||||
|
.largest(Unit::Day)
|
||||||
|
.relative(SpanRelativeTo::days_are_24_hours()),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let days = total_seconds / 86400;
|
let days = balanced.get_days();
|
||||||
let hours = total_seconds % 86400 / 3600;
|
let hours = balanced.get_hours();
|
||||||
let minutes = (total_seconds % 3600) / 60;
|
let minutes = balanced.get_minutes();
|
||||||
|
|
||||||
let mut time: Vec<String> = Vec::new();
|
let mut time: Vec<String> = Vec::new();
|
||||||
if days > 0 {
|
if days > 0 {
|
||||||
|
|
@ -546,7 +549,7 @@ mod tests {
|
||||||
for case in cases {
|
for case in cases {
|
||||||
let (actual, expected) = case;
|
let (actual, expected) = case;
|
||||||
let battery = Battery {
|
let battery = Battery {
|
||||||
remaining_duration: Duration::new(actual, 0).unwrap(),
|
remaining_duration: actual.seconds(),
|
||||||
is_charging: false,
|
is_charging: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ mod backend;
|
||||||
use self::backend::{GetCurrentPowerProfile, SetPowerProfile};
|
use self::backend::{GetCurrentPowerProfile, SetPowerProfile};
|
||||||
use backend::{Battery, ConnectedDevice, PowerProfile};
|
use backend::{Battery, ConnectedDevice, PowerProfile};
|
||||||
|
|
||||||
use chrono::TimeDelta;
|
|
||||||
use cosmic::iced::{self, Alignment, Length};
|
use cosmic::iced::{self, Alignment, Length};
|
||||||
use cosmic::iced_widget::{column, row};
|
use cosmic::iced_widget::{column, row};
|
||||||
use cosmic::widget::{self, radio, settings, text};
|
use cosmic::widget::{self, radio, settings, text};
|
||||||
|
|
@ -423,7 +422,7 @@ fn connected_devices() -> Section<crate::pages::Message> {
|
||||||
widget::icon::from_name(connected_device.battery.icon_name.clone());
|
widget::icon::from_name(connected_device.battery.icon_name.clone());
|
||||||
|
|
||||||
let battery_percent_and_time = widget::text(
|
let battery_percent_and_time = widget::text(
|
||||||
if connected_device.battery.remaining_duration > TimeDelta::zero() {
|
if connected_device.battery.remaining_duration.is_positive() {
|
||||||
format!(
|
format!(
|
||||||
"{}% - {}",
|
"{}% - {}",
|
||||||
connected_device.battery.percent,
|
connected_device.battery.percent,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2023 System76 <info@system76.com>
|
// Copyright 2023 System76 <info@system76.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use chrono::{Datelike, Timelike};
|
|
||||||
use cosmic::{
|
use cosmic::{
|
||||||
Apply, Element, Task,
|
Apply, Element, Task,
|
||||||
app::ContextDrawer,
|
app::ContextDrawer,
|
||||||
|
|
@ -564,10 +563,11 @@ fn format_date(date: &DateTime<Gregorian>, military: bool, show_seconds: bool) -
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_local_time() -> DateTime<Gregorian> {
|
fn update_local_time() -> DateTime<Gregorian> {
|
||||||
let now = chrono::Local::now();
|
let now = jiff::Zoned::now();
|
||||||
|
|
||||||
DateTime {
|
DateTime {
|
||||||
date: Date::try_new_gregorian(now.year(), now.month() as u8, now.day() as u8).unwrap(),
|
date: Date::try_new_gregorian(now.year() as i32, now.month() as u8, now.day() as u8)
|
||||||
|
.unwrap(),
|
||||||
time: Time::try_new(now.hour() as u8, now.minute() as u8, now.second() as u8, 0).unwrap(),
|
time: Time::try_new(now.hour() as u8, now.minute() as u8, now.second() as u8, 0).unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::any::TypeId;
|
use std::any::TypeId;
|
||||||
|
|
||||||
use ashpd::desktop::location::{Location, LocationProxy};
|
use ashpd::desktop::location::{Location, LocationProxy};
|
||||||
|
use chrono::NaiveDate;
|
||||||
use cosmic::iced::{
|
use cosmic::iced::{
|
||||||
Subscription,
|
Subscription,
|
||||||
futures::{SinkExt, StreamExt, channel::mpsc::Sender, future},
|
futures::{SinkExt, StreamExt, channel::mpsc::Sender, future},
|
||||||
|
|
@ -46,28 +47,49 @@ async fn inner(mut tx: Sender<bool>) -> anyhow::Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let coord = Coordinates::new(loc.latitude(), loc.longitude()).unwrap();
|
let coord = Coordinates::new(loc.latitude(), loc.longitude()).unwrap();
|
||||||
let now = chrono::Local::now();
|
let now = jiff::Zoned::now();
|
||||||
let date = now.date_naive();
|
let now_in_seconds = now.timestamp().as_second();
|
||||||
let now_in_seconds = now.timestamp();
|
let northern_tilt = now.month() >= 3 && now.month() <= 9;
|
||||||
|
// TODO: remove chrono if sunrise adds support for jiff - https://github.com/nathan-osman/rust-sunrise/pull/20
|
||||||
|
let date = NaiveDate::from_ymd_opt(now.year() as i32, now.month() as u32, now.day() as u32)
|
||||||
|
.expect("jiff date is valid");
|
||||||
let current_solar_day = SolarDay::new(coord, date);
|
let current_solar_day = SolarDay::new(coord, date);
|
||||||
let sunrise = current_solar_day
|
let sunrise = current_solar_day
|
||||||
.event_time(SolarEvent::Sunrise)
|
.event_time(SolarEvent::Sunrise)
|
||||||
.timestamp();
|
.map(|s| s.timestamp());
|
||||||
let sunset = current_solar_day.event_time(SolarEvent::Sunset).timestamp();
|
let sunset = current_solar_day
|
||||||
let daytime = now_in_seconds >= sunrise && now_in_seconds <= sunset;
|
.event_time(SolarEvent::Sunset)
|
||||||
|
.map(|s| s.timestamp());
|
||||||
|
let daytime = match (sunrise, sunset) {
|
||||||
|
(Some(sunrise), Some(sunset)) => now_in_seconds >= sunrise && now_in_seconds <= sunset,
|
||||||
|
// transition into polar day
|
||||||
|
(Some(sunrise), None) => now_in_seconds >= sunrise,
|
||||||
|
// transition out of polar day
|
||||||
|
(None, Some(sunset)) => now_in_seconds <= sunset,
|
||||||
|
// polar day
|
||||||
|
(None, None) => {
|
||||||
|
(coord.lat() > 0.0 && northern_tilt) || (coord.lat() < 0.0 && !northern_tilt)
|
||||||
|
}
|
||||||
|
};
|
||||||
tx.send(daytime).await?;
|
tx.send(daytime).await?;
|
||||||
|
|
||||||
let sleep = if daytime {
|
let next_event = if daytime {
|
||||||
sunset - now_in_seconds
|
sunset
|
||||||
} else if now_in_seconds < sunset {
|
} else if now_in_seconds < sunrise.unwrap_or(0) {
|
||||||
sunrise - now_in_seconds
|
sunrise
|
||||||
} else {
|
} else {
|
||||||
let tmrw = now + chrono::Duration::days(1);
|
let tmrw = now.checked_add(jiff::Span::new().days(1))?;
|
||||||
let tmrw_sunrise = SolarDay::new(coord, tmrw.date_naive())
|
let tmrw_sunrise =
|
||||||
|
NaiveDate::from_ymd_opt(tmrw.year() as i32, tmrw.month() as u32, tmrw.day() as u32)
|
||||||
|
.expect("jiff date is valid");
|
||||||
|
|
||||||
|
SolarDay::new(coord, tmrw_sunrise)
|
||||||
.event_time(SolarEvent::Sunrise)
|
.event_time(SolarEvent::Sunrise)
|
||||||
.timestamp();
|
.map(|s| s.timestamp())
|
||||||
tmrw_sunrise - now_in_seconds
|
|
||||||
};
|
};
|
||||||
|
let sleep = next_event
|
||||||
|
.map(|ts| (ts - now_in_seconds).max(60))
|
||||||
|
.unwrap_or(3600);
|
||||||
next = select! {
|
next = select! {
|
||||||
() = tokio::time::sleep(tokio::time::Duration::from_secs(sleep as u64)) => {
|
() = tokio::time::sleep(tokio::time::Duration::from_secs(sleep as u64)) => {
|
||||||
Some(Event::Daytime)
|
Some(Event::Daytime)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue