chrono
chrono copied to clipboard
plus_months function of the DateLike trait
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?
Unfortunately not, the closest you can get is adding days or durations.
+1 on this and probably related to https://github.com/chronotope/chrono/issues/52
Would be nice to be able to get last month
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()},
}
}
}
@doivosevic and @dmitriibundin - I know it's been a while, but does #731 solve your use case?
Added in https://github.com/chronotope/chrono/pull/731.