3

I have an issue with IConvertible, in short: If DateTimeOffset implemented IConvertible I would not have an issue.

You cannot use extension methods to implement an interface, so that road is closed. The struct DateTimeOffset is not partial so it cannot be extended that way.

When reading up in some MSDN docs I came across the TypeCode enum, which seems to be needed for IConvertible to work properly. And to my disappointment the enum did not contain TimeSpan either, which closes the option of using a Tuple-like structure with DateTime and TimeSpan (ie DateTimeOffset =P)

My question is as follows: How would you implement a DateTimeOffset-equivalent which has rudimentary IConvertible or similar support?

The implementation is concerning a fancy lazy dictionary implementation with [index,TType] where TType : IConvertible (both setters, getters and try-getters) functionality, and it needs to be able to store timezone specific data.

My ideas so far:

  • Create a new ISuperConvertible interface which in reality is just an extension to IConvertible and make DateTimeOffset a special case. This would break our IConvertible support in general, but work for this very specific case. Pros and cons?

  • Use two "slots" for storing DateTimeOffsets, one for the DateTime and one for the int halfhour offset (all timezones are not whole hours =/). Then we lose the cache[ApplicationStrings.LastUpdate, default : DateTimeOffset.Min] functionality.

Those represent my main thoughts, ie break DateTimeOffset and keep IConvertible or break IConvertible and keep DateTimeOffset.

I'm still new to the intrinsic peculiarities of C#, so any insight would be helpful. What are your thoughts?

EDIT: Additions:

  • There is a working solution right now which uses DateTime (fixed timezone), but now timezone is needed as well, optimal scenario would be to just use DateTimeOffset everywhere instead. The question in its essence is not about refactoring, but my specific problem is.
  • It is a quite large application, it uses entity framework and other more obscure frameworks for communicating with different services and storages, therefore keeping it a simple System defined type would not break LINQ-to-X optimizations etc (I have no idea how hard these are to do yourself).
  • I'm against splitting data, since I have no idea when another guy will come along and notice that there is a DateTime used for timestamping, and use it without taking the offset (timezone) into account.
flindeberg
  • 4,887
  • 1
  • 24
  • 37
  • 2
    What are you actually trying to do with this `ISuperConvertible `? – Thom Smith Jul 30 '12 at 17:30
  • 2
    Note that there's no such concept as partial for already-compiled code - it's only at the source code level. – Jon Skeet Jul 30 '12 at 17:39
  • 1
    Have you considered dropping the time zone information and making all dates in your dictionary UTC? Then you could use DateTimeOffset.UtcDateTime to get DateTime, which does implement IConvertible. – JamieSee Jul 30 '12 at 18:24
  • What do you need that? What are you trying to do? – Sergei Rogovtcev Jul 30 '12 at 20:06
  • @ThomSmith `ISuperConvertible` would just be a wrapper, and one step in the direction of wrapping `Convert` etc to keep functionality. IE replacing IConvertible and Convert functionality with my own implementation (which does seem like a lot of trouble). – flindeberg Jul 30 '12 at 20:53
  • @JamieSee The problem there is that we mustn't lose information, if the date was entered in with a certain timezone we must store it that way (This is actually governed by regulation, not much I can do here). – flindeberg Jul 30 '12 at 20:55
  • @SergRogovtsev What we are trying to do? Build something fancy ofcourse :D What I actually need is DateTimeOffset as well as TimeSpan to be treated as proper .NET primitives, they seem to be handled as bastards right now. I agree that would make sense from a purely programatic point of view, but given where international regulation is going it is very weird from a business perspective not to treat them as proper .NET types. – flindeberg Jul 30 '12 at 20:59
  • Why do you need that? (That's my favorite question) Why do you need `TimeSpan` to implement `IConvertible`? – Sergei Rogovtcev Jul 30 '12 at 21:01
  • @SergRogovtsev Right now the codebase is using IConvertible for limiting arguments to "simple" types in generic methods, I guess this has been the convention for a while. Keeping it under the IConvertible umbrella would keep it alot simpler :D I'm updating my question a bit as well. – flindeberg Jul 30 '12 at 21:10
  • That's funny, because *conventional* method for that is using `struct` constraint. – Sergei Rogovtcev Jul 30 '12 at 21:14
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/14653/discussion-between-flindeberg-and-serg-rogovtsev) – flindeberg Jul 30 '12 at 21:27
  • 1
    I know this is ridiculously simple and possibly naive, but have you considered just converting DateTimeOffset to a string before storing it in your dictionary? `.ToString(System.Globalization.DateTimeFormatInfo.InvariantInfo)` – JamieSee Jul 30 '12 at 23:18
  • @JamieSee In essence that would do it, but I'm looking for a smart ninja solution. But it seems like I will have to resort some good old bruteforcing.. – flindeberg Jul 31 '12 at 09:14

1 Answers1

0

You can create your own wrapper class on DateTimeOffset that will implement IConvertible. This class will have property of DateTimeOffset, that you will use for your wrapper properties and methods. And you implement methods of IConvertible for it. Example:

public class DTOffset:IConvertible
{
    private DateTimeOffset DateTimeOffset;

    //Implementation of IConvertible
    public long ToInt64(IFormatProvider provider)
    {
        return DateTimeOffset.Ticks;
    }

    public DateTime ToDateTime(IFormatProvider provider)
    {
        DateTimeOffset.DateTime;
    }
    //and so on

    //wrapper properites of DateTimeOffset:
    public int DayOfYear{get{return DateTimeOffset.DayOfYear;}}

    public DateTime Date{get{return DateTimeOffset.Date;}}
    //and so on
}
Kirill Bestemyanov
  • 11,946
  • 2
  • 24
  • 38