Skip to content

Commit 149b7b5

Browse files
fix datetime
1 parent 0679046 commit 149b7b5

File tree

3 files changed

+35
-20
lines changed

3 files changed

+35
-20
lines changed

packages/common-library/src/common_library/pydantic_validators.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
1-
import datetime
1+
import datetime as dt
22
import re
33
import warnings
4-
from datetime import timedelta
54

65
from pydantic import TypeAdapter, field_validator
76

87

9-
def _validate_legacy_timedelta_str(time_str: str | timedelta) -> str | timedelta:
8+
def validate_legacy_datetime_str(v: str | dt.datetime) -> dt.datetime:
9+
if isinstance(v, dt.datetime):
10+
return v
11+
try:
12+
return dt.datetime.fromisoformat(v)
13+
except ValueError:
14+
pass
15+
16+
try:
17+
return dt.datetime.strptime(v, "%Y-%m-%d %H:%M:%S.%f%z")
18+
except ValueError:
19+
raise ValueError("Timestamp must be in a recognized datetime format")
20+
21+
22+
def _validate_legacy_timedelta_str(time_str: str | dt.timedelta) -> str | dt.timedelta:
1023
if not isinstance(time_str, str):
1124
return time_str
1225

@@ -34,14 +47,14 @@ def validate_numeric_string_as_timedelta(field: str):
3447
"""Transforms a float/int number into a valid datetime as it used to work in the past"""
3548

3649
def _numeric_string_as_timedelta(
37-
v: datetime.timedelta | str | float,
38-
) -> datetime.timedelta | str | float:
50+
v: dt.timedelta | str | float,
51+
) -> dt.timedelta | str | float:
3952
if isinstance(v, str):
4053
try:
4154
converted_value = float(v)
4255

43-
iso8601_format = TypeAdapter(timedelta).dump_python(
44-
timedelta(seconds=converted_value), mode="json"
56+
iso8601_format = TypeAdapter(dt.timedelta).dump_python(
57+
dt.timedelta(seconds=converted_value), mode="json"
4558
)
4659
warnings.warn(
4760
f"{field}='{v}' -should be set to-> {field}='{iso8601_format}' (ISO8601 datetime format). "

services/director-v2/src/simcore_service_director_v2/models/comp_runs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ def convert_null_to_empty_metadata(cls, v):
106106
"iteration": 12,
107107
"result": "SUCCESS",
108108
"created": "2021-03-01 13:07:34.19161",
109-
"modified": "2021-03-0 13:07:34.19161",
110-
"started": "2021-03-01 8:07:34.19161",
109+
"modified": "2021-03-01 13:07:34.19161",
110+
"started": "2021-03-01 08:07:34.19161",
111111
"ended": "2021-03-01 13:07:34.10",
112112
"metadata": {
113113
"node_id_names_map": {},

services/director-v2/src/simcore_service_director_v2/models/comp_tasks.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import datetime
1+
import datetime as dt
22
from contextlib import suppress
33
from typing import Annotated, Any
44

5+
from common_library.pydantic_validators import validate_legacy_datetime_str
56
from dask_task_models_library.container_tasks.protocol import ContainerEnvsDict
67
from models_library.api_schemas_directorv2.services import NodeRequirements
78
from models_library.basic_regex import SIMPLE_VERSION_RE
@@ -16,6 +17,7 @@
1617
from models_library.services_resources import BootMode
1718
from pydantic import (
1819
BaseModel,
20+
BeforeValidator,
1921
ByteSize,
2022
ConfigDict,
2123
Field,
@@ -128,25 +130,25 @@ class CompTaskAtDB(BaseModel):
128130
description="the hex digest of the resolved inputs +outputs hash at the time when the last outputs were generated",
129131
)
130132
image: Image
131-
submit: datetime.datetime
132-
start: datetime.datetime | None = Field(default=None)
133-
end: datetime.datetime | None = Field(default=None)
133+
submit: dt.datetime
134+
start: dt.datetime | None = None
135+
end: dt.datetime | None = None
134136
state: RunningState
135-
task_id: PositiveInt | None = Field(default=None)
137+
task_id: PositiveInt | None = None
136138
internal_id: PositiveInt
137139
node_class: NodeClass
138-
errors: list[ErrorDict] | None = Field(default=None)
140+
errors: list[ErrorDict] | None = None
139141
progress: float | None = Field(
140142
default=None,
141143
ge=0.0,
142144
le=1.0,
143145
description="current progress of the task if available",
144146
)
145-
last_heartbeat: datetime.datetime | None = Field(
147+
last_heartbeat: dt.datetime | None = Field(
146148
..., description="Last time the running task was checked by the backend"
147149
)
148-
created: datetime.datetime
149-
modified: datetime.datetime
150+
created: Annotated[dt.datetime, BeforeValidator(validate_legacy_datetime_str)]
151+
modified: Annotated[dt.datetime, BeforeValidator(validate_legacy_datetime_str)]
150152
# Additional information about price and hardware (ex. AWS EC2 instance type)
151153
pricing_info: dict | None
152154
hardware_info: HardwareInfo
@@ -165,9 +167,9 @@ def _convert_state_from_state_type_enum_if_needed(cls, v):
165167

166168
@field_validator("start", "end", "submit")
167169
@classmethod
168-
def _ensure_utc(cls, v: datetime.datetime | None) -> datetime.datetime | None:
170+
def _ensure_utc(cls, v: dt.datetime | None) -> dt.datetime | None:
169171
if v is not None and v.tzinfo is None:
170-
v = v.replace(tzinfo=datetime.UTC)
172+
v = v.replace(tzinfo=dt.UTC)
171173
return v
172174

173175
@field_validator("hardware_info", mode="before")

0 commit comments

Comments
 (0)