pull/1235/head
Jason Rodney Hansen 3 years ago committed by Ivan Tham
parent febee2dc0c
commit c74cd48f38

@ -67,27 +67,16 @@ impl DateTimeIncrementor {
let has_date = format.fields.iter().any(|f| f.unit.is_date()); let has_date = format.fields.iter().any(|f| f.unit.is_date());
let has_time = format.fields.iter().any(|f| f.unit.is_time()); let has_time = format.fields.iter().any(|f| f.unit.is_time());
let date_time = &text[date_time.start()..date_time.end()];
let date_time = match (has_date, has_time) { let date_time = match (has_date, has_time) {
(true, true) => NaiveDateTime::parse_from_str( (true, true) => NaiveDateTime::parse_from_str(date_time, format.fmt).ok()?,
&text[date_time.start()..date_time.end()],
format.fmt,
)
.ok()?,
(true, false) => { (true, false) => {
let date = NaiveDate::parse_from_str( let date = NaiveDate::parse_from_str(date_time, format.fmt).ok()?;
&text[date_time.start()..date_time.end()],
format.fmt,
)
.ok()?;
date.and_hms(0, 0, 0) date.and_hms(0, 0, 0)
} }
(false, true) => { (false, true) => {
let time = NaiveTime::parse_from_str( let time = NaiveTime::parse_from_str(date_time, format.fmt).ok()?;
&text[date_time.start()..date_time.end()],
format.fmt,
)
.ok()?;
NaiveDate::from_ymd(0, 1, 1).and_time(time) NaiveDate::from_ymd(0, 1, 1).and_time(time)
} }
@ -123,22 +112,22 @@ impl Increment for DateTimeIncrementor {
static FORMATS: Lazy<Vec<Format>> = Lazy::new(|| { static FORMATS: Lazy<Vec<Format>> = Lazy::new(|| {
vec![ vec![
Format::new("%Y-%m-%d %H:%M:%S"), // 2021-11-24 07:12:23 Format::new("%Y-%m-%d %H:%M:%S").unwrap(), // 2021-11-24 07:12:23
Format::new("%Y/%m/%d %H:%M:%S"), // 2021/11/24 07:12:23 Format::new("%Y/%m/%d %H:%M:%S").unwrap(), // 2021/11/24 07:12:23
Format::new("%Y-%m-%d %H:%M"), // 2021-11-24 07:12 Format::new("%Y-%m-%d %H:%M").unwrap(), // 2021-11-24 07:12
Format::new("%Y/%m/%d %H:%M"), // 2021/11/24 07:12 Format::new("%Y/%m/%d %H:%M").unwrap(), // 2021/11/24 07:12
Format::new("%Y-%m-%d"), // 2021-11-24 Format::new("%Y-%m-%d").unwrap(), // 2021-11-24
Format::new("%Y/%m/%d"), // 2021/11/24 Format::new("%Y/%m/%d").unwrap(), // 2021/11/24
Format::new("%a %b %d %Y"), // Wed Nov 24 2021 Format::new("%a %b %d %Y").unwrap(), // Wed Nov 24 2021
Format::new("%d-%b-%Y"), // 24-Nov-2021 Format::new("%d-%b-%Y").unwrap(), // 24-Nov-2021
Format::new("%Y %b %d"), // 2021 Nov 24 Format::new("%Y %b %d").unwrap(), // 2021 Nov 24
Format::new("%b %d, %Y"), // Nov 24, 2021 Format::new("%b %d, %Y").unwrap(), // Nov 24, 2021
Format::new("%-I:%M:%S %P"), // 7:21:53 am Format::new("%-I:%M:%S %P").unwrap(), // 7:21:53 am
Format::new("%-I:%M %P"), // 7:21 am Format::new("%-I:%M %P").unwrap(), // 7:21 am
Format::new("%-I:%M:%S %p"), // 7:21:53 AM Format::new("%-I:%M:%S %p").unwrap(), // 7:21:53 AM
Format::new("%-I:%M %p"), // 7:21 AM Format::new("%-I:%M %p").unwrap(), // 7:21 AM
Format::new("%H:%M:%S"), // 23:24:23 Format::new("%H:%M:%S").unwrap(), // 23:24:23
Format::new("%H:%M"), // 23:24 Format::new("%H:%M").unwrap(), // 23:24
] ]
}); });
@ -151,55 +140,65 @@ struct Format {
} }
impl Format { impl Format {
fn new(fmt: &'static str) -> Self { fn new(fmt: &'static str) -> Result<Self, FormatError> {
let mut remaining = fmt; let mut remaining = fmt;
let mut fields = Vec::new(); let mut fields = Vec::new();
let mut regex = String::new(); let mut regex = String::new();
let mut max_len = 0; let mut max_len = 0;
while let Some(i) = remaining.find('%') { while let Some(i) = remaining.find('%') {
let mut chars = remaining[i + 1..].chars(); let after = &remaining[i + 1..];
let spec_len = if let Some(c) = chars.next() { let mut chars = after.chars();
if c == '-' { let c = chars
if chars.next().is_some() { .next()
2 .ok_or(FormatError::UnexpectedEndOfFormatString)?;
} else {
0 let spec_len = if c == '-' {
} if let Some(c) = chars.next() {
1 + c.len_utf8()
} else { } else {
1 return Err(FormatError::UnexpectedEndOfFormatString);
} }
} else { } else {
0 c.len_utf8()
}; };
if i < remaining.len() - spec_len { if i < remaining.len() - spec_len {
let specifier = &remaining[i + 1..i + 1 + spec_len]; let specifier = &after[..spec_len];
if let Some(field) = DateField::from_specifier(specifier) { if let Some(field) = DateField::from_specifier(specifier) {
fields.push(field); fields.push(field);
max_len += field.max_len + remaining[..i].len(); max_len += field.max_len + remaining[..i].len();
regex += &remaining[..i]; regex += &remaining[..i];
regex += &format!("({})", field.regex); regex += &format!("({})", field.regex);
remaining = &remaining[i + spec_len + 1..]; remaining = &after[spec_len..];
} else { } else {
regex += &remaining[..=i]; return Err(FormatError::UnsupportedSpecifier(
&remaining[i..i + 1 + spec_len],
));
} }
} else { } else {
regex += remaining; return Err(FormatError::UnexpectedEndOfFormatString);
} }
} }
let regex = Regex::new(&regex).unwrap(); let regex = Regex::new(&regex).map_err(FormatError::Regex)?;
Self { Ok(Self {
fmt, fmt,
fields, fields,
regex, regex,
max_len, max_len,
} })
} }
} }
#[derive(Clone, Debug)]
enum FormatError {
UnexpectedEndOfFormatString,
UnsupportedSpecifier(&'static str),
Regex(regex::Error),
}
impl PartialEq for Format { impl PartialEq for Format {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.fmt == other.fmt && self.fields == other.fields && self.max_len == other.max_len self.fmt == other.fmt && self.fields == other.fields && self.max_len == other.max_len
@ -348,10 +347,11 @@ fn add_months(date_time: NaiveDateTime, amount: i64) -> Option<NaiveDateTime> {
// Normalize month // Normalize month
let month = month % 12; let month = month % 12;
let month = if month.is_negative() { let month = if month.is_negative() {
month + 13 month + 12
} else { } else {
month + 1 month
} as u32; } as u32
+ 1;
let day = cmp::min(date_time.day(), ndays_in_month(year, month)); let day = cmp::min(date_time.day(), ndays_in_month(year, month));

@ -5803,17 +5803,17 @@ fn increment_impl(cx: &mut Context, amount: i64) {
let text = doc.text(); let text = doc.text();
let changes = selection.ranges().iter().filter_map(|range| { let changes = selection.ranges().iter().filter_map(|range| {
let incrementor: Option<Box<dyn Increment>> = if let Some(incrementor) = let incrementor: Box<dyn Increment> = if let Some(incrementor) =
DateTimeIncrementor::from_range(text.slice(..), *range) DateTimeIncrementor::from_range(text.slice(..), *range)
{ {
Some(Box::new(incrementor)) Box::new(incrementor)
} else if let Some(incrementor) = NumberIncrementor::from_range(text.slice(..), *range) { } else if let Some(incrementor) = NumberIncrementor::from_range(text.slice(..), *range) {
Some(Box::new(incrementor)) Box::new(incrementor)
} else { } else {
None return None;
}; };
let (range, new_text) = incrementor?.increment(amount); let (range, new_text) = incrementor.increment(amount);
Some((range.from(), range.to(), Some(new_text))) Some((range.from(), range.to(), Some(new_text)))
}); });

Loading…
Cancel
Save