Skip to main content

opening_hours/localization/
coordinates.rs

1use chrono::NaiveDate;
2use opening_hours_syntax::rules::time::TimeEvent;
3use sunrise::{DawnType, SolarDay, SolarEvent};
4
5/// A valid pair of geographic coordinates.
6///
7/// See https://en.wikipedia.org/wiki/Geographic_coordinate_system
8#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
9pub struct Coordinates(sunrise::Coordinates);
10
11impl Coordinates {
12    /// Validate a pair of latitude / longitude.
13    ///
14    /// Return `None` if values are out of range (`abs(lat) > 90` or
15    /// `abs(lon) > 180`).
16    pub const fn new(lat: f64, lon: f64) -> Option<Self> {
17        match sunrise::Coordinates::new(lat, lon) {
18            Some(c) => Some(Self(c)),
19            None => None,
20        }
21    }
22
23    /// Get the time for a sun event at a given date.
24    pub fn event_time(
25        &self,
26        date: NaiveDate,
27        event: TimeEvent,
28    ) -> Option<chrono::DateTime<chrono::Utc>> {
29        let solar_event = match event {
30            TimeEvent::Dawn => SolarEvent::Dawn(DawnType::Civil),
31            TimeEvent::Sunrise => SolarEvent::Sunrise,
32            TimeEvent::Sunset => SolarEvent::Sunset,
33            TimeEvent::Dusk => SolarEvent::Dusk(DawnType::Civil),
34        };
35
36        let solar_day = SolarDay::new(self.0, date);
37        solar_day.event_time(solar_event)
38    }
39
40    /// Get latitude component.
41    pub fn lat(&self) -> f64 {
42        self.0.lat()
43    }
44
45    /// Get longitude component.
46    pub fn lon(&self) -> f64 {
47        self.0.lon()
48    }
49}
50
51impl std::fmt::Display for Coordinates {
52    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53        write!(f, "({}, {})", self.lat(), self.lon())
54    }
55}