Use IncludeTimeValue attribute for DateTime fields in CAML using Camlex.NET

By default when you construct query using Camlex.NET attribute IncludeTimeValue is not used. As MSDN documentation states:

Optional Boolean. Specifies to build DateTime queries based on time as well as date. If you do not set this attribute, the time portion of queries that involve date and time are ignored.

In most cases there is no need to include time part in queries when you are looking for list items and your queries will work just fine. In my project it was essential to use date and time at the same time because millions of dollars depend upon several seconds.

Enough teory. It is time for practice.

For the purpose of this training I will use SharePoint StartDate field. The basic use of date field in CAML query might look like this:

spQuery.Query = Camlex.Query().Where(x=> (DateTime)x[SPBuiltInFieldId.StartDate] >= DateTime.Now).ToString();

So generated CAML looks like this:

<Where>
<Geq>
<FieldRef ID="64cd368d-2f95-4bfc-a1f9-8d4324ecb007" />
<Value Type="DateTime">2014-05-05T02:01:01Z</Value>
</Geq>
</Where>

As you can see there is no IncludeTimeValue attribute, so time part will be skipped when querying list items. To make it even funnier Camlex.NET documentation does not mention how can you force generation of a CAML to use this attribute. But when you look into Camlex.NET DataTypes object you will notice that there is a public method IncludeTimeValue() in DateTime object.

I spend hours of figuring out how can you use this method and none of my attempts did not work. And than I noticed the usage of DataType.Integer type on Camlex.NET website. It was as just simple as that:

x => x["ID"] == (DataTypes.Integer)"1"

And I started thinking. If you can cast string to Camlex integer type… What if you can do the same for date? The best way to find out if that is possible was to write it down. I came up with code below:

spQuery.Query = Camlex.Query().Where(x => x[SPBuiltInFieldId.StartDate] >= ((DataTypes.DateTime)SPUtility.CreateISO8601DateTimeFromSystemDateTime(startDate)).IncludeTimeValue()).ToString();

Compiler was happy, Camlex was happy and as it turned out I was happy too. The output CAML looked like this:

<Where>
<Geq>
<FieldRef ID="64cd368d-2f95-4bfc-a1f9-8d4324ecb007" />
<Value Type="DateTime" IncludeTimeValue="True">2014-05-05T02:01:01Z</Value>
</Geq>
</Where>

So next time if you need to construct any Sharepoint-specific data type try casting string to that type.