diff --git a/Cargo.toml b/Cargo.toml index 52d0701..56d5ac7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fastdate" -version = "0.3.25" +version = "0.3.26" edition = "2021" description = "Rust fast date carte" readme = "Readme.md" diff --git a/benches/bench.rs b/benches/bench.rs index fb5216a..fa55c75 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -138,3 +138,13 @@ fn bench_from_timestamp_millis(b: &mut Bencher) { }); }); } + +#[bench] +fn bench_format(b: &mut Bencher) { + let dt=DateTime::from_str("1997-12-13T11:12:13.123456+09:00").unwrap(); + b.iter(|| { + std::hint::black_box({ + dt.format("YYYY-MM-DD/hh/mm/ss.000000"); + }); + }); +} \ No newline at end of file diff --git a/src/datetime.rs b/src/datetime.rs index e87a40f..691b197 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -162,26 +162,64 @@ impl DateTime { /// /// ``` pub fn format(&self, fmt: &str) -> String { + use std::fmt::Write; let (mut h, mut m, _) = self.offset_hms(); let offset = self.offset(); - let add_sub; - if offset > 0 { - add_sub = '+'; - } else { - add_sub = '-'; - h = h.abs(); - m = m.abs(); + let add_sub = if offset >= 0 { '+' } else { '-' }; + let mut result = String::with_capacity(fmt.len()); + let mut chars = fmt.chars(); + while let Some(c) = chars.next() { + result.push(c); + if result.ends_with(".000000000") { + for _ in 0..".000000000".len() { + result.pop(); + } + write!(result, ".{:09}", self.nano()).unwrap() + } else if result.ends_with(".000000") { + for _ in 0..".000000".len() { + result.pop(); + } + write!(result, ".{:06}", self.nano() / 1000).unwrap() + } else if result.ends_with("+00:00") { + for _ in 0.."+00:00".len() { + result.pop(); + } + h = h.abs(); + m = m.abs(); + write!(result, "{}{:02}:{:02}", add_sub, h, m).unwrap(); + } else if result.ends_with("YYYY") { + for _ in 0.."YYYY".len() { + result.pop(); + } + write!(result, "{:04}", self.year()).unwrap() + } else if result.ends_with("MM") { + for _ in 0.."MM".len() { + result.pop(); + } + result.write_fmt(format_args!("{:02}", self.mon())).unwrap() + } else if result.ends_with("DD") { + for _ in 0.."DD".len() { + result.pop(); + } + write!(result, "{:02}", self.day()).unwrap() + } else if result.ends_with("hh") { + for _ in 0.."hh".len() { + result.pop(); + } + write!(result, "{:02}", self.hour()).unwrap() + } else if result.ends_with("mm") { + for _ in 0.."mm".len() { + result.pop(); + } + write!(result, "{:02}", self.minute()).unwrap(); + } else if result.ends_with("ss") { + for _ in 0.."ss".len() { + result.pop(); + } + write!(result, "{:02}", self.sec()).unwrap(); + } } - fmt.replacen("YYYY", &self.year().to_string(), 1) - .replacen("MM", &self.mon().to_string(), 1) - .replacen("DD", &self.day().to_string(), 1) - .replacen("hh", &self.hour().to_string(), 1) - .replacen("mm", &self.minute().to_string(), 1) - .replacen("ss", &self.sec().to_string(), 1) - .replacen(".000000000", &format!(".{:09}", self.nano()), 1) - .replacen(".000000", &format!(".{:06}", self.micro()), 1) - .replacen("+00:00", &format!("{}{:02}:{:02}", add_sub, h, m), 1) - .to_string() + result } /// parse an string by format. @@ -400,7 +438,7 @@ impl DateTime { Self { inner: time1::OffsetDateTime::from(s), } - .set_offset(offset) + .set_offset(offset) } /// stand "0000-00-00 00:00:00.000000000" @@ -611,7 +649,7 @@ impl From for DateTime { "{:04}-{:02}-{:02} 00:00:00.000000000Z", arg.year, arg.mon, arg.day )) - .unwrap() + .unwrap() } } @@ -630,7 +668,7 @@ impl From