| Crates.io | range_date |
| lib.rs | range_date |
| version | 0.2.3 |
| created_at | 2025-09-15 14:46:48.065531+00 |
| updated_at | 2025-11-26 03:06:52.840214+00 |
| description | A powerful Rust crate for handling date periods with embedded data and comprehensive date range operations. |
| homepage | https://github.com/GuoMonth/range_date |
| repository | https://github.com/GuoMonth/range_date |
| max_upload_size | |
| id | 1840152 |
| size | 87,961 |
A powerful Rust crate for handling date periods with embedded data and comprehensive date range operations.
chrono libraryAdd this to your Cargo.toml:
[dependencies]
range_date = "0.2.3"
use range_date::range_type::DatePeriod;
use std::str::FromStr;
// Create date periods with validation
let q1_2024 = DatePeriod::quarter(2024, 1).unwrap();
let may_2024 = DatePeriod::month(2024, 5).unwrap();
// String representation
println!("{}", q1_2024); // Output: 2024Q1
println!("{}", may_2024); // Output: 2024M5
// Parse from string
let parsed = DatePeriod::from_str("2024M03").unwrap();
println!("{:?}", parsed); // DatePeriod::Month(2024, 3)
// Get date ranges
let first_day = q1_2024.get_first_day()?; // 2024-01-01
let last_day = q1_2024.get_last_day()?; // 2024-03-31
use range_date::range_type::DatePeriod;
// Create with validation
let year_2024 = DatePeriod::year(2024);
let q2_2024 = DatePeriod::quarter(2024, 2).unwrap(); // Q2: April-June
let march_2024 = DatePeriod::month(2024, 3).unwrap(); // March
let day_60 = DatePeriod::daily(2024, 60).unwrap(); // 60th day of 2024
// Validation catches errors
assert!(DatePeriod::quarter(2024, 5).is_err()); // Quarter 5 doesn't exist
assert!(DatePeriod::month(2024, 13).is_err()); // Month 13 doesn't exist
assert!(DatePeriod::daily(2023, 366).is_err()); // Day 366 invalid in non-leap year
use range_date::range_type::DatePeriod;
use chrono::NaiveDate;
let date = NaiveDate::from_ymd_opt(2024, 8, 15).unwrap(); // August 15, 2024
// Convert to different period types
let as_year = DatePeriod::from_date_as_year(date); // 2024Y
let as_quarter = DatePeriod::from_date_as_quarter(date); // 2024Q3
let as_month = DatePeriod::from_date_as_month(date); // 2024M8
let as_daily = DatePeriod::from_date_as_daily(date); // 2024D228
use range_date::range_type::DatePeriod;
use chrono::NaiveDate;
let q1_2024 = DatePeriod::quarter(2024, 1).unwrap();
// Get date boundaries
let start = q1_2024.get_first_day()?; // 2024-01-01
let end = q1_2024.get_last_day()?; // 2024-03-31
// Check date containment
let valentine = NaiveDate::from_ymd_opt(2024, 2, 14).unwrap();
let contains = q1_2024.contains_date(valentine); // true
use range_date::range_type::DatePeriod;
use serde_json;
let quarter = DatePeriod::quarter(2024, 2).unwrap();
let json = serde_json::to_string(&quarter).unwrap();
println!("{}", json); // "2024Q2"
let deserialized: DatePeriod = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, DatePeriod::Quarter(2024, 2));
use range_date::range_type::DatePeriod;
use chrono::NaiveDate;
// Range generation - Generate all periods between two dates
let start = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
let end = NaiveDate::from_ymd_opt(2024, 6, 30).unwrap();
let quarters = DatePeriod::between_date_as_quarter(start, end).unwrap();
assert_eq!(quarters.len(), 2); // Q1 and Q2 2024
// Period navigation - Get next/previous periods
let q1 = DatePeriod::quarter(2024, 1).unwrap();
let q2 = q1.succ().unwrap(); // Next: 2024Q2
let back_to_q1 = q2.pred().unwrap(); // Previous: 2024Q1
// Bulk period navigation - Advance or retreat by multiple steps
let q4 = q1.succ_n(3).unwrap(); // Advance 3 quarters: 2024Q4
let back_to_q1_bulk = q4.pred_n(3).unwrap(); // Retreat 3 quarters: 2024Q1
let offset_q3 = q1.offset_n(2).unwrap(); // Unified offset: 2024Q3
let offset_back = q4.offset_n(-1).unwrap(); // Unified offset backward: 2024Q3
// Period decomposition - Break down into sub-periods
let year_2024 = DatePeriod::year(2024);
let quarters_in_year = year_2024.decompose();
assert_eq!(quarters_in_year.len(), 4); // 4 quarters in a year
// Period aggregation - Get parent period
let month = DatePeriod::month(2024, 5).unwrap();
let quarter = month.aggregate();
assert_eq!(quarter, DatePeriod::quarter(2024, 2).unwrap());
use range_date::range_type::DatePeriod;
let period = DatePeriod::quarter(2024, 2).unwrap();
// Query period information
assert_eq!(period.get_year(), 2024);
assert_eq!(period.value(), 2); // Quarter number
assert_eq!(period.short_name(), "Q");
assert_eq!(period.period_name(), "QUARTER");
The crate uses a compact string format for date periods:
YYYY[PERIOD][INDEX]2024Y - Year 20242024Q2 - Q2 2024 (April-June)2024M03 - March 20242024D060 / 2024D60 - 60th day of 2024| Period | Constructor | String Format | Description |
|---|---|---|---|
| Year | DatePeriod::year(2024) |
2024Y |
Entire year |
| Quarter | DatePeriod::quarter(2024, 1) |
2024Q1 |
Q1: Jan-Mar, Q2: Apr-Jun, etc. |
| Month | DatePeriod::month(2024, 3) |
2024M3 |
Specific month (1-12) |
| Daily | DatePeriod::daily(2024, 60) |
2024D60 |
Specific day of year (1-366) |
For complete API documentation, visit docs.rs.
Run the comprehensive test suite:
# Run all tests
cargo test
# Run specific test files
cargo test --test integration_tests
cargo test --test year_format_tests
# Run tests with output for manual verification
cargo test test_constructor_examples -- --nocapture
cargo test test_year_format -- --nocapture
This project is licensed under the MIT License - see the LICENSE file for details.
We welcome contributions! Here are several ways you can help:
git checkout -b feature/amazing-feature)cargo test)cargo fmt) and linting (cargo clippy)git commit -am 'Add amazing feature')git push origin feature/amazing-feature)Have questions or suggestions? Please open an issue - we'd love to hear from you!