> if I wanted go guard against "something that DateTime accepts" it feels like `when is_struct(datetime, DateTime) or is_struct(datetime, DateTime.Lazy)` would future proof that guard, where as `when is_struct(datetime, DateTime) or datetime == :utc_now` wouldn't.
Regardless of atom/struct/other implementation of a sentinel value, I think this is a compelling point: if we're going to expand the range of datatypes allowed as arguments to Date+Time functions, we should probably offer a stable guard API for callers to leverage.
Aka a Date.is_date/1 guard and {NativeDateTime, DateTime}.is_date_time/1 guards.
I do prefer the idea of a sentinel value to procure a utc_now datetime, to minimize the size of the Date+Time APIs. If we pursue this, I think we must be very intentional in the documentation about when the sentinel gets resolved into a proper Date+Time, though.
Ex. without clear instruction, I'd expect a struct called DateTime.Lazy to not get resolved until absolutely required by a Date+Time call that actually has to produce a value out of it, ex deferring shifting until serialized/stringified or a subcomponent is extracted.
My understanding that is not what's being proposed, though—rather that any Date+Time callsite that recieves the sentinel will immediately procure a proper utc_now Date+Time.
This ambiguity may be more a problem with the proposed term "Lazy" than anything else, but I think the docs would need to make resolution time crystal clear no matter the terminology chosen.