Minimal example dotnet fiddle available here.
I have to wrap a 3rd-party API that stores dates as uint
seconds post-epoch, but want to present them to consumers of my API as DateTime values. The mechanics of get
/init
the DTO record property is tripping me up. If I do as below, then I get a "can't implicitly convert from uint to DateTime" error:
public static void Main()
{
var foobar = new FoobarModel() { created = (uint)1725747561 };
}
public static class TimeConverter
{
public static DateTime ConvertFromUnixTimestamp(uint timestamp) =>
DateTime.UnixEpoch.AddSeconds((double)timestamp);
public static uint? ConvertToUnixTimestamp(DateTime date) =>
(uint)Math.Floor((date!.ToUniversalTime() - DateTime.UnixEpoch).TotalSeconds);
}
public record FoobarModel
{
private uint? _created;
public DateTime? created
{
get => created != null
? TimeConverter.ConvertFromUnixTimestamp(_created!.Value)
: null;
init => _created = value != null
? TimeConverter.ConvertToUnixTimestamp(value!.Value)
: null;
}
public FoobarModel() { }
}
I have to be able to instantiate a FoobarModel
with uint
data, but clearly my FoobarModel.created.init
method isn't able to accept uint
. How do I make this situation work?
(Please forgive the FoobarModel
property capitalization conventions, they match the 3rd party API. Also, eventually I would like to deserialize a JSON string with this property, so the fiddle has a little JSON code available.)
Consider keeping the formatted DateTime as a separate non-serialized value if you want to dual-purpose the model:
public static class TimeConverter
{
public static DateTime ConvertFromUnixTimestamp(uint timestamp) =>
DateTime.UnixEpoch.AddSeconds((double)timestamp);
public static DateTime? ConvertFromUnixTimestamp(uint? timestamp) =>
timestamp == null ? (DateTime?) null : ConvertFromUnixTimestamp(timestamp!);
public static uint ConvertToUnixTimestamp(DateTime date) =>
(uint)Math.Floor((date.ToUniversalTime() - DateTime.UnixEpoch).TotalSeconds);
}
public uint? created { get; init; }
[JsonIgnore]
public DateTime? createdDateTime
{
get => TimeConverter.ConvertFromUnixTimestamp(created)
}
I also just moved the #nullable handling into the converter.
The serialization/deserialization as well as any initialization continues to use the uint epoch values. Where you want to display it as a date-time use the createdDateTime property.