Here you can see how SharePoint is looking up the value for "Today"
private static string GetTodayValue(string token, IReadOnlyPropertyCollection queryProperties)
{
string parameterNameFromToken = QueryTemplateHelper.GetParameterNameFromToken(token);
DateTime dateTime = DateTime.Now;
if (queryProperties != null && queryProperties.ContainsKey(parameterNameFromToken))
{
object obj = queryProperties[parameterNameFromToken];
if (obj is DateTime)
dateTime = (DateTime) obj;
else if (obj is string)
dateTime = DateTime.Parse((string) obj, (IFormatProvider) CultureInfo.InvariantCulture);
}
char[] chArray = new char[4]
{
'[',
']',
'{',
'}'
};
token = token.Trim(chArray).Trim();
string s = token.Substring(5);
int result = 0;
if (int.TryParse(s, out result))
return dateTime.AddDays((double) result).ToString("yyyy-MM-dd", (IFormatProvider) CultureInfo.InvariantCulture);
return dateTime.ToString("yyyy-MM-dd", (IFormatProvider) CultureInfo.InvariantCulture);
}
As you can see, they do nothing else (besides some minor sideways) than taking DateTime.Now and writing the Date-Portion as string to the query.
Having in mind that SharePoint stores (and finds) all Dates in UTC, the fact that "Today" is replaced by DateTime.Now´s Date makes using it totally worthless.
In my opinion the code should be something like
DateTime.Today.ToUniversalTime.ToString("yyyy-MM-dd"). And even that would work only for date-only fields. If they Metadata should also respect Time for the user, the "Today" replacement would have to respect overlapping of days (e.g. 11.05.2015 23:00:00 - 12.05.2015 23:00:00). However in current implementation in most cases it would deliver wrong (or not as expected) results, as long as you are not using UTC0 g.
For example:
If I set a Date-Metadata for today, 12.05.2015. As we do have UTC+1, SharePoint stores the date for 11.05.2015 23:00:00. If I do a search with the "Today" Option, I wont find it, because today searches for 12.5.2015.