Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

editoast: use DateTime with timezone in work schedule API #9656

Merged
merged 1 commit into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion editoast/src/models/fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ pub async fn create_small_infra(conn: &mut DbConnection) -> Infra {
pub async fn create_work_schedule_group(conn: &mut DbConnection) -> WorkScheduleGroup {
WorkScheduleGroup::changeset()
.name("Empty work schedule group".to_string())
.creation_date(Utc::now().naive_utc())
.creation_date(Utc::now())
.create(conn)
.await
.expect("Failed to create empty work schedule group")
Expand Down
9 changes: 5 additions & 4 deletions editoast/src/models/work_schedules.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use chrono::NaiveDateTime;
use chrono::DateTime;
use chrono::Utc;
use editoast_derive::Model;
use editoast_schemas::infra::TrackRange;
use strum::FromRepr;
Expand All @@ -12,7 +13,7 @@ use utoipa::ToSchema;
#[model(gen(ops = crd, batch_ops = c, list))]
pub struct WorkScheduleGroup {
pub id: i64,
pub creation_date: NaiveDateTime,
pub creation_date: DateTime<Utc>,
pub name: String,
}

Expand All @@ -29,8 +30,8 @@ pub enum WorkScheduleType {
#[model(gen(batch_ops = c, list))]
pub struct WorkSchedule {
pub id: i64,
pub start_date_time: NaiveDateTime,
pub end_date_time: NaiveDateTime,
pub start_date_time: DateTime<Utc>,
pub end_date_time: DateTime<Utc>,
#[model(json)]
pub track_ranges: Vec<TrackRange>,
pub obj_id: String,
Expand Down
26 changes: 13 additions & 13 deletions editoast/src/views/timetable/stdcm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ use axum::extract::Path;
use axum::extract::Query;
use axum::extract::State;
use axum::Extension;
use chrono::Utc;
use chrono::{DateTime, Duration, NaiveDateTime, TimeZone};
use chrono::{DateTime, Duration, Utc};
use editoast_authz::BuiltinRole;
use editoast_derive::EditoastError;
use editoast_models::DbConnection;
Expand Down Expand Up @@ -786,8 +785,8 @@ async fn build_temporary_speed_limits(
Ok(applicable_speed_limits)
}

fn elapsed_since_time_ms(time: &NaiveDateTime, zero: &DateTime<Utc>) -> u64 {
max(0, (Utc.from_utc_datetime(time) - zero).num_milliseconds()) as u64
fn elapsed_since_time_ms(time: &DateTime<Utc>, zero: &DateTime<Utc>) -> u64 {
max(0, (*time - zero).num_milliseconds()) as u64
}

/// Create steps from track_map and waypoints
Expand Down Expand Up @@ -1200,17 +1199,17 @@ mod tests {

#[rstest]
// A day before the 'start_time' -> FILTERED OUT
#[case("2024-03-13 06:00:00", "2024-03-13 12:00:00", true)]
#[case("2024-03-13 06:00:00Z", "2024-03-13 12:00:00Z", true)]
// Finishing just after the 'start_time' -> KEPT
#[case("2024-03-14 06:00:00", "2024-03-14 08:01:00", false)]
#[case("2024-03-14 06:00:00Z", "2024-03-14 08:01:00Z", false)]
// Starting after the 'latest_simulation_end' -> FILTERED OUT
#[case("2024-03-14 10:01:00", "2024-03-14 12:00:00", true)]
#[case("2024-03-14 10:01:00Z", "2024-03-14 12:00:00Z", true)]
// Starting before the 'latest_simulation_end' -> KEPT
#[case("2024-03-14 09:59:00", "2024-03-14 12:00:00", false)]
#[case("2024-03-14 09:59:00Z", "2024-03-14 12:00:00Z", false)]
// Starting before the 'start_time' and finishing after 'latest_simulation_end' -> KEPT
#[case("2024-03-14 06:00:00", "2024-03-14 12:00:00", false)]
#[case("2024-03-14 06:00:00Z", "2024-03-14 12:00:00Z", false)]
// Starting after the 'start_time' and finishing before 'latest_simulation_end' -> KEPT
#[case("2024-03-14 08:30:00", "2024-03-14 09:30:00", false)]
#[case("2024-03-14 08:30:00Z", "2024-03-14 09:30:00Z", false)]
fn filter_stdcm_work_schedules_with_window(
#[case] ws_start_time: &str,
#[case] ws_end_time: &str,
Expand All @@ -1219,9 +1218,10 @@ mod tests {
// GIVEN
let work_schedules = [WorkSchedule {
id: rand::random::<i64>(),
start_date_time: NaiveDateTime::parse_from_str(ws_start_time, "%Y-%m-%d %H:%M:%S")
.unwrap(),
end_date_time: NaiveDateTime::parse_from_str(ws_end_time, "%Y-%m-%d %H:%M:%S").unwrap(),
start_date_time: DateTime::parse_from_rfc3339(ws_start_time)
.unwrap()
.to_utc(),
end_date_time: DateTime::parse_from_rfc3339(ws_end_time).unwrap().to_utc(),
..Default::default()
}];
let start_time = DateTime::parse_from_rfc3339("2024-03-14T08:00:00Z")
Expand Down
36 changes: 19 additions & 17 deletions editoast/src/views/work_schedules.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use axum::extract::Json;
use axum::extract::State;
use axum::Extension;
use chrono::NaiveDateTime;
use chrono::DateTime;
use chrono::Utc;
use derivative::Derivative;
use editoast_authz::BuiltinRole;
Expand Down Expand Up @@ -64,8 +64,8 @@ pub fn map_diesel_error(e: InternalError, name: impl AsRef<str>) -> InternalErro

#[derive(Serialize, Derivative, ToSchema)]
struct WorkScheduleItemForm {
pub start_date_time: NaiveDateTime,
pub end_date_time: NaiveDateTime,
pub start_date_time: DateTime<Utc>,
pub end_date_time: DateTime<Utc>,
pub track_ranges: Vec<TrackRange>,
pub obj_id: String,
#[schema(inline)]
Expand All @@ -80,8 +80,8 @@ impl<'de> Deserialize<'de> for WorkScheduleItemForm {
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct Internal {
start_date_time: NaiveDateTime,
end_date_time: NaiveDateTime,
start_date_time: DateTime<Utc>,
end_date_time: DateTime<Utc>,
track_ranges: Vec<TrackRange>,
obj_id: String,
work_schedule_type: WorkScheduleType,
Expand Down Expand Up @@ -163,7 +163,7 @@ async fn create(
// Create the work_schedule_group
let work_schedule_group = WorkScheduleGroup::changeset()
.name(work_schedule_group_name.clone())
.creation_date(Utc::now().naive_utc())
.creation_date(Utc::now())
.create(conn)
.await;
let work_schedule_group =
Expand Down Expand Up @@ -197,9 +197,9 @@ struct WorkScheduleProjection {
/// The type of the work schedule.
pub work_schedule_type: WorkScheduleType,
/// The date and time when the work schedule takes effect.
pub start_date_time: NaiveDateTime,
pub start_date_time: DateTime<Utc>,
/// The date and time when the work schedule ends.
pub end_date_time: NaiveDateTime,
pub end_date_time: DateTime<Utc>,
/// a list of intervals `(a, b)` that represent the projections of the work schedule track ranges:
/// - `a` is the distance from the beginning of the path to the beginning of the track range
/// - `b` is the distance from the beginning of the path to the end of the track range
Expand Down Expand Up @@ -297,8 +297,8 @@ pub mod tests {
let request = app.post("/work_schedules").json(&json!({
"work_schedule_group_name": "work schedule group name",
"work_schedules": [{
"start_date_time": "2024-01-01T08:00:00",
"end_date_time": "2024-01-01T09:00:00",
"start_date_time": "2024-01-01T08:00:00Z",
"end_date_time": "2024-01-01T09:00:00Z",
"track_ranges": [],
"obj_id": "work_schedule_obj_id",
"work_schedule_type": "CATENARY"
Expand Down Expand Up @@ -328,8 +328,8 @@ pub mod tests {
let request = app.post("/work_schedules").json(&json!({
"work_schedule_group_name": "work schedule group name",
"work_schedules": [{
"start_date_time": "2024-01-01T08:00:00",
"end_date_time": "2024-01-01T07:00:00",
"start_date_time": "2024-01-01T08:00:00Z",
"end_date_time": "2024-01-01T07:00:00Z",
"track_ranges": [],
"obj_id": "work_schedule_obj_id",
"work_schedule_type": "CATENARY"
Expand All @@ -348,16 +348,16 @@ pub mod tests {

WorkScheduleGroup::changeset()
.name("duplicated work schedule group name".to_string())
.creation_date(Utc::now().naive_utc())
.creation_date(Utc::now())
.create(&mut pool.get_ok())
.await
.expect("Failed to create work schedule group");

let request = app.post("/work_schedules").json(&json!({
"work_schedule_group_name": "duplicated work schedule group name",
"work_schedules": [{
"start_date_time": "2024-01-01T08:00:00",
"end_date_time": "2024-01-01T09:00:00",
"start_date_time": "2024-01-01T08:00:00Z",
"end_date_time": "2024-01-01T09:00:00Z",
"track_ranges": [],
"obj_id": "work_schedule_obj_id",
"work_schedule_type": "CATENARY"
Expand Down Expand Up @@ -437,12 +437,14 @@ pub mod tests {
NaiveDate::from_ymd_opt(2024, 1, (index + 1).try_into().unwrap())
.unwrap()
.and_hms_opt(0, 0, 0)
.unwrap();
.unwrap()
.and_utc();
let end_date_time =
NaiveDate::from_ymd_opt(2024, 1, (index + 2).try_into().unwrap())
.unwrap()
.and_hms_opt(0, 0, 0)
.unwrap();
.unwrap()
.and_utc();
WorkSchedule::changeset()
.start_date_time(start_date_time)
.end_date_time(end_date_time)
Expand Down
10 changes: 5 additions & 5 deletions tests/tests/test_stdcm.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def test_between_trains(small_scenario: Scenario, fast_rolling_stock: int):

def test_work_schedules(small_scenario: Scenario, fast_rolling_stock: int):
requests.post(EDITOAST_URL + f"infra/{small_scenario.infra}/load")
start_time = datetime.datetime(2024, 1, 1, 14, 0, 0)
start_time = datetime.datetime(2024, 1, 1, 14, 0, 0, tzinfo=datetime.timezone.utc)
end_time = start_time + datetime.timedelta(days=4)
# TODO: we cannot delete work schedules for now, so let's give a unique name
# to avoid collisions
Expand Down Expand Up @@ -217,10 +217,10 @@ def test_max_running_time(small_scenario: Scenario, fast_rolling_stock: int):
[ ] < departure time window
"""
requests.post(EDITOAST_URL + f"infra/{small_scenario.infra}/load")
origin_start_time = datetime.datetime(2024, 1, 1, 8, 0, 0)
origin_end_time = datetime.datetime(2025, 1, 1, 8, 0, 0)
destination_start_time = datetime.datetime(2023, 1, 1, 8, 0, 0)
destination_end_time = datetime.datetime(2024, 1, 1, 16, 0, 0)
origin_start_time = datetime.datetime(2024, 1, 1, 8, 0, 0, tzinfo=datetime.timezone.utc)
origin_end_time = datetime.datetime(2025, 1, 1, 8, 0, 0, tzinfo=datetime.timezone.utc)
destination_start_time = datetime.datetime(2023, 1, 1, 8, 0, 0, tzinfo=datetime.timezone.utc)
destination_end_time = datetime.datetime(2024, 1, 1, 16, 0, 0, tzinfo=datetime.timezone.utc)
# TODO: we cannot delete work schedules for now, so let's give a unique name
# to avoid collisions
now = datetime.datetime.now()
Expand Down
Loading