Get The Sunrise And Sunset Times For A Specific Location In Rust Including Daylight Saving Time

January 2025
---
[dependencies]
chrono = "0.4.39"
chrono-tz = "0.10.0"
lazy_static = "1.5.0"
sunrise = "1.0.1"
tzf-rs = "0.4.9"
---

use chrono::DateTime;
use chrono_tz::Tz;
use lazy_static::lazy_static;
use sunrise::sunrise_sunset;
use tzf_rs::DefaultFinder;

lazy_static! {
  static ref FINDER: DefaultFinder = DefaultFinder::new();
}

fn main() {
  let lat = 30.332184;
  let long = -81.655647;
  println!(
    "Daylight Time Sunrise Example: {}", 
    sunrise_for_lat_long(lat, long, 2024, 11, 2)
  );
  println!(
    "Daylight Time Sunset Example: {}", 
    sunset_for_lat_long(lat, long, 2024, 11, 2)
  );
  println!(
    "Standard Sunrise Time Example: {}", 
    sunrise_for_lat_long(lat, long, 2024, 11, 3)
  );
  println!(
    "Standard Sunset Time Example: {}", 
    sunset_for_lat_long(lat, long, 2024, 11, 3)
  );
}

fn sunrise_for_lat_long(lat: f64, long: f64, year: i32, month: u32, day: u32) -> DateTime<Tz> {
  let tz: Tz = FINDER.get_tz_name(long, lat).parse().unwrap();
  let (sunrise_ts, _) = sunrise_sunset(
    lat, long, year, month, day
  );
  let dt = DateTime::from_timestamp(sunrise_ts, 0).expect("invalid timestamp").with_timezone(&tz);
  dt
}

fn sunset_for_lat_long(lat: f64, long: f64, year: i32, month: u32, day: u32) -> DateTime<Tz> {
  let tz: Tz = FINDER.get_tz_name(long, lat).parse().unwrap();
  let (_, sunset_ts) = sunrise_sunset(
    lat, long, year, month, day
  );
  let dt = DateTime::from_timestamp(sunset_ts, 0).expect("invalid timestamp").with_timezone(&tz);
  dt
}
Output:
Daylight Time Sunrise Example: 2024-11-02 07:42:04 EDT
Daylight Time Sunset Example: 2024-11-02 18:38:12 EDT
Standard Sunrise Time Example: 2024-11-03 06:42:52 EST
Standard Sunset Time Example: 2024-11-03 17:37:26 EST

Notes

  • This code panics if there's an issue (i.e. error handling could be improved)
  • Handles daylight saving time changes
  • From what I can tell it's not necessary to convert the date into UTC before running the sunrise_sunset function. There might be a use case though based on some time zones where that would be necessary, but I haven't figured out that edge case yet if it exists.
end of line

References

The crate that does the main date handling

The crate that allows using named time zones for chrono's DateTime

A macro crate that helps speed up searching for time zones in chrono_tz when multiple searches are needed

The crate that does the calculation for sunrise and sunset given a specific lat/long

The create the provides time zones for specific lat/long coordinates