Specifying UTC time or current time offset What do you think about this helper class to specify UTC time? It should also support an easy way to capture current time offsets. Let's say we expose it in API like this:

interface IApi
{
    void Start(Utc at);
}


Now it should go as:

api.Start(new DateTime(2021, 01, 01)) // starts on 2021-01-01 UTC
api.Start(new TimeSpan(1, 0, 0)) // starts in one hour
api.Start(2000) // starts in 2 seconds


Library code is:

struct Utc
{
    public static Utc Now =&gt; 0;

    public static implicit operator Utc(DateTime value) =&gt; new Utc(value);
    public static implicit operator Utc(DateTimeOffset value) =&gt; value.UtcDateTime;
    public static implicit operator Utc(TimeSpan value) =&gt; DateTime.UtcNow + value;
    public static implicit operator Utc(int value) =&gt; TimeSpan.FromMilliseconds(value);

    public static implicit operator DateTime(Utc utc) =&gt; utc.Time;
    public static implicit operator DateTimeOffset(Utc utc) =&gt; 
        new DateTimeOffset(utc, TimeSpan.Zero);

    Utc(DateTime time) =&gt; Time = DateTime.SpecifyKind(time, DateTimeKind.Utc);
    DateTime Time { get; }
}
In terms of conventions there is nothing to poke at there.

Where I find that approach lacking is that it tries to merge two different concepts. Namely a point in time an a time difference (or offset). Another non .NET example that I can think of is swift which has Date and TimeInterval. TimeInterval being an alias for a double which represents the offset in seconds.

Most libraries (.NET included) have distinct types to separate these two concepts.

To illustrate where it goes wrong I would expect

Utc.Now == DateTime.Now


But it is not.

I understand the convenience for have the common type and using the type system to enforce this for you but consumers of the API would have some trouble with it.

Two alternatives: 


Use a built in library type. Either DateTime to specify the exact time of execution or TimeSpan.


In this case DateTime provides the utility of ToUniversalTime() but that would require the implementer of the interface IApi to ensure that this is done. As long as you clearly document what you expect it is OK.

An added benefit is that you don't have to reinvent the wheel and your code is now more portable between all .NET platforms. These types include IComparable and IEquatable already which is one less thing to worry about for the future.


Keep the type Utc but make sure you keep the underlying type consistent to either by an offset or a fixed time.


Either one works. I would lean to storing the backing data as TimeSpan. Converting a time to the time interval from when it was called.

The implicit conversions in this case are a good idea.