Skip to content
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 src/shacl2code/lang/templates/rust/Cargo.toml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
chrono = { version = "0.4", features = ["serde"] }
chrono = { version = "0.4.31", features = ["serde"] }
lazy_static = "1.4"
regex = "1"
serde = { version = "1", features = ["derive"] }
Expand Down
6 changes: 3 additions & 3 deletions src/shacl2code/lang/templates/rust/lib.rs.j2
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,9 @@ fn decode_datetime_string(
"" => {
let naive = NaiveDateTime::parse_from_str(base, "%Y-%m-%dT%H:%M:%S")
.map_err(|e| Error::Decode(path.to_string(), format!("Invalid date time '{}': {}", s, e)))?;
let local_offset = *Local::now().offset();
Ok(local_offset.from_local_datetime(&naive).single()
.ok_or_else(|| Error::Decode(path.to_string(), format!("Ambiguous local time '{}'", s)))?)
Ok(Local.from_local_datetime(&naive).single()
.ok_or_else(|| Error::Decode(path.to_string(), format!("Ambiguous local time '{}'", s)))?
.fixed_offset())
}
_ => {
let full = format!("{}{}", base, tz);
Expand Down
31 changes: 29 additions & 2 deletions tests/test_rust.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import textwrap
from enum import Enum
from pathlib import Path
from typing import Callable, Optional

import pytest

Expand Down Expand Up @@ -117,7 +118,7 @@ def f(code_fragment, *, passes=True, progress=None):
[dependencies]
shacl_model = {{ path = "{test_lib}" }}
serde_json = "1"
chrono = {{ version = "0.4", features = ["serde"] }}
chrono = {{ version = "0.4.31", features = ["serde"] }}
"""))

src = tmp_path / "src" / "main.rs"
Expand Down Expand Up @@ -643,6 +644,32 @@ def test_datetime_decode(compile_test, value, expect):
), f"Test failed. Expected {s!r}, got {output.rstrip()!r}"


def test_datetime_decode_dst_transition(
compile_test: Callable[..., Optional[str]], monkeypatch: pytest.MonkeyPatch
) -> None:
"""Offset must reflect the daylight saving time (DST) rule of the
parsed date, not of "now"."""
monkeypatch.setenv("TZ", "America/New_York")

# Winter and summer require different offsets, so both must be resolved per-date, not from "now".
output = compile_test(
"""\
let path = Path::new();

let winter = decode_date_time("2024-01-15T12:00:00", &path)?;
println!("{}", encode_date_time(&winter));

let summer = decode_date_time("2024-07-15T12:00:00", &path)?;
println!("{}", encode_date_time(&summer));
""",
)
assert output is not None

lines = output.splitlines()
assert lines[0] == "2024-01-15T12:00:00-05:00", "EST (no DST) offset expected"
assert lines[1] == "2024-07-15T12:00:00-04:00", "EDT (DST) offset expected"


@timetests.datetimestamp_decode_tests()
def test_datetimestamp_decode(compile_test, value, expect):
output = compile_test(
Expand Down Expand Up @@ -724,7 +751,7 @@ def test_extensible_context(compile_test, roundtrip):


class _Prop:
def __init__(self, path, varname=None):
def __init__(self, path: str, varname: Optional[str] = None) -> None:
self.path = path
self.varname = varname if varname is not None else path

Expand Down
Loading