[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/22 20:22 | 2011/12/22 12:22 | 2011/12/22 4:22 | ||
2011/12/22 12:22 | 2011/12/22 20: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 |
从表格中看出
- 通过webservice更新时间字段时,已经要求了时间格式,并且该时间值会作为UTC时间写入到sharepoint中。在这种情况下通过COM读取该时间字段,会进行-8H的处理。可以认为通过COM方式读取时间字段时候,sharepoint默认会根据UTC时间和用户时区进行时间转换。
- 通过COM更新时间字段时,若传入的参数值已经按格式yyyy-MM-ddTHH:mm:ssZ(UTC)格式化,sharepoint在接受该参数时,a)先转换为时区时间(+8). b)最后在写入sharepoint时,会根据本地时区和UTC的时差进行转换(--8,因为读取的时是-8)。若传入的参数值未进行UTC格式化,则跳过a步骤,之后的读取结果也是一样。
- 总之,通过webservice写入的时间值直接作为UTC时间,期间不会进行时区转换。通过COM方式写入时,根据参数值的格式,时区转换差额存在区别。
本文版权归菜鸟和博客园共有,欢迎转载,但请注明出处。