SharePoint - 全天事件在CAML查询中表现不同

7
在SharePoint日历列表中,我创建了两个今天日期的事件。一个是全天事件,另一个则将开始时间设为上午12点,结束时间设为晚上11:55。当我使用"U2U CAML Query Builder"创建一个CAML查询时,出现了一些奇怪的行为。当我的查询只是一个简单的"OrderBy"时,两个事件都会被返回。但是当我执行以下查询来搜索大于或等于今天的事件时,只有未标记为"全天事件"的事件被返回:
<Where>
    <Geq>
        <FieldRef Name='EventDate' />
        <Value Type='DateTime'>2009-10-05T00:00:00Z</Value>
    </Geq>
</Where>

使用查询生成器工具检查结果后,我发现“EventDate”(开始时间列的内部名称)的值是相同的(2009-10-05 00:00:00)。为什么SharePoint会将这两个事件视为相同?这可能是一个时区问题吗?
编辑:更多信息,我认为这可能是一个时区问题。我发现“Value”元素的“IncludeTimeValue”属性 - 在这里描述:MSDN。我在东海岸(目前是GMT-4小时)。如果我按以下方式编辑“Value”元素:(请注意,日期现在是4号而不是5号)
<Value Type='DateTime' IncludeTimeValue='True'>2009-10-04T20:00:00Z</Value>

然后两个事件都会被返回,但是如果我将时间调整到20:01,那么我就会失去全天事件。当我调整到20:01时,我也会失去全天事件。有人知道我在哪里可以找到这种行为的详细描述吗?
4个回答

8

SharePoint将日期/时间存储为UTC时间(也称为GMT或Zulu),在显示时先转换为站点本地时区。

但是,对于全天事件,它将时间(00:00到23:59:00)存储在站点的本地时区中。

正如您已经自己发现的那样 - 我相信您已经发现了SharePoint解释查询的方式中的错误,并且忘记了全天事件是本地时间。

我想您可以通过查询以下内容来进行不好的解决:

EventDate >= SomeDate OR AllDayEvent = True AND EventDate >= SomeDate - 4hrs

这位作者也有类似的问题 SO - SharePoint all day event gives obscure result

这将为您提供更多有关SharePoint中时区问题的见解 SharePoint Web Services and UTC time fun and games

如果这还不够让你感到沮丧,那么看看通过对象模型查看创建/修改日期,并惊叹于普通事件报告本地时间,而全天事件则报告UTC时间!


我在 CAML 查询中添加了一个简单的解决方法,以便考虑“全天事件”。请在这里查看:https://sharepoint.stackexchange.com/questions/244536/include-all-day-events-in-caml-query-for-a-date/248884#248884 - Alberto S.

1

处理 CAML 查询结果时,这样做可以解决问题,但并不理想:

foreach (SPListItem item in _items){

     //   ... loop for processing items returned from CAML query, 
     //       code unrelated to UTC conversion excluded

      var localSDate = Convert.ToDateTime(item["StartDate"].ToString());

      if (Convert.ToBoolean(item["fAllDayEvent"])){
            localSDate = localSDate.ToUniversalTime();
      }
}

注意:此修正假设您没有通过日期限制搜索。显然,在这种情况下,它将不起作用,除非您扩展搜索参数以包括比实际需要返回的范围更广的范围。

我知道这不完全是海报要寻找的内容,但这可能会帮助其他找到此页面的人......关于此问题,没有很多记录。

具体而言,如果您按月查询,并仅显示存在于该月份的日历项,则此修正将起作用。 在这种情况下,CAML 将无论如何返回上个月的最后几天和下个月的前几天,因此您不会失去由一天偏移的数据。(使用 <Month />)


Convert.ToBoolean(item["fAllDayEvent"]) 正是我正在寻找的。谢谢! - Philipp Hofmann

1
oQuery.Query = "<Where><Geq><FieldRef Name='EventDate' /><Value Type='DateTime'>" + SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Today.Subtract(new TimeSpan(1))) + "</Value></Geq></Where>"

添加一个TimeSpan值,例如:

SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Today.Subtract(new TimeSpan(1)))
"2010-08-23T23:59:59Z"

这应该可以解决问题。


0

这对我有用。

<Where>
<Or>
    <Or>
        <And>
            <Eq>
                <FieldRef Name='fAllDayEvent' />
                <Value Type='AllDayEvent'>1</Value>
            </Eq>
            <Geq>
                <FieldRef Name='EndDate' />
                <Value Type='DateTime'>
                    <Today />
                </Value>
            </Geq>
        </And>
        <DateRangesOverlap>
          <FieldRef Name='EventDate' />
          <FieldRef Name='EndDate' />
          <FieldRef Name='RecurrenceID' />
          <Value Type='DateTime' IncludeTimeValue='TRUE'>
            <Today />
          </Value>
        </DateRangesOverlap>
    </Or>
   <Geq>
      <FieldRef Name='EventDate' />
      <Value Type='DateTime' IncludeTimeValue='TRUE'>
         <Today />
      </Value>
   </Geq>
</Or>
</Where>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接