chrono icon indicating copy to clipboard operation
chrono copied to clipboard

plus_months function of the DateLike trait

Open dmitriibundin opened this issue 5 years ago • 4 comments
trafficstars

Is there a way to add some number of months to NaiveDate? I'm looking for something with the following behavior

assert_eq!(NaiveDate::from_ymd(2015,  1,  5).add_months(10), Some(NaiveDate::from_ymd(2015,  11,  5)));
assert_eq!(NaiveDate::from_ymd(2015,  1,  31).add_months(1), None);

Is it currently implemented somewhere?

dmitriibundin avatar Aug 21 '20 18:08 dmitriibundin

Unfortunately not, the closest you can get is adding days or durations.

quodlibetor avatar Aug 21 '20 19:08 quodlibetor

+1 on this and probably related to https://github.com/chronotope/chrono/issues/52

Would be nice to be able to get last month

doivosevic avatar Nov 16 '20 10:11 doivosevic

use chrono::{ Datelike, NaiveDate, ParseResult}; fn main() {

let fmt = "%Y-%m-%d";
//

let str_date: String = "2020-12-1".to_string(); // 2021-01-04 20:02:09
println!("now: {}", str_date);
//
let result: ParseResult<NaiveDate> = NaiveDate::parse_from_str(str_date.as_str(), fmt);
if result.is_err() {
    result.expect("parse error");
}
let date: NaiveDate = result.unwrap();


println!("time: {}, parsed from:'{}'", date, str_date);

println!("{}",year_add(&date,1));
println!("{}",month_add(&date,11));
//

println!("{}",-5/12);
println!("{}",-5%12);

let mut v=vec![];
let t=["2020-1-1",
    "2020-1-31",
    "2020-2-1",
    "2020-2-29",
    "2020-3-1",
    "2020-3-31",
    "2020-4-1",
    "2020-4-30",
    "2020-5-1",
    "2020-5-31",
    "2020-6-1",
    "2020-6-30",
    "2020-7-1",
    "2020-7-31",
    "2020-8-1",
    "2020-8-31",
    "2020-9-1",
    "2020-9-30",
    "2020-10-1",
    "2020-10-31",
    "2020-11-1",
    "2020-11-30",
    "2020-12-1",
    "2020-12-31",
];
for i in &t {
    let result: ParseResult<NaiveDate> = NaiveDate::parse_from_str(i, fmt);
    if result.is_err() {
        result.expect("parse error");
        break;
    }
    let date: NaiveDate = result.unwrap();
    v.push(date);
}
for i in v.iter() {
    //println!("{}",i);
    for j in  -48..=48 {
        println!("{}+{}====={}",i.to_string(),j,month_add(i,j));
    }
    println!("======================================")
}

}

fn year_add(date:&NaiveDate,i:i32)->String { let month=date.month(); let day=date.day(); //is_leap_year(date.year()) match is_leap_year(date.year()) { true=>match is_leap_year(date.year()+i){ true=>{
format!("{}-{}-{}",date.year()+i,month,day)
}, false=>{ if month==2&&day==29 { format!("{}-{}-{}",date.year()+i,month,day-1) }else{ format!("{}-{}-{}",date.year()+i,month,day) }

        }
    },
    false=>match is_leap_year(date.year()+i){
        true=>{
            if month==2&&day==28 {
                format!("{}-{}-{}",date.year()+i,month,day+1)
            }else{
                format!("{}-{}-{}",date.year()+i,month,day)
            }
        },
        false=>{
            format!("{}-{}-{}",date.year()+i,month,day)  
        }
    }
} 

} fn is_leap_year(year:i32)->bool{ match year%100{ 0=>match year%400{ 0=>true, _=>false,

    },
    _=>match year%4{
        0=>true,
        _=>false           
    }
}

}

fn month_add(date:&NaiveDate,i:i32)->String { // let year=date.year() as i32; let month=date.month() as i32; let day=date.day() as i32; // if i==0 { // date.format("%Y-%m-%d").to_string() // }else if i>0{ // is_positive(year,month,day,i) // }else { // is_negative(year,month,day,i) // } if i==0 { format!("{}-{}-{}",year,month,day) }else { let dest_year=year+(month+i)/12; let dest_month=(month+i)%12; match dest_month{ 0=>{ format!("{}-{}-{}",dest_year-1,12,day) }, -2|-4|-5|-7|-9|-11=>{ format!("{}-{}-{}",dest_year-1,12+dest_month,day)
}, -1|-3|-6|-8=>{ match day { 31=>{format!("{}-{}-{}",dest_year-1,12+dest_month,30)}, _=>{format!("{}-{}-{}",dest_year-1,12+dest_month,day)}, } }, -10=>{ match day { 29|30|31=>{ if is_leap_year(dest_year-1){ format!("{}-{}-{}",dest_year-1,12+dest_month,29) }else { format!("{}-{}-{}",dest_year-1,12+dest_month,28) } }, _=>{format!("{}-{}-{}",dest_year-1,12+dest_month,day)}, } }, 1|3|5|7|8|10=>{ format!("{}-{}-{}",dest_year,dest_month,day) }, 2=>{ if is_leap_year(dest_year) { match day { 29|30|31=>{ format!("{}-{}-{}",dest_year,dest_month,29) }, _=>{ format!("{}-{}-{}",dest_year,dest_month,day) }, } }else { match day { 29|30|31=>{ format!("{}-{}-{}",dest_year,dest_month,28) }, _=>{ format!("{}-{}-{}",dest_year,dest_month,day) }, } } }, 4|6|9|11=>{ match day { 31=>format!("{}-{}-{}",dest_year,dest_month,30), _=>format!("{}-{}-{}",dest_year,dest_month,day) } }, _=>{"error".to_string()},
} }

}

zwq1792966796 avatar Jul 02 '21 07:07 zwq1792966796

@doivosevic and @dmitriibundin - I know it's been a while, but does #731 solve your use case?

esheppa avatar Aug 17 '22 13:08 esheppa

Added in https://github.com/chronotope/chrono/pull/731.

pitdicker avatar Jun 06 '23 19:06 pitdicker