Wednesday, May 25, 2011

Convert.ToInt32(DateTime) is a Lie

Warning, this is a bit of a rant, I'm just blown away.

I'm building some new features into our C# REST API that all of our phone apps talk to and I wanted to send down a Date in the form of an integer.  I noticed that there was a surprising helper method in the Convert class called ToInt32(DateTime).  That sounded perfect for what I needed, but I really wan't sure what the format would be since you can't really squeeze a DateTime object into 32 bits.  I figured they probably had some standard though, maybe the number of seconds since 1/1/1970 (like Unix/POSIX) or something like that.  So I opened up the documentation and low and behold I find:


Convert.ToInt32 Method (DateTime)

.NET Framework 4


Calling this method always throws InvalidCastException.


http://msdn.microsoft.com/en-us/library/ch56d3w9.aspx

Using this doesn't result in a compiler error.  It doesn't even result in any warnings at compile time.  It just results in a runtime exception if you were naive enough to assume it would do something good.  What are we developing in VB?

In my mind, the biggest benefit to strongly typed languages like c# is that they should expose the fact that you did something stupid at compile time so you don't need to wait for it to crash on your when it's released... (OK: there are probably a million different reasons why strongly type languages make sense, but that's one of them ;-) )


Sorry for the Rant-- Back to being productive.

2 comments:

HalfInchShy said...

I didn't know about that method either. Must be something new and obviously not well thought out.

Use DateTime.Ticks with some scaling if you want an integer. Tick's timebase is year 0001, though. If you want more Posix style time base of Jan 1 '70 as a count of seconds (it is seconds, right?), you could write an extension method called "PosixTime" as

public static class NerdBob {
static readonly DateTime k70sBasis = new DateTime(1970, 1, 1);

static Int32 PosixTime(this DateTime value) {
return (Int32)(value-k70sBasis).TotalSeconds;
}
}

Bob Wold said...

Yeah, I ended up doing just about exactly what you posted for Posix Time (only I didn't write it in as few lines as you did in your example).

Thanks ;-)