Skip to content

Commit

Permalink
Start building fmrc utils
Browse files Browse the repository at this point in the history
  • Loading branch information
mpiannucci committed Mar 11, 2024
1 parent 08f2345 commit 8b7f82d
Showing 1 changed file with 75 additions and 21 deletions.
96 changes: 75 additions & 21 deletions src/tools/date.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
use chrono::{DateTime, Duration, Timelike, Utc};

/// Creates a datetime object for the most recent model run output for stations data given the logic that
/// weather models run at 0Z, 6Z, 12Z, and 18Z
pub fn closest_gfs_model_stations_datetime(datetime: &DateTime<Utc>) -> DateTime<Utc> {
let adjusted = *datetime + Duration::hours(-6);
let latest_model_hour = adjusted.hour() % 6;
(adjusted - Duration::hours(latest_model_hour as i64))
// Rounds the datetime to the nearest multiple hour
// For example, if the datetime is 2023-04-13 23:00:00 and the multiplier is 6, the result would be 2023-04-13 18:00:00
// If the datetime is 2023-04-13 23:00:00 and the multiplier is 3, the result would be 2023-04-13 21:00:00
// This operation is a floor, meaning that it will only round down to the nearest multiple hour
pub fn round_to_nearest_multiple_hour(datetime: &DateTime<Utc>, multiplier: u32) -> DateTime<Utc> {
let hour = datetime.hour();
let remainder = hour % multiplier;
let rounded_hour = hour - remainder;
datetime
.with_hour(rounded_hour)
.unwrap()
.with_minute(0)
.unwrap()
.with_second(0)
Expand All @@ -14,18 +19,31 @@ pub fn closest_gfs_model_stations_datetime(datetime: &DateTime<Utc>) -> DateTime
.unwrap()
}

/// Creates a datetime object for the most recent model run output for stations data given the logic that
/// weather models run at 0Z, 6Z, 12Z, and 18Z
pub fn closest_gfs_model_stations_datetime(datetime: &DateTime<Utc>) -> DateTime<Utc> {
let adjusted = *datetime + Duration::hours(-6);
round_to_nearest_multiple_hour(&adjusted, 6)
}

/// Creates a datetime object for the most recent model run for gridded data given the logic that
/// weather models run at 0Z, 6Z, 12Z, and 18Z
pub fn closest_gfs_model_gridded_datetime(datetime: &DateTime<Utc>) -> DateTime<Utc> {
let adjusted = *datetime + Duration::hours(-5);
let latest_model_hour = adjusted.hour() % 6;
(adjusted - Duration::hours(latest_model_hour as i64))
.with_minute(0)
.unwrap()
.with_second(0)
.unwrap()
.with_nanosecond(0)
.unwrap()
round_to_nearest_multiple_hour(&adjusted, 6)
}

// TODO: Fix and document this function
pub fn gfs_model_gridded_fmrc_datetimes(
(start, end): (DateTime<Utc>, DateTime<Utc>),
) -> Vec<DateTime<Utc>> {
let mut datetimes = vec![];
let mut current = start;
while current <= end {
datetimes.push(closest_gfs_model_gridded_datetime(&current));
current = current + Duration::hours(6);
}
datetimes
}

/// Creates a datetime object for the most recent model run given the logic that
Expand All @@ -43,12 +61,32 @@ pub fn closest_hourly_model_datetime(datetime: &DateTime<Utc>) -> DateTime<Utc>

#[cfg(test)]
mod test {
use crate::tools::date::{closest_gfs_model_gridded_datetime, closest_gfs_model_stations_datetime};
use crate::tools::date::{
closest_gfs_model_gridded_datetime, closest_gfs_model_stations_datetime,
closest_hourly_model_datetime, round_to_nearest_multiple_hour,
};
use chrono::prelude::*;

#[test]
fn test_closest_station_model_datetime() {
use chrono::prelude::*;
fn test_round_to_nearest_multiple_hour() {
let datetime = Utc.with_ymd_and_hms(2023, 4, 13, 23, 0, 0).unwrap();
let expected = Utc.with_ymd_and_hms(2023, 4, 13, 18, 0, 0).unwrap();
let result = round_to_nearest_multiple_hour(&datetime, 6);
assert_eq!(result, expected);

let datetime = Utc.with_ymd_and_hms(2023, 4, 13, 23, 0, 0).unwrap();
let expected = Utc.with_ymd_and_hms(2023, 4, 13, 21, 0, 0).unwrap();
let result = round_to_nearest_multiple_hour(&datetime, 3);
assert_eq!(result, expected);

let datetime = Utc.with_ymd_and_hms(2023, 4, 13, 23, 0, 0).unwrap();
let expected = Utc.with_ymd_and_hms(2023, 4, 13, 23, 0, 0).unwrap();
let result = round_to_nearest_multiple_hour(&datetime, 1);
assert_eq!(result, expected);
}

#[test]
fn test_gfs_closest_station_model_datetime() {
let datetime = Utc.with_ymd_and_hms(2023, 4, 13, 23, 0, 0).unwrap();
let expected = Utc.with_ymd_and_hms(2023, 4, 13, 12, 0, 0).unwrap();

Expand All @@ -57,13 +95,29 @@ mod test {
}

#[test]
fn test_closest_gridded_model_datetime() {
use chrono::prelude::*;

fn test_gfs_closest_gridded_model_datetime() {
let datetime = Utc.with_ymd_and_hms(2023, 4, 13, 23, 0, 0).unwrap();
let expected = Utc.with_ymd_and_hms(2023, 4, 13, 18, 0, 0).unwrap();

let result = closest_gfs_model_gridded_datetime(&datetime);
assert_eq!(result, expected);
}
}

// #[test]
// fn test_gfs_gridded_model_fmrc_datetime() {
// let start = Utc.with_ymd_and_hms(2023, 4, 13, 0, 0, 0).unwrap();
// let end = Utc.with_ymd_and_hms(2023, 4, 14, 0, 0, 0).unwrap();

// let result = gfs_model_gridded_fmrc_datetimes((start, end));
// println!("{:?}", result);
// }

#[test]
fn test_closest_hourly_model_datetime() {
let datetime = Utc.with_ymd_and_hms(2023, 4, 13, 23, 0, 0).unwrap();
let expected = Utc.with_ymd_and_hms(2023, 4, 13, 21, 0, 0).unwrap();

let result = closest_hourly_model_datetime(&datetime);
assert_eq!(result, expected);
}
}

0 comments on commit 8b7f82d

Please sign in to comment.