unit Test.Myc.Ast.RTL.DateTime; interface uses DUnitX.TestFramework, System.SysUtils, System.DateUtils, System.Math, Myc.Ast.Environment, Myc.Ast.Script, Myc.Data.Value, Myc.Data.Scalar; type [TestFixture] [IgnoreMemoryLeaks] TTestRtlDateTime = class private FEnv: TAstEnvironment; public [Setup] procedure Setup; [Teardown] procedure Teardown; [Test] procedure Test_Constructor_FixedDate; [Test] procedure Test_Constructor_Now; [Test] [TestCase('Later', '2025,1,1,2024,1,1,True')] [TestCase('Earlier', '2020,1,1,2021,1,1,False')] procedure Test_GreaterThan(Y1, M1, D1, Y2, M2, D2: Integer; ExpectTrue: Boolean); [Test] procedure Test_Equality; [Test] procedure Test_DateTime_Is_Truthy; [Test] procedure Test_Round_DateTime; end; implementation procedure TTestRtlDateTime.Setup; begin // Creates a fresh environment with all RTL functions registered // (including Date, Now, True, False) FEnv := TAstEnvironment.Construct(nil); end; procedure TTestRtlDateTime.Teardown; begin // Environment is a record (interface wrapper), automatic cleanup end; procedure TTestRtlDateTime.Test_Constructor_FixedDate; var Res: TDataValue; Expected: TDateTime; begin // Act Res := FEnv.Run(TAstScript.Parse('(date 2025 11 24)')); // Assert Assert.AreEqual(TDataValueKind.vkScalar, Res.Kind, 'Result should be scalar'); Assert.AreEqual(TScalar.TKind.DateTime, Res.AsScalar.Kind, 'Scalar kind should be DateTime'); Expected := EncodeDate(2025, 11, 24); Assert.AreEqual(Expected, Res.AsScalar.Value.AsDouble, 0.0001, 'Date value mismatch'); end; procedure TTestRtlDateTime.Test_Constructor_Now; var Res: TDataValue; Before, After: TDateTime; begin Before := System.SysUtils.Now; // Allow small window for execution time Sleep(1); // Act Res := FEnv.Run(TAstScript.Parse('(now)')); After := System.SysUtils.Now; // Assert Assert.AreEqual(TScalar.TKind.DateTime, Res.AsScalar.Kind); // Check if result is within the time window Assert.IsTrue(Res.AsScalar.Value.AsDouble >= Before); Assert.IsTrue(Res.AsScalar.Value.AsDouble <= After); end; procedure TTestRtlDateTime.Test_GreaterThan(Y1, M1, D1, Y2, M2, D2: Integer; ExpectTrue: Boolean); var Script: string; Res: TDataValue; begin // (> (Date y1 m1 d1) (Date y2 m2 d2)) Script := Format('(> (date %d %d %d) (date %d %d %d))', [Y1, M1, D1, Y2, M2, D2]); Res := FEnv.Run(TAstScript.Parse(Script)); Assert.AreEqual(TScalar.TKind.Boolean, Res.AsScalar.Kind); if ExpectTrue then Assert.AreEqual(Int64(1), Res.AsScalar.Value.AsInt64, 'Expected True') else Assert.AreEqual(Int64(0), Res.AsScalar.Value.AsInt64, 'Expected False'); end; procedure TTestRtlDateTime.Test_Equality; var Res: TDataValue; begin // (= (Date 2023 10 10) (Date 2023 10 10)) Res := FEnv.Run(TAstScript.Parse('(= (date 2023 10 10) (date 2023 10 10))')); Assert.AreEqual(TScalar.TKind.Boolean, Res.AsScalar.Kind); Assert.AreEqual(Int64(1), Res.AsScalar.Value.AsInt64); end; procedure TTestRtlDateTime.Test_DateTime_Is_Truthy; var Res: TDataValue; begin // (if (Date 2023 1 1) "yes" "no") // Checks if IsTruthy correctly handles TKind.DateTime Res := FEnv.Run(TAstScript.Parse('(if (date 2023 1 1) "yes" "no")')); Assert.AreEqual(TDataValueKind.vkText, Res.Kind); Assert.AreEqual('yes', Res.AsText); end; procedure TTestRtlDateTime.Test_Round_DateTime; var Res: TDataValue; InputDate: TDateTime; Expected: Int64; begin // Ensure RTL Round handles DateTime as float // (Round (Date 2023 11 24)) // Date creates a TDateTime (Double) with 0.0 time fraction, so Round should return the truncation. InputDate := EncodeDate(2023, 11, 24); Expected := System.Round(InputDate); Res := FEnv.Run(TAstScript.Parse('(round (date 2023 11 24))')); Assert.AreEqual(TScalar.TKind.Ordinal, Res.AsScalar.Kind); Assert.AreEqual(Expected, Res.AsScalar.Value.AsInt64); end; end.