[SharePoint 2010] 中关于UTC时间的问题记录

最近业务部门总是反馈说查询出来的文档发布日期不对,检查后发现,实际日期和显示的日期总有8H的差值。8这个数字应该就是北京时间和UTC时间的时差了。

翻阅了一些资料(http://www.novolocus.com/2008/07/31/sharepoint-web-services-and-utc-time-fun-and-games/),下面做一些测试。

我们知道Sharepoint是支持多个时区的,用户可以设置自己合适的时区。因此sharepoint采用UTC方式来存储时间,不管哪个时区的时间,最终写入sharepoint的都是UTC时间。

测试环境:Sharepoint 2010

测试数据:以2011年12月22日 12:22:11为例。列表:TestUTC 栏:MyTime(日期和时间)

1.采用webservice方式更新时间字段。注意,此方式要求更新的时间格式为yyyy-MM-ddTHH:mm:ssZ

        protected void UpdateByWebService()
        {
            DateTime dt = DateTime.Parse("2011-12-22 12:22:11");
            ListService.Lists lst = new ListService.Lists();
            lst.Url = "http://mydemo/_vti_bin/Lists.asmx";
            lst.Credentials = CredentialCache.DefaultCredentials;

            XmlDocument xml = new XmlDocument();
            XmlElement xe = xml.CreateElement("Batch");
            xe.SetAttribute("OnError", "Continue");
            XmlNode xnResult = null;

            string strXml = @"<Method ID='1' Cmd='Update'>
                                  <Field Name='ID'>1</Field>
                                  <Field Name='MyTime'>{0}</Field>
                               </Method>";

            xe.InnerXml = string.Format(strXml, dt.ToString("yyyy-MM-ddTHH:mm:ssZ"));
            xnResult = lst.UpdateListItems("TestUTC", xe);
        }

2.采用COM方式更新时间字段。

        protected void UpdateByCOM()
        {
            DateTime dt = DateTime.Parse("2011-12-22 12:22:11");
            using (SP.ClientContext context = new SP.ClientContext("http://mydemo/"))
            {
                context.Credentials = CredentialCache.DefaultCredentials;
                SP.List lst = context.Web.Lists.GetByTitle("TestUTC");

                context.Load(lst);

                SP.ListItem li = lst.GetItemById(2);
                
                context.Load(li);

                if (li == null) return;

                li["MyTime"] = dt.ToString("yyyy-MM-ddTHH:mm:ssZ");//dt.ToString();

                li.Update();

                context.ExecuteQuery();

            }
        }

3.通过webservice方式读取时间字段。

        protected void ReadFromWebservice()
        {
            ListService.Lists lst = new ListService.Lists();
            lst.Url = "http://mydemo/_vti_bin/Lists.asmx";
            lst.Credentials = CredentialCache.DefaultCredentials;

            XmlDocument xmlDoc = new XmlDocument();
            XmlNode xnQuery = xmlDoc.CreateElement("Query");

            string xmlFilter = @"<Where><Eq><FieldRef Name='ID' /><Value Type='Text'>1</Value></Eq></Where>";
            xnQuery.InnerXml = xmlFilter;

            XmlNode xnList = lst.GetListItems("TestUTC", "{4208DB7A-A0E1-4699-9187-A15AB78234B5}", xnQuery, null, "1", null, null);
            
            int itemCount = Convert.ToInt16(xnList.ChildNodes[1].Attributes["ItemCount"].Value);
            if (itemCount < 1) return;

            string strMyTime = string.Empty;
            foreach (XmlNode xn in xnList.ChildNodes[1].ChildNodes)
            {
                if (xn.Name.ToLower() != "z:row") continue;
                strMyTime = xn.Attributes["ows_MyTime"].Value;
            }
            lblWB.Text = strMyTime;
        }

4.通过COM读取时间字段。

        protected void ReadFromCOM()
        {
            string strMyTime = string.Empty;

            using (SP.ClientContext context = new SP.ClientContext("http://mydemo/"))
            {
                context.Credentials = CredentialCache.DefaultCredentials;
                SP.List lst = context.Web.Lists.GetByTitle("TestUTC");

                context.Load(lst);

                SP.ListItem li = lst.GetItemById(1);

                context.Load(li);
                context.ExecuteQuery();

                if (li == null) return;

                strMyTime = ((DateTime)li["MyTime"]).ToString();
            }

            lblCOM.Text = strMyTime;
        }

5.结果对比

时区:东八区,时差+8H,即北京时间=UTC+8H
传入参数值 Client Object Model更新 Webservice更新
界面显示 通过webservice读取 通过COM读取 界面显示 通过webservice读取 通过COM读取
2011-12-22T12:22:00Z
2011/12/23 4:22
2011/12/23 4:22 2011/12/22 20:22 2011/12/22 12:22
2011/12/22 12:22
2011/12/22 4:22
2011/12/22 12:22 2011/12/22 20:22
2011/12/22 20:22
2011/12/22 12:22
NULL NULL NULL
2011-12-22T4:22:00Z 2011/12/22 20:22 2011/12/22 20:22 2011/12/22 12:22 2011/12/22 4:22 2011/12/22 4:22 2011/12/21 12:22
2011/12/22 4:22 2011/12/22 12:22 2011/12/22 12:22 2011/12/22 4:22 NULL NULL NULL

从表格中看出

  1. 通过webservice更新时间字段时,已经要求了时间格式,并且该时间值会作为UTC时间写入到sharepoint中。在这种情况下通过COM读取该时间字段,会进行-8H的处理。可以认为通过COM方式读取时间字段时候,sharepoint默认会根据UTC时间和用户时区进行时间转换。
  2. 通过COM更新时间字段时,若传入的参数值已经按格式yyyy-MM-ddTHH:mm:ssZ(UTC)格式化,sharepoint在接受该参数时,a)先转换为时区时间(+8). b)最后在写入sharepoint时,会根据本地时区和UTC的时差进行转换(--8,因为读取的时是-8)。若传入的参数值未进行UTC格式化,则跳过a步骤,之后的读取结果也是一样。
  3. 总之,通过webservice写入的时间值直接作为UTC时间,期间不会进行时区转换。通过COM方式写入时,根据参数值的格式,时区转换差额存在区别。

 

 

posted @ 2012-10-11 16:19  一只小小菜鸟  阅读(525)  评论(1编辑  收藏  举报