Rust日期处理库bdays的使用,高效计算生日、纪念日及周期性日期管理

Rust日期处理库bdays的使用,高效计算生日、纪念日及周期性日期管理

以下是内容中提供的示例代码:

基本使用示例

use chrono::NaiveDate;
use bdays::HolidayCalendar;

fn main() {
    // 创建假日日历实例
    let cal = bdays::calendars::WeekendsOnly;

    let d0 = NaiveDate::from_ymd(2018, 11, 22);
    let d1 = NaiveDate::from_ymd(2018, 11, 24);
    let d2 = NaiveDate::from_ymd(2018, 11, 26);

    // 检查日期是否为假日
    assert_eq!(cal.is_holiday(d0), false);

    // 检查日期是否为工作日
    assert_eq!(cal.is_bday(d0), true);
    assert_eq!(cal.is_bday(d1), false);

    // 调整到上一个/下一个工作日
    assert_eq!(cal.to_bday(d1, false), NaiveDate::from_ymd(2018, 11, 23));
    assert_eq!(cal.to_bday(d1, true), d2);

    // 前进若干工作日
    assert_eq!(cal.advance_bdays(d0, 2), d2);
    assert_eq!(cal.advance_bdays(d2, -2), d0);

    // 返回两个日期之间的工作日数量
    assert_eq!(cal.bdays(d0, d2), 2);
    assert_eq!(cal.bdays(d2, d0), -2);
}

HolidayCalendarCache示例

use chrono::NaiveDate;
use bdays::HolidayCalendar;

let cal = bdays::HolidayCalendarCache::new(
    bdays::calendars::brazil::BRSettlement,
    NaiveDate::from_ymd(1980, 1, 1),
    NaiveDate::from_ymd(2100, 12, 31)
);

let d0 = NaiveDate::from_ymd(2001, 2, 1);
let d1 = NaiveDate::from_ymd(2100, 2, 1);

for _i in 0..30 {
    cal.bdays(d0, d1);
}

完整示例demo

use chrono::NaiveDate;
use bdays::HolidayCalendar;

fn main() {
    // 使用只考虑周末的日历
    let cal = bdays::calendars::WeekendsOnly;

    // 假设生日是2020年2月20日
    let birthday = NaiveDate::from_ymd_opt(2020, 2, 20).unwrap();
    
    // 计算10个工作日后的日期
    let after_10_bdays = cal.advance_bdays(birthday, 10);
    println!("10个工作日后是: {}", after_10_bdays);

    // 计算2020年2月20日到2020年3月20日之间的工作日数量
    let end_date = NaiveDate::from_ymd_opt(2020, 3, 20).unwrap();
    let bdays_count = cal.bdays(birthday, end_date);
    println!("{}到{}之间有{}个工作日", birthday, end_date, bdays_count);

    // 检查特定日期是否为工作日
    let check_date = NaiveDate::from_ymd_opt(2020, 2, 22).unwrap(); // 周六
    println!("{}是工作日吗? {}", check_date, cal.is_bday(check_date));

    // 调整到最近的工作日
    let adjusted_date = cal.to_bday(check_date, true); // 调整为下一个工作日
    println!("调整后的工作日是: {}", adjusted_date);
}

更完整的周期性日期管理示例

use chrono::{NaiveDate, Duration};
use bdays::{HolidayCalendar, HolidayCalendarCache};
use bdays::calendars::us::USSettlement;

// 周期性日期管理函数
fn calculate_periodic_dates(
    start_date: NaiveDate,
    end_date: NaiveDate,
    interval_days: i64,
    cal: &impl HolidayCalendar
) -> Vec<NaiveDate> {
    let mut current_date = start_date;
    let mut result = Vec::new();
    
    while current_date <= end_date {
        result.push(current_date);
        current_date = cal.advance_bdays(current_date, interval_days);
    }
    
    result
}

fn main() {
    // 使用美国假日日历
    let cal = HolidayCalendarCache::new(
        USSettlement,
        NaiveDate::from_ymd_opt(2000, 1, 1).unwrap(),
        NaiveDate::from_ymd_opt(2030, 12, 31).unwrap()
    );

    // 纪念日计算
    let anniversary = NaiveDate::from_ymd_opt(2020, 5, 15).unwrap();
    let today = NaiveDate::from_ymd_opt(2023, 5, 1).unwrap();
    
    // 计算纪念日之间的工作日
    let work_days = cal.bdays(anniversary, today);
    println!("从纪念日到今天之间有{}个工作日", work_days);

    // 计算未来10个周期性日期(每30个工作日一次)
    let periodic_dates = calculate_periodic_dates(
        today,
        NaiveDate::from_ymd_opt(2024, 5, 1).unwrap(),
        30,
        &cal
    );
    
    println!("未来的周期性日期:");
    for date in periodic_dates {
        println!("- {}", date);
    }
}

这个库特别适合需要精确计算工作日的应用场景,如金融、人力资源和项目管理等领域。通过使用不同的假日日历,可以适应不同国家或地区的特殊假日安排。


1 回复

Rust日期处理库bdays的使用指南

简介

bdays是一个专门用于处理生日、纪念日和周期性日期计算的Rust库。它提供了高效的工具来计算日期之间的天数、周年纪念日、下一个生日等常见日期操作,特别适合需要处理周期性日期场景的应用程序。

主要功能

  • 计算两个日期之间的天数差
  • 计算下一个生日或纪念日
  • 处理周期性日期(每月、每年等)
  • 考虑闰年和不同月份天数差异
  • 轻量级且无依赖(仅使用Rust标准库)

