mirror of
https://github.com/0x5eal/chrono-lc.git
synced 2024-12-12 12:50:36 +00:00
feat: support latest version chrono
* Fixed crate breaking due to non-exhaustive matches on the latest chrono version * Addressed minor clippy lints
This commit is contained in:
parent
e3f2c5a088
commit
ddd6ed6f96
2 changed files with 110 additions and 95 deletions
3
build.rs
3
build.rs
|
@ -23,7 +23,7 @@ pub struct Locale {
|
||||||
fn main() {
|
fn main() {
|
||||||
let out_dir = env::var("OUT_DIR").unwrap();
|
let out_dir = env::var("OUT_DIR").unwrap();
|
||||||
let dest_path = Path::new(&out_dir).join("locales.rs");
|
let dest_path = Path::new(&out_dir).join("locales.rs");
|
||||||
let mut f = File::create(&dest_path).unwrap();
|
let mut f = File::create(dest_path).unwrap();
|
||||||
|
|
||||||
let _ = f.write_all(
|
let _ = f.write_all(
|
||||||
r#####"// This file is @generated automatically by chrono_lc. Please don't edit by hand.
|
r#####"// This file is @generated automatically by chrono_lc. Please don't edit by hand.
|
||||||
|
@ -148,6 +148,7 @@ fn load_locale(entry: &DirEntry) -> Result<Locale, BuildError> {
|
||||||
Ok(locale)
|
Ok(locale)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
enum BuildError {
|
enum BuildError {
|
||||||
Io(IoError),
|
Io(IoError),
|
||||||
Json(JsonError),
|
Json(JsonError),
|
||||||
|
|
202
src/lib.rs
202
src/lib.rs
|
@ -59,7 +59,7 @@
|
||||||
pub(crate) use lazy_static::lazy_static;
|
pub(crate) use lazy_static::lazy_static;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt::{self, Error};
|
||||||
|
|
||||||
use chrono::format::{Fixed, Item, Numeric, Pad, StrftimeItems};
|
use chrono::format::{Fixed, Item, Numeric, Pad, StrftimeItems};
|
||||||
use chrono::{Datelike, FixedOffset, NaiveDate, NaiveTime, Offset, TimeZone, Timelike};
|
use chrono::{Datelike, FixedOffset, NaiveDate, NaiveTime, Offset, TimeZone, Timelike};
|
||||||
|
@ -145,6 +145,109 @@ impl<'a, I: Iterator<Item = Item<'a>> + Clone> fmt::Display for DelayedFormatL10
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Prints an offset from UTC in the format of `+HHMM` or `+HH:MM`.
|
||||||
|
/// `Z` instead of `+00[:]00` is allowed when `allow_zulu` is true.
|
||||||
|
fn write_local_minus_utc(w: &mut fmt::Formatter, off: FixedOffset, allow_zulu: bool, use_colon: bool) -> fmt::Result {
|
||||||
|
let off = off.local_minus_utc();
|
||||||
|
if !allow_zulu || off != 0 {
|
||||||
|
let (sign, off) = if off < 0 { ('-', -off) } else { ('+', off) };
|
||||||
|
if use_colon {
|
||||||
|
write!(w, "{}{:02}:{:02}", sign, off / 3600, off / 60 % 60)
|
||||||
|
} else {
|
||||||
|
write!(w, "{}{:02}{:02}", sign, off / 3600, off / 60 % 60)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
write!(w, "Z")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_fixed(
|
||||||
|
w: &mut fmt::Formatter,
|
||||||
|
date: Option<&NaiveDate>,
|
||||||
|
time: Option<&NaiveTime>,
|
||||||
|
off: Option<&(String, FixedOffset)>,
|
||||||
|
spec: Fixed,
|
||||||
|
locale: &str,
|
||||||
|
) -> Option<Result<(), Error>> {
|
||||||
|
use self::Fixed::*;
|
||||||
|
|
||||||
|
match spec {
|
||||||
|
ShortMonthName => date.map(|d| write!(w, "{}", short_month(d.month0() as usize, locale))),
|
||||||
|
LongMonthName => date.map(|d| write!(w, "{}", long_month(d.month0() as usize, locale))),
|
||||||
|
ShortWeekdayName => date.map(|d| write!(w, "{}", short_weekday(d.weekday().num_days_from_monday() as usize, locale))),
|
||||||
|
LongWeekdayName => date.map(|d| write!(w, "{}", long_weekday(d.weekday().num_days_from_monday() as usize, locale))),
|
||||||
|
LowerAmPm => time.map(|t| write!(w, "{}", ampm(t.hour12().0 as usize, locale))),
|
||||||
|
UpperAmPm => time.map(|t| write!(w, "{}", ampm(t.hour12().0 as usize + 2, locale))),
|
||||||
|
Nanosecond => time.map(|t| {
|
||||||
|
let nano = t.nanosecond() % 1_000_000_000;
|
||||||
|
if nano == 0 {
|
||||||
|
Ok(())
|
||||||
|
} else if nano % 1_000_000 == 0 {
|
||||||
|
write!(w, ".{:03}", nano / 1_000_000)
|
||||||
|
} else if nano % 1_000 == 0 {
|
||||||
|
write!(w, ".{:06}", nano / 1_000)
|
||||||
|
} else {
|
||||||
|
write!(w, ".{:09}", nano)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
Nanosecond3 => time.map(|t| {
|
||||||
|
let nano = t.nanosecond() % 1_000_000_000;
|
||||||
|
write!(w, ".{:03}", nano / 1_000_000)
|
||||||
|
}),
|
||||||
|
Nanosecond6 => time.map(|t| {
|
||||||
|
let nano = t.nanosecond() % 1_000_000_000;
|
||||||
|
write!(w, ".{:06}", nano / 1_000)
|
||||||
|
}),
|
||||||
|
Nanosecond9 => time.map(|t| {
|
||||||
|
let nano = t.nanosecond() % 1_000_000_000;
|
||||||
|
write!(w, ".{:09}", nano)
|
||||||
|
}),
|
||||||
|
Internal(_) => panic!("Internal is not supported"),
|
||||||
|
TimezoneName => off.map(|(name, _)| write!(w, "{}", *name)),
|
||||||
|
TimezoneOffsetColon => off.map(|&(_, off)| write_local_minus_utc(w, off, false, true)),
|
||||||
|
TimezoneOffsetColonZ => off.map(|&(_, off)| write_local_minus_utc(w, off, true, true)),
|
||||||
|
TimezoneOffsetDoubleColon => off.map(|&(_, off)| write_local_minus_utc(w, off, false, true)),
|
||||||
|
TimezoneOffsetTripleColon => off.map(|&(_, off)| write_local_minus_utc(w, off, false, true)),
|
||||||
|
TimezoneOffset => off.map(|&(_, off)| write_local_minus_utc(w, off, false, false)),
|
||||||
|
TimezoneOffsetZ => off.map(|&(_, off)| write_local_minus_utc(w, off, true, false)),
|
||||||
|
RFC2822 =>
|
||||||
|
// same to `%a, %e %b %Y %H:%M:%S %z`
|
||||||
|
{
|
||||||
|
if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) {
|
||||||
|
let sec = t.second() + t.nanosecond() / 1_000_000_000;
|
||||||
|
write!(
|
||||||
|
w,
|
||||||
|
"{}, {:2} {} {:04} {:02}:{:02}:{:02} ",
|
||||||
|
short_weekday(d.weekday().num_days_from_monday() as usize, locale),
|
||||||
|
d.day(),
|
||||||
|
short_month(d.month0() as usize, locale),
|
||||||
|
d.year(),
|
||||||
|
t.hour(),
|
||||||
|
t.minute(),
|
||||||
|
sec
|
||||||
|
)
|
||||||
|
.ok()?;
|
||||||
|
Some(write_local_minus_utc(w, off, false, false))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RFC3339 =>
|
||||||
|
// same to `%Y-%m-%dT%H:%M:%S%.f%:z`
|
||||||
|
{
|
||||||
|
if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) {
|
||||||
|
// reuse `Debug` impls which already print ISO 8601 format.
|
||||||
|
// this is faster in this way.
|
||||||
|
write!(w, "{:?}T{:?}", d, t).ok()?;
|
||||||
|
Some(write_local_minus_utc(w, off, false, true))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spec => parse_fixed(w, date, time, off, spec, locale),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This function is nearly entirely copied from chrono's format()
|
/// This function is nearly entirely copied from chrono's format()
|
||||||
/// internal formats (3, 6 and 9-digits nanoseconds) have been disabled due to lack of access to chrono internals
|
/// internal formats (3, 6 and 9-digits nanoseconds) have been disabled due to lack of access to chrono internals
|
||||||
pub fn format_l10n<'a, I>(
|
pub fn format_l10n<'a, I>(
|
||||||
|
@ -193,13 +296,14 @@ where
|
||||||
Timestamp => (
|
Timestamp => (
|
||||||
1,
|
1,
|
||||||
match (date, time, off) {
|
match (date, time, off) {
|
||||||
(Some(d), Some(t), None) => Some(d.and_time(*t).timestamp()),
|
(Some(d), Some(t), None) => Some(d.and_time(*t).and_utc().timestamp()),
|
||||||
(Some(d), Some(t), Some(&(_, off))) => Some((d.and_time(*t) - off).timestamp()),
|
(Some(d), Some(t), Some(&(_, off))) => Some((d.and_time(*t) - off).and_utc().timestamp()),
|
||||||
(_, _, _) => None,
|
(_, _, _) => None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
// for the future expansion
|
// for the future expansion
|
||||||
Internal(_) => (1, None),
|
Internal(_) => (1, None),
|
||||||
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(v) = v {
|
if let Some(v) = v {
|
||||||
|
@ -223,97 +327,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
Item::Fixed(spec) => {
|
Item::Fixed(spec) => {
|
||||||
use self::Fixed::*;
|
let ret = parse_fixed(w, date, time, off, spec, &locale);
|
||||||
|
|
||||||
/// Prints an offset from UTC in the format of `+HHMM` or `+HH:MM`.
|
|
||||||
/// `Z` instead of `+00[:]00` is allowed when `allow_zulu` is true.
|
|
||||||
fn write_local_minus_utc(w: &mut fmt::Formatter, off: FixedOffset, allow_zulu: bool, use_colon: bool) -> fmt::Result {
|
|
||||||
let off = off.local_minus_utc();
|
|
||||||
if !allow_zulu || off != 0 {
|
|
||||||
let (sign, off) = if off < 0 { ('-', -off) } else { ('+', off) };
|
|
||||||
if use_colon {
|
|
||||||
write!(w, "{}{:02}:{:02}", sign, off / 3600, off / 60 % 60)
|
|
||||||
} else {
|
|
||||||
write!(w, "{}{:02}{:02}", sign, off / 3600, off / 60 % 60)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
write!(w, "Z")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let ret = match spec {
|
|
||||||
ShortMonthName => date.map(|d| write!(w, "{}", short_month(d.month0() as usize, &locale))),
|
|
||||||
LongMonthName => date.map(|d| write!(w, "{}", long_month(d.month0() as usize, &locale))),
|
|
||||||
ShortWeekdayName => date.map(|d| write!(w, "{}", short_weekday(d.weekday().num_days_from_monday() as usize, &locale))),
|
|
||||||
LongWeekdayName => date.map(|d| write!(w, "{}", long_weekday(d.weekday().num_days_from_monday() as usize, &locale))),
|
|
||||||
LowerAmPm => time.map(|t| write!(w, "{}", ampm(t.hour12().0 as usize, &locale))),
|
|
||||||
UpperAmPm => time.map(|t| write!(w, "{}", ampm(t.hour12().0 as usize + 2, &locale))),
|
|
||||||
Nanosecond => time.map(|t| {
|
|
||||||
let nano = t.nanosecond() % 1_000_000_000;
|
|
||||||
if nano == 0 {
|
|
||||||
Ok(())
|
|
||||||
} else if nano % 1_000_000 == 0 {
|
|
||||||
write!(w, ".{:03}", nano / 1_000_000)
|
|
||||||
} else if nano % 1_000 == 0 {
|
|
||||||
write!(w, ".{:06}", nano / 1_000)
|
|
||||||
} else {
|
|
||||||
write!(w, ".{:09}", nano)
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
Nanosecond3 => time.map(|t| {
|
|
||||||
let nano = t.nanosecond() % 1_000_000_000;
|
|
||||||
write!(w, ".{:03}", nano / 1_000_000)
|
|
||||||
}),
|
|
||||||
Nanosecond6 => time.map(|t| {
|
|
||||||
let nano = t.nanosecond() % 1_000_000_000;
|
|
||||||
write!(w, ".{:06}", nano / 1_000)
|
|
||||||
}),
|
|
||||||
Nanosecond9 => time.map(|t| {
|
|
||||||
let nano = t.nanosecond() % 1_000_000_000;
|
|
||||||
write!(w, ".{:09}", nano)
|
|
||||||
}),
|
|
||||||
Internal(_) => panic!("Internal is not supported"),
|
|
||||||
TimezoneName => off.map(|(name, _)| write!(w, "{}", *name)),
|
|
||||||
TimezoneOffsetColon => off.map(|&(_, off)| write_local_minus_utc(w, off, false, true)),
|
|
||||||
TimezoneOffsetColonZ => off.map(|&(_, off)| write_local_minus_utc(w, off, true, true)),
|
|
||||||
TimezoneOffsetDoubleColon => off.map(|&(_, off)| write_local_minus_utc(w, off, false, true)),
|
|
||||||
TimezoneOffsetTripleColon => off.map(|&(_, off)| write_local_minus_utc(w, off, false, true)),
|
|
||||||
TimezoneOffset => off.map(|&(_, off)| write_local_minus_utc(w, off, false, false)),
|
|
||||||
TimezoneOffsetZ => off.map(|&(_, off)| write_local_minus_utc(w, off, true, false)),
|
|
||||||
RFC2822 =>
|
|
||||||
// same to `%a, %e %b %Y %H:%M:%S %z`
|
|
||||||
{
|
|
||||||
if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) {
|
|
||||||
let sec = t.second() + t.nanosecond() / 1_000_000_000;
|
|
||||||
write!(
|
|
||||||
w,
|
|
||||||
"{}, {:2} {} {:04} {:02}:{:02}:{:02} ",
|
|
||||||
short_weekday(d.weekday().num_days_from_monday() as usize, &locale),
|
|
||||||
d.day(),
|
|
||||||
short_month(d.month0() as usize, &locale),
|
|
||||||
d.year(),
|
|
||||||
t.hour(),
|
|
||||||
t.minute(),
|
|
||||||
sec
|
|
||||||
)?;
|
|
||||||
Some(write_local_minus_utc(w, off, false, false))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RFC3339 =>
|
|
||||||
// same to `%Y-%m-%dT%H:%M:%S%.f%:z`
|
|
||||||
{
|
|
||||||
if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) {
|
|
||||||
// reuse `Debug` impls which already print ISO 8601 format.
|
|
||||||
// this is faster in this way.
|
|
||||||
write!(w, "{:?}T{:?}", d, t)?;
|
|
||||||
Some(write_local_minus_utc(w, off, false, true))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match ret {
|
match ret {
|
||||||
Some(ret) => ret?,
|
Some(ret) => ret?,
|
||||||
|
|
Loading…
Reference in a new issue