mirror of
https://github.com/mztlive/dx-admin-template.git
synced 2025-12-22 21:59:59 +00:00
移除chrono
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1620,7 +1620,6 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
|||||||
name = "dx-admin-template"
|
name = "dx-admin-template"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dioxus = { version = "0.7.1", features = ["router", "fullstack"] }
|
dioxus = { version = "0.7.1", features = ["router", "fullstack"] }
|
||||||
chrono = { version = "0.4", default-features = false, features = ["std"] }
|
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
js-sys = "0.3"
|
js-sys = "0.3"
|
||||||
|
|||||||
@@ -966,8 +966,7 @@ fn InteractiveTableSample() -> Element {
|
|||||||
- `on_select` 返回选中的 `NaiveDate`。
|
- `on_select` 返回选中的 `NaiveDate`。
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use crate::components::ui::Calendar;
|
use crate::{components::ui::Calendar, time::NaiveDate};
|
||||||
use chrono::NaiveDate;
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
@@ -992,8 +991,10 @@ fn CalendarSample() -> Element {
|
|||||||
- `on_change` 返回新的区间或 `None`。
|
- `on_change` 返回新的区间或 `None`。
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use crate::components::ui::{DateRange, DateRangePicker};
|
use crate::{
|
||||||
use chrono::NaiveDate;
|
components::ui::{DateRange, DateRangePicker},
|
||||||
|
time::NaiveDate,
|
||||||
|
};
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use chrono::{Datelike, Duration, NaiveDate};
|
use crate::time::{Duration, NaiveDate};
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use super::utils::merge_class;
|
use super::utils::merge_class;
|
||||||
const WEEKDAY_LABELS: [&str; 7] = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
const WEEKDAY_LABELS: [&str; 7] = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
use super::button::{Button, ButtonSize, ButtonVariant};
|
use super::button::{Button, ButtonSize, ButtonVariant};
|
||||||
use chrono::{Datelike, Duration, NaiveDate};
|
use super::utils::merge_class;
|
||||||
|
use crate::{
|
||||||
|
components::ui::PopoverHandle,
|
||||||
|
time::{Duration, NaiveDate},
|
||||||
|
};
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use super::utils::merge_class;#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use crate::components::ui::PopoverHandle;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub struct DateRange {
|
pub struct DateRange {
|
||||||
@@ -77,9 +80,9 @@ fn today_date() -> NaiveDate {
|
|||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
fn today_date() -> NaiveDate {
|
fn today_date() -> NaiveDate {
|
||||||
let now = SystemTime::now();
|
NaiveDate::from_system_time(SystemTime::now())
|
||||||
let datetime: chrono::DateTime<chrono::Utc> = now.into();
|
.or_else(|| NaiveDate::from_ymd_opt(1970, 1, 1))
|
||||||
datetime.date_naive()
|
.expect("system time within supported range")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn describe_range(range: DateRange) -> String {
|
fn describe_range(range: DateRange) -> String {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// need dioxus
|
// need dioxus
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
mod time;
|
||||||
use views::{Components, Home, Navbar, Orders};
|
use views::{Components, Home, Navbar, Orders};
|
||||||
|
|
||||||
/// Define a components module that contains all shared components for our app.
|
/// Define a components module that contains all shared components for our app.
|
||||||
|
|||||||
297
src/time.rs
Normal file
297
src/time.rs
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
use std::fmt::{self, Display, Formatter, Write};
|
||||||
|
use std::ops::{Add, AddAssign, Sub, SubAssign};
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
const SECONDS_PER_DAY: i64 = 86_400;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct NaiveDate {
|
||||||
|
days_since_epoch: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub struct Duration {
|
||||||
|
days: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub enum Weekday {
|
||||||
|
Monday = 0,
|
||||||
|
Tuesday = 1,
|
||||||
|
Wednesday = 2,
|
||||||
|
Thursday = 3,
|
||||||
|
Friday = 4,
|
||||||
|
Saturday = 5,
|
||||||
|
Sunday = 6,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Weekday {
|
||||||
|
pub fn num_days_from_monday(self) -> u8 {
|
||||||
|
self as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Duration {
|
||||||
|
pub fn days(days: i64) -> Self {
|
||||||
|
Self { days }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn num_days(self) -> i64 {
|
||||||
|
self.days
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct FormattedDate<'a> {
|
||||||
|
date: NaiveDate,
|
||||||
|
pattern: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Display for FormattedDate<'a> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
|
f.write_str(&self.date.format_internal(self.pattern))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NaiveDate {
|
||||||
|
pub fn from_ymd_opt(year: i32, month: u32, day: u32) -> Option<Self> {
|
||||||
|
if month == 0 || month > 12 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
if day == 0 || day > days_in_month(year, month) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(Self {
|
||||||
|
days_since_epoch: days_from_civil(year, month, day)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_day(self, day: u32) -> Option<Self> {
|
||||||
|
Self::from_ymd_opt(self.year(), self.month(), day)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn year(self) -> i32 {
|
||||||
|
self.components().0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn month(self) -> u32 {
|
||||||
|
self.components().1
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn day(self) -> u32 {
|
||||||
|
self.components().2
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn weekday(self) -> Weekday {
|
||||||
|
let idx = (self.days_since_epoch as i64 + 3).rem_euclid(7) as u8;
|
||||||
|
match idx {
|
||||||
|
0 => Weekday::Monday,
|
||||||
|
1 => Weekday::Tuesday,
|
||||||
|
2 => Weekday::Wednesday,
|
||||||
|
3 => Weekday::Thursday,
|
||||||
|
4 => Weekday::Friday,
|
||||||
|
5 => Weekday::Saturday,
|
||||||
|
_ => Weekday::Sunday,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format<'a>(self, pattern: &'a str) -> FormattedDate<'a> {
|
||||||
|
FormattedDate { date: self, pattern }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_system_time(time: SystemTime) -> Option<Self> {
|
||||||
|
match time.duration_since(UNIX_EPOCH) {
|
||||||
|
Ok(duration) => {
|
||||||
|
let days = (duration.as_secs() as i64) / SECONDS_PER_DAY;
|
||||||
|
Self::from_days_since_epoch(days)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
let duration = err.duration();
|
||||||
|
let days = (duration.as_secs() as i64 + SECONDS_PER_DAY - 1) / SECONDS_PER_DAY;
|
||||||
|
Self::from_days_since_epoch(-days)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_days_since_epoch(days: i64) -> Option<Self> {
|
||||||
|
let value: i32 = days.try_into().ok()?;
|
||||||
|
Some(Self {
|
||||||
|
days_since_epoch: value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn components(self) -> (i32, u32, u32) {
|
||||||
|
civil_from_days(self.days_since_epoch)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_internal(self, pattern: &str) -> String {
|
||||||
|
let (year, month, day) = self.components();
|
||||||
|
let mut output = String::with_capacity(pattern.len() + 8);
|
||||||
|
let mut chars = pattern.chars();
|
||||||
|
while let Some(ch) = chars.next() {
|
||||||
|
if ch == '%' {
|
||||||
|
if let Some(spec) = chars.next() {
|
||||||
|
match spec {
|
||||||
|
'Y' => {
|
||||||
|
let _ = write!(output, "{year:04}");
|
||||||
|
}
|
||||||
|
'm' => {
|
||||||
|
let _ = write!(output, "{month:02}");
|
||||||
|
}
|
||||||
|
'd' => {
|
||||||
|
let _ = write!(output, "{day:02}");
|
||||||
|
}
|
||||||
|
'B' => output.push_str(full_month(month)),
|
||||||
|
'b' => output.push_str(short_month(month)),
|
||||||
|
'%' => output.push('%'),
|
||||||
|
other => {
|
||||||
|
output.push('%');
|
||||||
|
output.push(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output.push(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add<Duration> for NaiveDate {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, rhs: Duration) -> Self::Output {
|
||||||
|
let total = self.days_since_epoch as i64 + rhs.days;
|
||||||
|
Self::from_days_since_epoch(total).expect("date overflow")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign<Duration> for NaiveDate {
|
||||||
|
fn add_assign(&mut self, rhs: Duration) {
|
||||||
|
*self = *self + rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub<Duration> for NaiveDate {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn sub(self, rhs: Duration) -> Self::Output {
|
||||||
|
let total = self.days_since_epoch as i64 - rhs.days;
|
||||||
|
Self::from_days_since_epoch(total).expect("date overflow")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SubAssign<Duration> for NaiveDate {
|
||||||
|
fn sub_assign(&mut self, rhs: Duration) {
|
||||||
|
*self = *self - rhs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sub for NaiveDate {
|
||||||
|
type Output = Duration;
|
||||||
|
|
||||||
|
fn sub(self, rhs: NaiveDate) -> Self::Output {
|
||||||
|
Duration::days(self.days_since_epoch as i64 - rhs.days_since_epoch as i64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn days_in_month(year: i32, month: u32) -> u32 {
|
||||||
|
match month {
|
||||||
|
1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
|
||||||
|
4 | 6 | 9 | 11 => 30,
|
||||||
|
2 if is_leap_year(year) => 29,
|
||||||
|
2 => 28,
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_leap_year(year: i32) -> bool {
|
||||||
|
(year % 4 == 0 && year % 100 != 0) || year % 400 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn days_from_civil(year: i32, month: u32, day: u32) -> Option<i32> {
|
||||||
|
let y = year - if month <= 2 { 1 } else { 0 };
|
||||||
|
let era = if y >= 0 { y } else { y - 399 } / 400;
|
||||||
|
let yoe = y - era * 400;
|
||||||
|
let mp = month as i32 + if month > 2 { -3 } else { 9 };
|
||||||
|
let doy = (153 * mp + 2) / 5 + day as i32 - 1;
|
||||||
|
let doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
|
||||||
|
let days = era * 146097 + doe - 719_468;
|
||||||
|
days.try_into().ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn civil_from_days(days: i32) -> (i32, u32, u32) {
|
||||||
|
let days = days as i64 + 719_468;
|
||||||
|
let era = if days >= 0 {
|
||||||
|
days / 146_097
|
||||||
|
} else {
|
||||||
|
(days - 146_096) / 146_097
|
||||||
|
};
|
||||||
|
let doe = days - era * 146_097;
|
||||||
|
let yoe = (doe - doe / 1_460 + doe / 36_524 - doe / 146_096) / 365;
|
||||||
|
let mut y = yoe + era * 400;
|
||||||
|
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
|
||||||
|
let mp = (5 * doy + 2) / 153;
|
||||||
|
let day = doy - (153 * mp + 2) / 5 + 1;
|
||||||
|
let month = mp + if mp < 10 { 3 } else { -9 };
|
||||||
|
y += if month <= 2 { 1 } else { 0 };
|
||||||
|
(y as i32, month as u32, day as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn full_month(month: u32) -> &'static str {
|
||||||
|
match month {
|
||||||
|
1 => "January",
|
||||||
|
2 => "February",
|
||||||
|
3 => "March",
|
||||||
|
4 => "April",
|
||||||
|
5 => "May",
|
||||||
|
6 => "June",
|
||||||
|
7 => "July",
|
||||||
|
8 => "August",
|
||||||
|
9 => "September",
|
||||||
|
10 => "October",
|
||||||
|
11 => "November",
|
||||||
|
12 => "December",
|
||||||
|
_ => "Unknown",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_month(month: u32) -> &'static str {
|
||||||
|
match month {
|
||||||
|
1 => "Jan",
|
||||||
|
2 => "Feb",
|
||||||
|
3 => "Mar",
|
||||||
|
4 => "Apr",
|
||||||
|
5 => "May",
|
||||||
|
6 => "Jun",
|
||||||
|
7 => "Jul",
|
||||||
|
8 => "Aug",
|
||||||
|
9 => "Sep",
|
||||||
|
10 => "Oct",
|
||||||
|
11 => "Nov",
|
||||||
|
12 => "Dec",
|
||||||
|
_ => "Unk",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn roundtrip_ymd() {
|
||||||
|
let date = NaiveDate::from_ymd_opt(2024, 6, 30).unwrap();
|
||||||
|
assert_eq!(date.year(), 2024);
|
||||||
|
assert_eq!(date.month(), 6);
|
||||||
|
assert_eq!(date.day(), 30);
|
||||||
|
assert_eq!(date.weekday().num_days_from_monday(), 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_days() {
|
||||||
|
let mut date = NaiveDate::from_ymd_opt(2024, 1, 31).unwrap();
|
||||||
|
date += Duration::days(1);
|
||||||
|
assert_eq!((date.year(), date.month(), date.day()), (2024, 2, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ use crate::components::ui::{
|
|||||||
TabsTrigger, Textarea, Toast, ToastViewport, Toggle, ToggleGroup, ToggleGroupItem,
|
TabsTrigger, Textarea, Toast, ToastViewport, Toggle, ToggleGroup, ToggleGroupItem,
|
||||||
ToggleGroupMode, ToggleGroupOrientation, Tooltip,
|
ToggleGroupMode, ToggleGroupOrientation, Tooltip,
|
||||||
};
|
};
|
||||||
use chrono::NaiveDate;
|
use crate::time::NaiveDate;
|
||||||
use dioxus::html::events::FormEvent;
|
use dioxus::html::events::FormEvent;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::components::ui::{
|
|||||||
SelectOption, Slider, Table, TableBody, TableCaption, TableCell, TableColumnConfig,
|
SelectOption, Slider, Table, TableBody, TableCaption, TableCell, TableColumnConfig,
|
||||||
TableFooter, TableHead, TableHeader, TableRow, TableRowData,
|
TableFooter, TableHead, TableHeader, TableRow, TableRowData,
|
||||||
};
|
};
|
||||||
use chrono::NaiveDate;
|
use crate::time::NaiveDate;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
const PAGE_SIZE: usize = 8;
|
const PAGE_SIZE: usize = 8;
|
||||||
|
|||||||
Reference in New Issue
Block a user