Friday, February 7, 2014

Converting DateTime to Date in Apex: Undocumented Pitfall

All roads lead to Rome... almost.  There's more than one way to do the conversion in Apex, and they yield subtle but meaningful differences.  Consider these two statements:

system.debug(Date.Valueof(DateTime.valueof('2014-02-06 21:11:11')));

system.debug(DateTime.valueof('2014-02-06 21:11:11').date());

Both on the surface do an explicit type cast from DateTime to Date, but the results are different.  An important note: I ran them as an Eastern Time Zone user.  Here are the results:

10:12:51.045 (45992000)|USER_DEBUG|[8]|DEBUG|2014-02-07 02:11:11
10:12:51.046 (46064000)|USER_DEBUG|[9]|DEBUG|2014-02-06 00:00:00

Semantically the second statement has the right answer: as a user in EST, I expect to get the date in my time zone, which should be Feb 6th.  The first one seems to supply a GMT date.  Also note it still has the time part.  Weird.

The catch here is, Date.valueOf(DateTime) doesn't exist in the official documentation.  Date.valueOf(Object) does exist, but that's meant to be used only with history tracking values.  Since it's not officially supported, I guess you can't blame Salesforce officially for the unexpected result.

I didn't use the undocumented method on purpose - I just did it assuming it's there.  Apex, after all, is only almost strongly typed, because we don't have well-documented rules for type casting.  I crossed the boundary, and I was on my own.  Well, it wasn't that bad - it just cost me some extra time to figure out why the hell the test failed at night, when it ran flawlessly during the day.

No comments:

Post a Comment