finance_query_core/models/
calendar.rs1use chrono::{DateTime, TimeZone, Utc};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6#[serde(rename_all = "camelCase")]
7pub struct Calendar {
8 pub symbol: String,
9 pub earnings_date: Option<DateTime<Utc>>,
11 pub earnings_date_start: Option<DateTime<Utc>>,
13 pub earnings_date_end: Option<DateTime<Utc>>,
15 pub dividend_date: Option<DateTime<Utc>>,
17 pub ex_dividend_date: Option<DateTime<Utc>>,
19 pub dividend_rate: Option<f64>,
21 pub dividend_yield: Option<f64>,
23}
24
25impl Calendar {
26 pub(crate) fn from_yahoo_response(
27 symbol: String,
28 response: YahooCalendarResponse,
29 ) -> Result<Self, crate::client::YahooError> {
30 let result = response.quote_summary.result.first().ok_or_else(|| {
31 crate::client::YahooError::ParseError("No calendar data in response".to_string())
32 })?;
33
34 let events = &result.calendar_events;
35
36 let earnings_dates: Vec<DateTime<Utc>> = events
38 .earnings
39 .as_ref()
40 .and_then(|e| e.earnings_date.as_ref())
41 .map(|dates| {
42 dates
43 .iter()
44 .filter_map(|ts| Utc.timestamp_opt(*ts, 0).single())
45 .collect()
46 })
47 .unwrap_or_default();
48
49 let earnings_date = earnings_dates.first().copied();
50 let earnings_date_start = earnings_dates.first().copied();
51 let earnings_date_end = earnings_dates.get(1).copied().or(earnings_date_start);
52
53 let dividend_date = events
55 .dividend_date
56 .and_then(|ts| Utc.timestamp_opt(ts, 0).single());
57
58 let ex_dividend_date = events
60 .ex_dividend_date
61 .and_then(|ts| Utc.timestamp_opt(ts, 0).single());
62
63 Ok(Self {
64 symbol,
65 earnings_date,
66 earnings_date_start,
67 earnings_date_end,
68 dividend_date,
69 ex_dividend_date,
70 dividend_rate: None,
71 dividend_yield: None,
72 })
73 }
74}
75
76#[derive(Debug, Deserialize)]
78pub(crate) struct YahooCalendarResponse {
79 #[serde(rename = "quoteSummary")]
80 pub quote_summary: QuoteSummaryData,
81}
82
83#[derive(Debug, Deserialize)]
84pub(crate) struct QuoteSummaryData {
85 pub result: Vec<QuoteSummaryResult>,
86}
87
88#[derive(Debug, Deserialize)]
89pub(crate) struct QuoteSummaryResult {
90 #[serde(rename = "calendarEvents")]
91 pub calendar_events: CalendarEventsData,
92}
93
94#[derive(Debug, Deserialize)]
95pub(crate) struct CalendarEventsData {
96 pub earnings: Option<EarningsData>,
97 #[serde(rename = "dividendDate")]
98 pub dividend_date: Option<i64>,
99 #[serde(rename = "exDividendDate")]
100 pub ex_dividend_date: Option<i64>,
101}
102
103#[derive(Debug, Deserialize)]
104pub(crate) struct EarningsData {
105 #[serde(rename = "earningsDate")]
106 pub earnings_date: Option<Vec<i64>>,
107}