#[cfg(feature = "chrono")]
mod chrono_example {
use serde_json::Value;
use tushare_api::{
DeriveFromTushareData,
error::TushareError,
traits::{FromOptionalTushareValue, FromTushareValue},
};
#[derive(Debug, Clone)]
pub struct CustomDate(pub chrono::NaiveDate);
impl FromTushareValue for CustomDate {
fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
match value {
Value::String(s) => {
if let Ok(date) = chrono::NaiveDate::parse_from_str(s, "%d/%m/%Y") {
Ok(CustomDate(date))
} else if let Ok(date) = chrono::NaiveDate::parse_from_str(s, "%m-%d-%Y") {
Ok(CustomDate(date))
} else {
chrono::NaiveDate::from_tushare_value(value).map(CustomDate)
}
}
_ => chrono::NaiveDate::from_tushare_value(value).map(CustomDate),
}
}
}
impl FromOptionalTushareValue for CustomDate {
fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
match value {
Value::Null => Ok(None),
_ => CustomDate::from_tushare_value(value).map(Some),
}
}
}
#[derive(Debug, Clone)]
pub struct TushareDate(pub chrono::NaiveDate);
impl FromTushareValue for TushareDate {
fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
match value {
Value::String(s) => {
chrono::NaiveDate::parse_from_str(s, "%Y%m%d")
.map(TushareDate)
.map_err(|e| {
TushareError::ParseError(format!("Failed to parse date '{}': {}", s, e))
})
}
Value::Number(n) => {
if let Some(date_int) = n.as_u64() {
let date_str = date_int.to_string();
if date_str.len() == 8 {
chrono::NaiveDate::parse_from_str(&date_str, "%Y%m%d")
.map(TushareDate)
.map_err(|e| {
TushareError::ParseError(format!(
"Failed to parse date '{}': {}",
date_str, e
))
})
} else {
Err(TushareError::ParseError(format!(
"Invalid date format: {}",
date_int
)))
}
} else {
Err(TushareError::ParseError(
"Date must be a valid integer".to_string(),
))
}
}
_ => Err(TushareError::ParseError(
"Date must be a string or number".to_string(),
)),
}
}
}
impl FromOptionalTushareValue for TushareDate {
fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
match value {
Value::Null => Ok(None),
_ => TushareDate::from_tushare_value(value).map(Some),
}
}
}
#[derive(Debug, Clone, DeriveFromTushareData)]
pub struct CustomDateFormats {
#[tushare(field = "ts_code")]
pub stock_code: String,
#[tushare(field = "trade_date")]
pub trade_date: chrono::NaiveDate,
#[tushare(field = "european_date", date_format = "%d/%m/%Y")]
pub european_date: chrono::NaiveDate,
#[tushare(field = "us_date", date_format = "%m-%d-%Y")]
pub us_date: chrono::NaiveDate,
#[tushare(field = "german_date", date_format = "%d.%m.%Y")]
pub german_date: Option<chrono::NaiveDate>,
#[tushare(field = "custom_datetime", date_format = "%Y/%m/%d %H:%M")]
pub custom_datetime: chrono::NaiveDateTime,
#[tushare(field = "chinese_date", date_format = "%Y年%m月%d日")]
pub chinese_date: Option<chrono::NaiveDate>,
#[tushare(field = "utc_datetime", date_format = "%Y-%m-%d %H:%M:%S %z")]
pub utc_datetime: chrono::DateTime<chrono::Utc>,
}
pub fn run_example() {
println!("Custom Date Format Example");
println!("==========================");
use serde_json::json;
let date_values = [
json!("15/03/2024"), json!("03-15-2024"), json!("20240315"), ];
for date_value in &date_values {
match chrono::NaiveDate::from_tushare_value(date_value) {
Ok(date) => println!("Parsed date: {} -> {}", date_value, date),
Err(e) => println!("Failed to parse {}: {}", date_value, e),
}
}
let tushare_dates = [json!("20240315"), json!(20240315)];
for date_value in &tushare_dates {
match TushareDate::from_tushare_value(date_value) {
Ok(date) => println!("Parsed Tushare date: {} -> {:?}", date_value, date),
Err(e) => println!("Failed to parse Tushare date {}: {}", date_value, e),
}
}
println!();
println!("Custom Date Format Attributes:");
println!("==============================");
println!("Use #[tushare(date_format = \"...\")] to specify custom formats:");
println!(" European: #[tushare(date_format = \"%d/%m/%Y\")]");
println!(" US: #[tushare(date_format = \"%m-%d-%Y\")]");
println!(" German: #[tushare(date_format = \"%d.%m.%Y\")]");
println!(" Chinese: #[tushare(date_format = \"%Y年%m月%d日\")]");
println!(" Custom: #[tushare(date_format = \"%Y/%m/%d %H:%M\")]");
println!();
println!("This enables precise field-level date format control!");
}
}
fn main() {
#[cfg(feature = "chrono")]
{
chrono_example::run_example();
}
#[cfg(not(feature = "chrono"))]
{
println!("Custom Date Format Example");
println!("==========================");
println!();
println!("This example requires the 'chrono' feature to be enabled.");
println!("Run with: cargo run --example custom_date_format_example --features chrono");
println!();
println!("The chrono feature enables:");
println!(" - Custom date format parsing with #[tushare(date_format = \"...\")]");
println!(" - Support for chrono::NaiveDate, NaiveDateTime, DateTime<Utc>");
println!(" - Multiple date format support (European, US, German, Chinese, etc.)");
}
}