diff --git a/csharp/App/RemoteSupportConsole/Program.cs b/csharp/App/RemoteSupportConsole/Program.cs
index 7ce5cbdcd..03067a613 100644
--- a/csharp/App/RemoteSupportConsole/Program.cs
+++ b/csharp/App/RemoteSupportConsole/Program.cs
@@ -134,7 +134,7 @@ public static class Program
var company = x.LastOrDefault()?.Split('(').FirstOrDefault()?.Trim() ?? "";
var sn = x.LastOrDefault()?.Split('(').LastOrDefault()?.Trim("() ".ToCharArray()) ?? "";
- var created = i.Created.ToUtcDateTime().ToString("dd.MM.yyyy HH:mm");
+ var created = i.Created.DateTimeFromUnixTime().ToString("dd.MM.yyyy HH:mm");
var line = new[]
{
diff --git a/csharp/App/SaliMax/SaliMax.csproj b/csharp/App/SaliMax/SaliMax.csproj
index 06875a6f8..e350ddf37 100644
--- a/csharp/App/SaliMax/SaliMax.csproj
+++ b/csharp/App/SaliMax/SaliMax.csproj
@@ -18,7 +18,6 @@
-
diff --git a/csharp/App/SaliMax/src/Logfile.cs b/csharp/App/SaliMax/src/Logfile.cs
index b3fe2510e..701e66181 100644
--- a/csharp/App/SaliMax/src/Logfile.cs
+++ b/csharp/App/SaliMax/src/Logfile.cs
@@ -1,4 +1,4 @@
-using InnovEnergy.Lib.Time.Unix;
+using InnovEnergy.Lib.Utils;
using Microsoft.Extensions.Logging;
namespace InnovEnergy.App.SaliMax;
@@ -56,7 +56,7 @@ public class CustomLogger : ILogger
File.Delete(logFiles.First());
// Rename the current log file with a timestamp
- var logFileBackupPath = Path.Combine(logFileDir, $"{logFileBaseName}_{UnixTime.Now}{logFileExt}");
+ var logFileBackupPath = Path.Combine(logFileDir, $"{logFileBaseName}_{DateTime.Now.ToUnixTime()}{logFileExt}");
File.Move(_LogFilePath, logFileBackupPath);
}
}
diff --git a/csharp/App/SaliMax/src/Program.cs b/csharp/App/SaliMax/src/Program.cs
index 5e2ec5581..78c2eeb6d 100644
--- a/csharp/App/SaliMax/src/Program.cs
+++ b/csharp/App/SaliMax/src/Program.cs
@@ -16,18 +16,18 @@ using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes;
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc;
using InnovEnergy.Lib.Devices.Trumpf.TruConvertDc.Control;
using InnovEnergy.Lib.Protocols.Modbus.Channels;
-using InnovEnergy.Lib.Time.Unix;
using InnovEnergy.Lib.Units;
using InnovEnergy.Lib.Utils;
using static InnovEnergy.Lib.Devices.Trumpf.SystemControl.DataTypes.SystemConfig;
+
#pragma warning disable IL2026
namespace InnovEnergy.App.SaliMax;
internal static class Program
{
- private static readonly UnixTimeSpan UpdateInterval = UnixTimeSpan.FromSeconds(2);
+ private static readonly TimeSpan UpdateInterval = TimeSpan.FromSeconds(2);
private static readonly IReadOnlyList BatteryNodes;
@@ -148,9 +148,9 @@ internal static class Program
while (true)
{
await Observable
- .Interval(UpdateInterval.ToTimeSpan())
+ .Interval(UpdateInterval)
.Select(_ => RunIteration())
- .SelectMany(r => UploadCsv(r, UnixTime.Now.RoundTo(UpdateInterval)))
+ .SelectMany(r => UploadCsv(r, DateTime.UtcNow))
.SelectError()
.ToTask();
}
@@ -185,7 +185,7 @@ internal static class Program
record.ControlConstants();
record.ControlSystemState();
- $"{UnixTime.Now} : {record.StateMachine.State}: {record.StateMachine.Message}".WriteLine().LogInfo();
+ $"{record.StateMachine.State}: {record.StateMachine.Message}".LogInfo();
var essControl = record.ControlEss().WriteLine().LogInfo();
@@ -313,20 +313,17 @@ internal static class Program
sc.ResetAlarmsAndWarnings = true;
}
- private static async Task UploadCsv(StatusRecord status, UnixTime timeStamp)
+ private static async Task UploadCsv(StatusRecord status, DateTime timeStamp)
{
var s3Config = status.Config.S3;
- var csv = status.ToCsv().LogInfo();
if (s3Config is null)
return false;
+ var csv = status.ToCsv();
var s3Path = timeStamp + ".csv";
var request = s3Config.CreatePutRequest(s3Path);
var response = await request.PutAsync(new StringContent(csv));
- // This is temporary for Wittman
- //await File.WriteAllTextAsync("/var/www/html/status.csv", csv.SplitLines().Where(l => !l.Contains("Secret")).JoinLines());
-
if (response.StatusCode != 200)
{
Console.WriteLine("ERROR: PUT");
diff --git a/csharp/App/SaliMax/src/SystemConfig/AcDcConfig.cs b/csharp/App/SaliMax/src/SystemConfig/AcDcConfig.cs
index c8eb05a8a..ac4a274aa 100644
--- a/csharp/App/SaliMax/src/SystemConfig/AcDcConfig.cs
+++ b/csharp/App/SaliMax/src/SystemConfig/AcDcConfig.cs
@@ -2,7 +2,7 @@ namespace InnovEnergy.App.SaliMax.SystemConfig;
public class AcDcConfig
{
- public required Double MaxDcLinkVoltage { get; set; }
- public required Double MinDcLinkVoltage { get; set; }
- public required Double ReferenceDcLinkVoltage { get; set; }
+ public required Double MaxDcLinkVoltage { get; init; }
+ public required Double MinDcLinkVoltage { get; init; }
+ public required Double ReferenceDcLinkVoltage { get; init; }
}
\ No newline at end of file
diff --git a/csharp/App/SaliMax/src/SystemConfig/Config.cs b/csharp/App/SaliMax/src/SystemConfig/Config.cs
index 452935375..fcbd5f869 100644
--- a/csharp/App/SaliMax/src/SystemConfig/Config.cs
+++ b/csharp/App/SaliMax/src/SystemConfig/Config.cs
@@ -1,5 +1,4 @@
using System.Text.Json;
-using InnovEnergy.Lib.Time.Unix;
using InnovEnergy.Lib.Utils;
using static System.Text.Json.JsonSerializer;
@@ -27,7 +26,6 @@ public class Config //TODO: let IE choose from config files (Json) and connect t
public required Double MaxBatteryDischargingCurrent { get; set; }
public required Double MaxDcPower { get; set; }
-
public required Double MaxChargeBatteryVoltage { get; set; }
public required Double MinDischargeBatteryVoltage { get; set; }
@@ -49,16 +47,16 @@ public class Config //TODO: let IE choose from config files (Json) and connect t
{
AcDc = new ()
{
- MinDcLinkVoltage = 690,
- ReferenceDcLinkVoltage = 750,
- MaxDcLinkVoltage = 810,
+ MinDcLinkVoltage = 690,
+ ReferenceDcLinkVoltage = 750,
+ MaxDcLinkVoltage = 810,
},
DcDc = new ()
{
- UpperDcLinkVoltage = 50,
- LowerDcLinkVoltage = 50,
- ReferenceDcLinkVoltage = 750,
+ UpperDcLinkVoltage = 50,
+ LowerDcLinkVoltage = 50,
+ ReferenceDcLinkVoltage = 750,
},
},
@@ -66,25 +64,26 @@ public class Config //TODO: let IE choose from config files (Json) and connect t
{
AcDc = new ()
{
- MinDcLinkVoltage = 720,
- ReferenceDcLinkVoltage = 750,
- MaxDcLinkVoltage = 810,
+ MinDcLinkVoltage = 720,
+ ReferenceDcLinkVoltage = 750,
+ MaxDcLinkVoltage = 810,
},
DcDc = new ()
{
- UpperDcLinkVoltage = 50,
- LowerDcLinkVoltage = 50,
- ReferenceDcLinkVoltage = 750,
+ UpperDcLinkVoltage = 50,
+ LowerDcLinkVoltage = 50,
+ ReferenceDcLinkVoltage = 750,
},
},
- MaxBatteryChargingCurrent = 210,
- MaxBatteryDischargingCurrent = 210,
- MaxDcPower = 10000,
+ MaxBatteryChargingCurrent = 210,
+ MaxBatteryDischargingCurrent = 210,
+ MaxDcPower = 10000,
- MaxChargeBatteryVoltage = 57,
- MinDischargeBatteryVoltage = 0,
+ MaxChargeBatteryVoltage = 57,
+ MinDischargeBatteryVoltage = 0,
+
Devices = new ()
{
TruConvertAcIp = new() { Host = "localhost", Port = 5001},
@@ -111,16 +110,16 @@ public class Config //TODO: let IE choose from config files (Json) and connect t
{
AcDc = new ()
{
- MinDcLinkVoltage = 690,
- ReferenceDcLinkVoltage = 750,
- MaxDcLinkVoltage = 810,
+ MinDcLinkVoltage = 690,
+ ReferenceDcLinkVoltage = 750,
+ MaxDcLinkVoltage = 810,
},
DcDc = new ()
{
- UpperDcLinkVoltage = 50,
- LowerDcLinkVoltage = 50,
- ReferenceDcLinkVoltage = 750,
+ UpperDcLinkVoltage = 50,
+ LowerDcLinkVoltage = 50,
+ ReferenceDcLinkVoltage = 750,
},
},
@@ -128,26 +127,26 @@ public class Config //TODO: let IE choose from config files (Json) and connect t
{
AcDc = new ()
{
- MinDcLinkVoltage = 720,
- ReferenceDcLinkVoltage = 750,
- MaxDcLinkVoltage = 780,
+ MinDcLinkVoltage = 720,
+ ReferenceDcLinkVoltage = 750,
+ MaxDcLinkVoltage = 780,
},
DcDc = new ()
{
- UpperDcLinkVoltage = 20,
- LowerDcLinkVoltage = 20,
- ReferenceDcLinkVoltage = 750,
+ UpperDcLinkVoltage = 20,
+ LowerDcLinkVoltage = 20,
+ ReferenceDcLinkVoltage = 750,
},
},
- MaxBatteryChargingCurrent = 210,
- MaxBatteryDischargingCurrent = 210,
- MaxDcPower = 10000,
+ MaxBatteryChargingCurrent = 210,
+ MaxBatteryDischargingCurrent = 210,
+ MaxDcPower = 10000,
- MaxChargeBatteryVoltage = 57,
- MinDischargeBatteryVoltage = 0,
+ MaxChargeBatteryVoltage = 57,
+ MinDischargeBatteryVoltage = 0,
S3 = new()
{
Bucket = "saliomameiringen",
diff --git a/csharp/App/SaliMax/src/SystemConfig/DcDcConfig.cs b/csharp/App/SaliMax/src/SystemConfig/DcDcConfig.cs
index eb32158d4..82fb79df3 100644
--- a/csharp/App/SaliMax/src/SystemConfig/DcDcConfig.cs
+++ b/csharp/App/SaliMax/src/SystemConfig/DcDcConfig.cs
@@ -2,7 +2,7 @@ namespace InnovEnergy.App.SaliMax.SystemConfig;
public class DcDcConfig
{
- public required Double LowerDcLinkVoltage { get; set; }
- public required Double ReferenceDcLinkVoltage { get; set; }
- public required Double UpperDcLinkVoltage { get; set; }
+ public required Double LowerDcLinkVoltage { get; init; }
+ public required Double ReferenceDcLinkVoltage { get; init; }
+ public required Double UpperDcLinkVoltage { get; init; }
}
\ No newline at end of file
diff --git a/csharp/App/SaliMax/src/SystemConfig/DevicesConfig.cs b/csharp/App/SaliMax/src/SystemConfig/DevicesConfig.cs
index 2b61fb2e8..4ae202e32 100644
--- a/csharp/App/SaliMax/src/SystemConfig/DevicesConfig.cs
+++ b/csharp/App/SaliMax/src/SystemConfig/DevicesConfig.cs
@@ -2,6 +2,6 @@ namespace InnovEnergy.App.SaliMax.SystemConfig;
public class DevicesConfig
{
- public required AcDcConfig AcDc { get; set; }
- public required DcDcConfig DcDc { get; set; }
+ public required AcDcConfig AcDc { get; init; }
+ public required DcDcConfig DcDc { get; init; }
}
\ No newline at end of file
diff --git a/csharp/App/SaliMax/src/Topology.cs b/csharp/App/SaliMax/src/Topology.cs
index 5ff0660ff..ce1b957f2 100644
--- a/csharp/App/SaliMax/src/Topology.cs
+++ b/csharp/App/SaliMax/src/Topology.cs
@@ -285,7 +285,7 @@ public static class Topology
return Switch.Open("K3");
}
- private static TextBlock CreateDcDcColumn(this StatusRecord status, ActivePower? l)
+ private static TextBlock CreateDcDcColumn(this StatusRecord status, ActivePower? p)
{
var dc48Voltage = status.DcDc.Dc.Battery.Voltage.ToDisplayString();
@@ -293,7 +293,7 @@ public static class Topology
.AlignLeft(dc48Voltage)
.TitleBox("DC/DC");
- var busFlow = Flow.Horizontal(l);
+ var busFlow = Flow.Horizontal(p);
return TextBlock.AlignCenterVertical(busBox, busFlow);
}
@@ -371,6 +371,7 @@ public static class Topology
return batteryAvgBox; // TODO: individualBatteries hidden atm
+ #pragma warning disable CS0162
var batteryBoxes = bat
.Devices
.Select(CreateBatteryBox)
@@ -386,6 +387,8 @@ public static class Topology
batteryAvgBox ,
individualBatteries
);
+
+ #pragma warning enable CS0162
}
private static TextBlock CreateAveragedBatteryBox(Battery48TlRecords? bat)
diff --git a/csharp/Lib/Time/Time.csproj b/csharp/Lib/Time/Time.csproj
index ee1aa459a..23e7c5ce3 100644
--- a/csharp/Lib/Time/Time.csproj
+++ b/csharp/Lib/Time/Time.csproj
@@ -8,5 +8,9 @@
InnovEnergy.Lib.Time
+
+
+
+
diff --git a/csharp/Lib/Time/Unix/UnixTime.Compare.cs b/csharp/Lib/Time/Unix/UnixTime.Compare.cs
index 044ef1a32..483309f81 100644
--- a/csharp/Lib/Time/Unix/UnixTime.Compare.cs
+++ b/csharp/Lib/Time/Unix/UnixTime.Compare.cs
@@ -1,7 +1,7 @@
-namespace InnovEnergy.Lib.Time.Unix;
-
-public readonly partial struct UnixTime : IComparable, IEquatable
-{
- Int32 IComparable.CompareTo(UnixTime other) => Ticks.CompareTo(other.Ticks);
- Boolean IEquatable.Equals(UnixTime other) => Ticks == other.Ticks;
-}
\ No newline at end of file
+// namespace InnovEnergy.Lib.Time.Unix;
+//
+// public readonly partial struct UnixTime : IComparable, IEquatable
+// {
+// Int32 IComparable.CompareTo(UnixTime other) => Ticks.CompareTo(other.Ticks);
+// Boolean IEquatable.Equals(UnixTime other) => Ticks == other.Ticks;
+// }
\ No newline at end of file
diff --git a/csharp/Lib/Time/Unix/UnixTime.Constructors.cs b/csharp/Lib/Time/Unix/UnixTime.Constructors.cs
index 5d963e488..cb49cc929 100644
--- a/csharp/Lib/Time/Unix/UnixTime.Constructors.cs
+++ b/csharp/Lib/Time/Unix/UnixTime.Constructors.cs
@@ -1,20 +1,19 @@
-namespace InnovEnergy.Lib.Time.Unix;
-
-public readonly partial struct UnixTime
-{
- private UnixTime(UInt32 ticks) => Ticks = ticks;
-
- public static UnixTime FromTicks(UInt32 ticks) => new UnixTime(ticks);
- public static UnixTime FromTicks(Int32 ticks) => new UnixTime((UInt32) ticks);
-
- public static UnixTime FromUtcDateTime(DateTime dateTime)
- {
- var timeSinceEpoch = dateTime - DateTime.UnixEpoch;
- var ticks = (UInt32) timeSinceEpoch.TotalSeconds;
-
- return new UnixTime(ticks);
- }
-
- public static UnixTime Epoch => new UnixTime(0);
- public static UnixTime Now => FromUtcDateTime(DateTime.UtcNow);
-}
\ No newline at end of file
+// namespace InnovEnergy.Lib.Time.Unix;
+//
+// public readonly partial struct UnixTime
+// {
+// public static UnixTime FromTicks(Int32 ticks) => new UnixTime { Ticks = ticks };
+//
+// public static UnixTime FromUtcDateTime(DateTime dateTime)
+// {
+// var timeSinceEpoch = dateTime - DateTime.UnixEpoch;
+// var ticks = (Int32) timeSinceEpoch.TotalSeconds;
+//
+// return new UnixTime{ Ticks = ticks};
+// }
+//
+// public static UnixTime Epoch => new UnixTime { Ticks = 0 };
+// public static UnixTime Now => FromUtcDateTime(DateTime.UtcNow);
+//
+//
+// }
\ No newline at end of file
diff --git a/csharp/Lib/Time/Unix/UnixTime.Converters.cs b/csharp/Lib/Time/Unix/UnixTime.Converters.cs
index 7c28860a9..922661020 100644
--- a/csharp/Lib/Time/Unix/UnixTime.Converters.cs
+++ b/csharp/Lib/Time/Unix/UnixTime.Converters.cs
@@ -1,9 +1,9 @@
-namespace InnovEnergy.Lib.Time.Unix;
-
-public readonly partial struct UnixTime
-{
- public DateTime ToUtcDateTime() => DateTime.UnixEpoch + TimeSpan.FromSeconds(Ticks);
-
- public static implicit operator DateTime(UnixTime unixTimeSpan) => unixTimeSpan.ToUtcDateTime();
- public static implicit operator UnixTime(DateTime dateTime) => FromUtcDateTime(dateTime);
-}
\ No newline at end of file
+// namespace InnovEnergy.Lib.Time.Unix;
+//
+// public readonly partial struct UnixTime
+// {
+// public DateTime ToUtcDateTime() => DateTime.UnixEpoch + TimeSpan.FromSeconds(Ticks);
+//
+// public static implicit operator DateTime(UnixTime unixTimeSpan) => unixTimeSpan.ToUtcDateTime();
+// public static implicit operator UnixTime(DateTime dateTime) => FromUtcDateTime(dateTime);
+// }
\ No newline at end of file
diff --git a/csharp/Lib/Time/Unix/UnixTime.Operators.cs b/csharp/Lib/Time/Unix/UnixTime.Operators.cs
index 7aeb71b69..0ca12ad1b 100644
--- a/csharp/Lib/Time/Unix/UnixTime.Operators.cs
+++ b/csharp/Lib/Time/Unix/UnixTime.Operators.cs
@@ -1,20 +1,27 @@
-namespace InnovEnergy.Lib.Time.Unix;
-
-public readonly partial struct UnixTime
-{
- public static UnixTime operator -(UnixTime a, UnixTimeSpan b) => FromTicks(a.Ticks - b.Ticks);
- public static UnixTime operator +(UnixTime a, UnixTimeSpan b) => FromTicks(a.Ticks + b.Ticks);
- public static UnixTime operator +(UnixTimeSpan a, UnixTime b) => FromTicks(a.Ticks + b.Ticks);
-
- public static UInt32 operator /(UnixTime a, UnixTimeSpan b) => a.Ticks / b.Ticks;
- public static UInt32 operator %(UnixTime a, UnixTimeSpan b) => a.Ticks % b.Ticks;
-
- public static Boolean operator < (UnixTime l, UnixTime r) => l.Ticks < r.Ticks;
- public static Boolean operator > (UnixTime l, UnixTime r) => l.Ticks > r.Ticks;
- public static Boolean operator <= (UnixTime l, UnixTime r) => l.Ticks <= r.Ticks;
- public static Boolean operator >= (UnixTime l, UnixTime r) => l.Ticks >= r.Ticks;
- public static Boolean operator == (UnixTime l, UnixTime r) => l.Ticks == r.Ticks;
- public static Boolean operator != (UnixTime l, UnixTime r) => l.Ticks != r.Ticks;
-
- public static UnixTimeSpan operator -(UnixTime a, UnixTime b) => UnixTimeSpan.FromTicks(a.Ticks - b.Ticks);
-}
\ No newline at end of file
+// using InnovEnergy.Lib.Utils;
+//
+// namespace InnovEnergy.Lib.Time.Unix;
+//
+// public readonly partial struct UnixTime
+// {
+// public static UnixTime operator -(UnixTime a, TimeSpan b) => FromTicks(a.Ticks - GetUnixTicks(b));
+// public static UnixTime operator +(UnixTime a, TimeSpan b) => FromTicks(a.Ticks + GetUnixTicks(b));
+// public static UnixTime operator +(TimeSpan a, UnixTime b) => FromTicks(GetUnixTicks(a) + b.Ticks);
+//
+// public static Double operator /(UnixTime a, TimeSpan b) => a.Ticks.ConvertTo() / b.Ticks;
+// public static Int32 operator %(UnixTime a, TimeSpan b) => a.Ticks % GetUnixTicks(b);
+//
+// public static Boolean operator < (UnixTime l, UnixTime r) => l.Ticks < r.Ticks;
+// public static Boolean operator > (UnixTime l, UnixTime r) => l.Ticks > r.Ticks;
+// public static Boolean operator <= (UnixTime l, UnixTime r) => l.Ticks <= r.Ticks;
+// public static Boolean operator >= (UnixTime l, UnixTime r) => l.Ticks >= r.Ticks;
+// public static Boolean operator == (UnixTime l, UnixTime r) => l.Ticks == r.Ticks;
+// public static Boolean operator != (UnixTime l, UnixTime r) => l.Ticks != r.Ticks;
+//
+// public static TimeSpan operator -(UnixTime a, UnixTime b) => TimeSpan.FromSeconds(a.Ticks - b.Ticks);
+//
+// private static Int32 GetUnixTicks(TimeSpan ts)
+// {
+// return (Int32) (ts.Ticks / 10000000L);
+// }
+// }
\ No newline at end of file
diff --git a/csharp/Lib/Time/Unix/UnixTime.Overrides.cs b/csharp/Lib/Time/Unix/UnixTime.Overrides.cs
index c2ba77a5e..9cc9f9464 100644
--- a/csharp/Lib/Time/Unix/UnixTime.Overrides.cs
+++ b/csharp/Lib/Time/Unix/UnixTime.Overrides.cs
@@ -1,8 +1,8 @@
-namespace InnovEnergy.Lib.Time.Unix;
-
-public readonly partial struct UnixTime
-{
- public override Boolean Equals(Object? obj) => obj is UnixTime other && Ticks == other.Ticks;
- public override Int32 GetHashCode() => (Int32) (Ticks & 0x7F_FF_FF_FF);
- public override String ToString() => Ticks.ToString();
-}
\ No newline at end of file
+// namespace InnovEnergy.Lib.Time.Unix;
+//
+// public readonly partial struct UnixTime
+// {
+// public override Boolean Equals(Object? obj) => obj is UnixTime other && Ticks == other.Ticks;
+// public override Int32 GetHashCode() => (Int32) (Ticks & 0x7F_FF_FF_FF);
+// public override String ToString() => Ticks.ToString();
+// }
\ No newline at end of file
diff --git a/csharp/Lib/Time/Unix/UnixTime.cs b/csharp/Lib/Time/Unix/UnixTime.cs
index b370ad764..65b05907c 100644
--- a/csharp/Lib/Time/Unix/UnixTime.cs
+++ b/csharp/Lib/Time/Unix/UnixTime.cs
@@ -1,14 +1,6 @@
-
-
-// ReSharper disable ArrangeStaticMemberQualifier
-
-namespace InnovEnergy.Lib.Time.Unix;
-
-public readonly partial struct UnixTime
-{
- // IMPORTANT: init is necessary for JSON deserializer
- // ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global
- public UInt32 Ticks { get; init; }
-
- public UnixTime RoundTo(UnixTimeSpan span) => Epoch + this / span * span;
-}
\ No newline at end of file
+// namespace InnovEnergy.Lib.Time.Unix;
+//
+// public readonly partial struct UnixTime
+// {
+// public required Int32 Ticks { get; init; }
+// }
\ No newline at end of file
diff --git a/csharp/Lib/Time/Unix/UnixTimeSpan.Compare.cs b/csharp/Lib/Time/Unix/UnixTimeSpan.Compare.cs
deleted file mode 100644
index 72f59f82e..000000000
--- a/csharp/Lib/Time/Unix/UnixTimeSpan.Compare.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace InnovEnergy.Lib.Time.Unix;
-
-public readonly partial struct UnixTimeSpan : IComparable, IEquatable
-{
- Int32 IComparable.CompareTo(UnixTimeSpan other) => Ticks.CompareTo(other.Ticks);
- Boolean IEquatable.Equals(UnixTimeSpan other) => Ticks == other.Ticks;
-}
\ No newline at end of file
diff --git a/csharp/Lib/Time/Unix/UnixTimeSpan.Constructors.cs b/csharp/Lib/Time/Unix/UnixTimeSpan.Constructors.cs
deleted file mode 100644
index c1fa4f877..000000000
--- a/csharp/Lib/Time/Unix/UnixTimeSpan.Constructors.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-namespace InnovEnergy.Lib.Time.Unix;
-
-public readonly partial struct UnixTimeSpan
-{
- private UnixTimeSpan(UInt32 ticks) => Ticks = ticks;
-
- public static UnixTimeSpan FromTicks(UInt32 ticks) => new UnixTimeSpan(ticks);
-
- public static UnixTimeSpan FromTimeSpan(TimeSpan timeSpan)
- {
- var ticks = (UInt32) timeSpan.TotalSeconds;
- return FromTicks(ticks);
- }
-
- public static UnixTimeSpan FromSeconds(UInt32 s) => FromTicks (s);
- public static UnixTimeSpan FromMinutes(UInt32 m) => FromSeconds(m * 60);
- public static UnixTimeSpan FromHours (UInt32 h) => FromMinutes(h * 60);
- public static UnixTimeSpan FromDays (UInt32 d) => FromHours (d * 24);
- public static UnixTimeSpan FromWeeks (UInt32 w) => FromDays (w * 7);
-
- public static UnixTimeSpan FromSeconds(Int32 s) => FromSeconds((UInt32) s);
- public static UnixTimeSpan FromMinutes(Int32 m) => FromMinutes((UInt32) m);
- public static UnixTimeSpan FromHours (Int32 h) => FromHours ((UInt32) h);
- public static UnixTimeSpan FromDays (Int32 d) => FromDays ((UInt32) d);
- public static UnixTimeSpan FromWeeks (Int32 w) => FromWeeks ((UInt32) w);
-}
\ No newline at end of file
diff --git a/csharp/Lib/Time/Unix/UnixTimeSpan.Converters.cs b/csharp/Lib/Time/Unix/UnixTimeSpan.Converters.cs
deleted file mode 100644
index b2bce89d4..000000000
--- a/csharp/Lib/Time/Unix/UnixTimeSpan.Converters.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace InnovEnergy.Lib.Time.Unix;
-
-public readonly partial struct UnixTimeSpan
-{
- public TimeSpan ToTimeSpan() => TimeSpan.FromSeconds(Ticks);
-
- public static implicit operator TimeSpan(UnixTimeSpan unixTimeSpan) => unixTimeSpan.ToTimeSpan();
- public static implicit operator UnixTimeSpan(TimeSpan timeSpan) => FromTimeSpan(timeSpan);
-}
\ No newline at end of file
diff --git a/csharp/Lib/Time/Unix/UnixTimeSpan.Operators.cs b/csharp/Lib/Time/Unix/UnixTimeSpan.Operators.cs
deleted file mode 100644
index e59d3dfba..000000000
--- a/csharp/Lib/Time/Unix/UnixTimeSpan.Operators.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-namespace InnovEnergy.Lib.Time.Unix;
-
-public readonly partial struct UnixTimeSpan
-{
- public static Boolean operator < (UnixTimeSpan l, UnixTimeSpan r) => l.Ticks < r.Ticks;
- public static Boolean operator > (UnixTimeSpan l, UnixTimeSpan r) => l.Ticks > r.Ticks;
- public static Boolean operator <= (UnixTimeSpan l, UnixTimeSpan r) => l.Ticks <= r.Ticks;
- public static Boolean operator >= (UnixTimeSpan l, UnixTimeSpan r) => l.Ticks >= r.Ticks;
- public static Boolean operator == (UnixTimeSpan l, UnixTimeSpan r) => l.Ticks == r.Ticks;
- public static Boolean operator != (UnixTimeSpan l, UnixTimeSpan r) => l.Ticks != r.Ticks;
-
- public static UnixTimeSpan operator +(UnixTimeSpan a, UnixTimeSpan b) => new UnixTimeSpan(a.Ticks + b.Ticks);
- public static UnixTimeSpan operator -(UnixTimeSpan a, UnixTimeSpan b) => new UnixTimeSpan(a.Ticks - b.Ticks);
-
- public static UnixTimeSpan operator *(UnixTimeSpan a, UInt32 b) => new UnixTimeSpan(a.Ticks * b);
- public static UnixTimeSpan operator *(UnixTimeSpan a, Int32 b) => new UnixTimeSpan(a.Ticks * (UInt32) b);
-
- public static UnixTimeSpan operator *(UInt32 a, UnixTimeSpan b) => new UnixTimeSpan(a * b.Ticks);
- public static UnixTimeSpan operator *(Int32 a, UnixTimeSpan b) => new UnixTimeSpan((UInt32) a * b.Ticks);
-
- public static UnixTimeSpan operator /(UnixTimeSpan a, UInt32 b) => new UnixTimeSpan(a.Ticks / b);
- public static UnixTimeSpan operator /(UnixTimeSpan a, Int32 b) => new UnixTimeSpan(a.Ticks / (UInt32)b);
- public static UInt32 operator /(UnixTimeSpan a, UnixTimeSpan b) => a.Ticks / b.Ticks;
-
- public static UnixTimeSpan operator %(UnixTimeSpan a, UInt32 b) => new UnixTimeSpan(a.Ticks % b);
- public static UnixTimeSpan operator %(UnixTimeSpan a, Int32 b) => new UnixTimeSpan(a.Ticks % (UInt32)b);
- public static UInt32 operator %(UnixTimeSpan a, UnixTimeSpan b) => a.Ticks % b.Ticks;
-
-}
\ No newline at end of file
diff --git a/csharp/Lib/Time/Unix/UnixTimeSpan.Overrides.cs b/csharp/Lib/Time/Unix/UnixTimeSpan.Overrides.cs
deleted file mode 100644
index 9552fbbe3..000000000
--- a/csharp/Lib/Time/Unix/UnixTimeSpan.Overrides.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using System.Text;
-
-namespace InnovEnergy.Lib.Time.Unix;
-
-public readonly partial struct UnixTimeSpan
-{
- public override String ToString()
- {
- var sb = new StringBuilder();
- var dt = ToTimeSpan();
-
- var weeks = dt.Days / 7;
- var days = dt.Days % 7;
-
- if (weeks > 0)
- {
- sb.Append(weeks);
- sb.Append("w ");
- }
- if (days > 0)
- {
- sb.Append(days);
- sb.Append("d ");
- }
- if (dt.Hours > 0)
- {
- sb.Append(dt.Hours);
- sb.Append("h ");
- }
- if (dt.Minutes > 0)
- {
- sb.Append(dt.Minutes);
- sb.Append("m ");
- }
- if (dt.Seconds > 0)
- {
- sb.Append(dt.Seconds);
- sb.Append("s");
- }
-
- return sb.ToString().Trim();
- }
-
- public override Boolean Equals(Object? obj) => obj is UnixTime other && Ticks == other.Ticks;
-
- public override Int32 GetHashCode() => (Int32) (Ticks & 0x7F_FF_FF_FF);
-
- public static UnixTimeSpan Forever { get; } = FromTicks(UInt32.MaxValue) / 1.Weeks() * 1.Weeks();
-
-}
\ No newline at end of file
diff --git a/csharp/Lib/Time/Unix/UnixTimeSpan.cs b/csharp/Lib/Time/Unix/UnixTimeSpan.cs
deleted file mode 100644
index 4dd19d675..000000000
--- a/csharp/Lib/Time/Unix/UnixTimeSpan.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace InnovEnergy.Lib.Time.Unix;
-
-public readonly partial struct UnixTimeSpan
-{
- public UInt32 Ticks { get; }
-
-
-}
\ No newline at end of file
diff --git a/csharp/Lib/Time/Unix/UnixTimeSpanExtensions.cs b/csharp/Lib/Time/Unix/UnixTimeSpanExtensions.cs
deleted file mode 100644
index b5bd2b53f..000000000
--- a/csharp/Lib/Time/Unix/UnixTimeSpanExtensions.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace InnovEnergy.Lib.Time.Unix;
-
-public static class UnixTimeSpanExtensions
-{
- public static UnixTimeSpan Seconds(this Int32 s) => UnixTimeSpan.FromSeconds(s);
- public static UnixTimeSpan Minutes(this Int32 m) => UnixTimeSpan.FromMinutes(m);
- public static UnixTimeSpan Hours (this Int32 h) => UnixTimeSpan.FromHours (h);
- public static UnixTimeSpan Days (this Int32 d) => UnixTimeSpan.FromDays (d);
- public static UnixTimeSpan Weeks (this Int32 w) => UnixTimeSpan.FromWeeks (w);
-
- public static UnixTimeSpan Seconds(this UInt32 s) => UnixTimeSpan.FromSeconds(s);
- public static UnixTimeSpan Minutes(this UInt32 m) => UnixTimeSpan.FromMinutes(m);
- public static UnixTimeSpan Hours (this UInt32 h) => UnixTimeSpan.FromHours (h);
- public static UnixTimeSpan Days (this UInt32 d) => UnixTimeSpan.FromDays (d);
- public static UnixTimeSpan Weeks (this UInt32 w) => UnixTimeSpan.FromWeeks (w);
-}
\ No newline at end of file
diff --git a/csharp/Lib/Units/Units.csproj b/csharp/Lib/Units/Units.csproj
index 3647bbf78..94df36c09 100644
--- a/csharp/Lib/Units/Units.csproj
+++ b/csharp/Lib/Units/Units.csproj
@@ -8,7 +8,6 @@
-
diff --git a/csharp/Lib/Utils/DateTimeUtils.cs b/csharp/Lib/Utils/DateTimeUtils.cs
new file mode 100644
index 000000000..0cb872d33
--- /dev/null
+++ b/csharp/Lib/Utils/DateTimeUtils.cs
@@ -0,0 +1,38 @@
+namespace InnovEnergy.Lib.Utils;
+
+public static class DateTimeUtils
+{
+ public static DateTime Epoch { get; } = new DateTime
+ (
+ year: 1970,
+ month: 1,
+ day: 1,
+ hour: 0,
+ minute: 0,
+ second: 0,
+ DateTimeKind.Utc
+ );
+
+ public static Int64 ToUnixTime(this DateTime dateTime)
+ {
+ var timeSinceEpoch = dateTime.ToUniversalTime() - Epoch;
+ return timeSinceEpoch.Ticks / TimeSpan.TicksPerSecond;
+ }
+
+ public static DateTime DateTimeFromUnixTime(this IConvertible unixTime)
+ {
+ var epochTicks = Epoch.Ticks + unixTime.ConvertTo() * TimeSpan.TicksPerSecond;
+
+ return new DateTime(epochTicks.ConvertTo(), DateTimeKind.Utc);
+ }
+
+ public static DateTime Round(this DateTime date, TimeSpan interval)
+ {
+ var i = interval.Ticks;
+ var t = date.Ticks;
+
+ var intervalTicks = (t + i / 2 + 1) / i * i;
+
+ return new DateTime(intervalTicks, date.Kind);
+ }
+}
\ No newline at end of file