- Nuevas opciones `app.timezone_regions`, `app.timezone_order` y `app.timezone_per_user` para limitar y ordenar las regiones ofrecidas y decidir si cada usuario puede tener su propia zona horaria. - Añade `TzRegion` y `TimezoneOrder`; `Timezone::supported_by_region()` devuelve ahora `TzRegion` y excluye los alias de la base IANA que repiten otra zona (tzdata 2025b). - Añade `Timezone::is_supported_in()` para validar con otras regiones. - `SelectTimezone` admite `with_regions()`, `with_order()` y `with_utc_offset()`, muestra nombres legibles y conserva la zona actual aunque ya no se ofrezca. - `app.timezone` se resuelve sin distinguir mayúsculas. - pagetop-user no ofrece idioma ni zona horaria si no se aplican y conserva lo guardado; acepta la zona actual aunque ya no se ofrezca.
57 lines
2.4 KiB
Rust
57 lines
2.4 KiB
Rust
use crate::AutoDefault;
|
|
|
|
use serde::{Deserialize, Deserializer};
|
|
|
|
/// Criterios para ordenar las regiones de zonas horarias que se ofrecen para elegir.
|
|
///
|
|
/// Se obtiene de [`global::SETTINGS.app.timezone_order`](crate::global::App::timezone_order) y
|
|
/// determina el orden de los grupos de [`Timezone::supported_by_region()`]. Es también el orden
|
|
/// por defecto de [`form::SelectTimezone`], que puede cambiarse con `with_order()`. En todos los
|
|
/// casos el grupo *"Etc"* (`Etc/UTC`) va siempre al final.
|
|
///
|
|
/// [`Timezone::supported_by_region()`]: crate::datetime::Timezone::supported_by_region
|
|
/// [`form::SelectTimezone`]: crate::base::component::form::SelectTimezone
|
|
#[derive(AutoDefault, Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub enum TimezoneOrder {
|
|
/// Primero la región de la zona horaria del sitio y luego el resto, de la más cercana a la más
|
|
/// lejana según su desfase horario. Es el comportamiento por defecto.
|
|
#[default]
|
|
Nearest,
|
|
/// Por nombre de la región. [`form::SelectTimezone`] las ordena por su nombre traducido al
|
|
/// idioma de la página, sin distinguir mayúsculas ni acentos;
|
|
/// `Timezone::supported_by_region()`, que no depende del idioma, por su nombre IANA.
|
|
///
|
|
/// [`form::SelectTimezone`]: crate::base::component::form::SelectTimezone
|
|
Alphabetical,
|
|
/// En el orden en que se indican las regiones, en
|
|
/// [`global::SETTINGS.app.timezone_regions`](crate::global::App::timezone_regions) o con
|
|
/// `SelectTimezone::with_regions()`; si no se indica ninguna región válida, por nombre, como
|
|
/// `TimezoneOrder::Alphabetical`.
|
|
Listed,
|
|
}
|
|
|
|
impl<'de> Deserialize<'de> for TimezoneOrder {
|
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
let raw = String::deserialize(deserializer)?;
|
|
let result = match raw.trim().to_ascii_lowercase().as_str() {
|
|
"nearest" => Self::Nearest,
|
|
"alphabetical" => Self::Alphabetical,
|
|
"listed" => Self::Listed,
|
|
_ => {
|
|
let default = Self::default();
|
|
println!(
|
|
concat!(
|
|
"\nInvalid value \"{}\" for [app].timezone_order. ",
|
|
"Using \"{:?}\". Check settings.",
|
|
),
|
|
raw, default,
|
|
);
|
|
default
|
|
}
|
|
};
|
|
Ok(result)
|
|
}
|
|
}
|