dcvb 发表于 2015-9-28 07:48:24

[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.Attributes["ItemCount"].Value);
if (itemCount < 1) return;
string strMyTime = string.Empty;
foreach (XmlNode xn in xnList.ChildNodes.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


  从表格中看出


[*]通过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方式写入时,根据参数值的格式,时区转换差额存在区别。
  
  
页: [1]
查看完整版本: [SharePoint 2010] 中关于UTC时间的问题记录