安装

在Cargo.toml中添加依赖:

[dependencies]
bdays = "0.3"

基本使用方法

1. 计算日期差

use bdays::Birthday;
use chrono::NaiveDate;

fn main() {
    let birth_date = NaiveDate::from_ymd(1990, 5, 15);
    let today = NaiveDate::from_ymd(2023, 10, 20);
    
    let bday = Birthday::new(birth_date);
    let days_until_next = bday.days_until_next(today);
    
    println!("距离下一次生日还有 {} 天", days_until_next);
}

2. 计算下一个纪念日

use bdays::Anniversary;
use chrono::NaiveDate;

fn main() {
    let anniversary_date = NaiveDate::from_ymd(2015, 8, 10);
    let today = NaiveDate::from_ymd(2023, 7, 1);
    
    let anni = Anniversary::new(anniversary_date);
    let next_anni = anni.next_anniversary(today);
    
    println!("下一个纪念日是: {}", next_anni);
}

3. 计算年龄

use bdays::Birthday;
use chrono::NaiveDate;

fn main() {
    let birth_date = NaiveDate::from_ymd(1985, 11, 3);
    let today = NaiveDate::from_ymd(2023, 6, 15);
    
    let bday = Birthday::new(birth_date);
    let age = bday.age(today);
    
    println!("当前年龄: {} 岁", age);
}

4. 处理周期性日期

use bdays::PeriodicDate;
use chrono::NaiveDate;

fn main() {
    let start_date = NaiveDate::from_ymd(2023, 1, 15);
    let today = NaiveDate::from_ymd(2023, 5, 20);
    
    // 每月15日的周期性日期
    let monthly = PeriodicDate::monthly(15);
    let next_date = monthly.next_date_after(start_date, today);
    
    println!("下一个周期性日期是: {}", next_date);
}

高级用法

处理闰年生日

use bdays::Birthday;
use chrono::NaiveDate;

fn main() {
    let birth_date = NaiveDate::from_ymd(2000, 2, 29); // 闰年生日
    let today = NaiveDate::from_ymd(2023, 2, 28);
    
    let bday = Birthday::new(birth_date);
    let next_bday = bday.next_birthday(today);
    
    println!("下一个生日是: {}", next_bday); // 将显示2023-02-28
}

计算多个纪念日

use bdays::Anniversary;
use chrono::NaiveDate;

fn main() {
    let dates = vec![
        NaiveDate::from_ymd(2010, 5, 10),
        NaiveDate::from_ymd(2015, 8, 15),
        NaiveDate::from_ymd(2020, 3, 20),
    ];
    
    let today = NaiveDate::from_ymd(2023, 4, 1);
    
    for date in dates {
        let anni = Anniversary::new(date);
        println!(
            "日期: {}, 下一个周年: {}, 周年数: {}",
            date,
            anni.next_anniversary(today),
            anni.years_passed(today)
        );
    }
}

完整示例demo

下面是一个整合了bdays库主要功能的完整示例:

use bdays::{Birthday, Anniversary, PeriodicDate};
use chrono::NaiveDate;

fn main() {
    // 1. 计算生日相关数据
    let birth_date = NaiveDate::from_ymd(1995, 8, 20);
    let today = NaiveDate::from_ymd(2023, 11, 15);
    
    let bday = Birthday::new(birth_date);
    println!("\n生日: {}", birth_date);
    println!("当前年龄: {} 岁", bday.age(today));
    println!("距离下一次生日还有 {} 天", bday.days_until_next(today));
    println!("下一个生日是: {}", bday.next_birthday(today));
    
    // 2. 计算纪念日数据
    let anni_date = NaiveDate::from_ymd(2018, 6, 10);
    let anni = Anniversary::new(anni_date);
    
    println!("\n纪念日: {}", anni_date);
    println!("已庆祝周年数: {}", anni.years_passed(today));
    println!("下一个周年纪念日是: {}", anni.next_anniversary(today));
    
    // 3. 处理闰年生日特殊情况
    let leap_bday = NaiveDate::from_ymd(2000, 2, 29);
    let leap_birthday = Birthday::new(leap_bday);
    
    println!("\n闰年生日: {}", leap_bday);
    println!("2023年生日(非闰年): {}", leap_birthday.next_birthday(today));
    
    // 4. 处理周期性日期
    let period_date = NaiveDate::from_ymd(2023, 1, 10);
    let monthly = PeriodicDate::monthly(10); // 每月10日
    
    println!("\n周期性日期(每月10日)");
    println!("下一个日期是: {}", monthly.next_date_after(period_date, today));
    
    // 5. 批量处理多个日期
    let important_dates = vec![
        NaiveDate::from_ymd(2010, 3, 15),
        NaiveDate::from_ymd(2015, 7, 22),
        NaiveDate::from_ymd(2020, 11, 5),
    ];
    
    println!("\n重要日期追踪:");
    for date in important_dates {
        let anni = Anniversary::new(date);
        println!(
            "日期: {}, 周年数: {}, 下一个周年: {}",
            date,
            anni.years_passed(today),
            anni.next_anniversary(today)
        );
    }
}

注意事项

  1. bdays库依赖于chrono库的NaiveDate类型来处理日期
  2. 所有日期计算都不考虑时区
  3. 对于闰年2月29日的生日,在非闰年会默认为2月28日
  4. 周期性日期计算支持每月、每年等常见周期

bdays库非常适合需要处理生日提醒、周年纪念、周期性事件等功能的应用程序,它的API设计简洁,计算高效,是Rust生态中日期处理的一个实用工具。

回到顶部