在从ListItemCollection和FileCollection调用File obj Created和Modified属性时,我注意到了一些值的差异。详细信息如下:
下面是一些从FileCollection中的文件夹中提取文件的旧代码,我在这里初始化所需的属性:
using (var spClientContext = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, _clientId, _clientSecret))
{
if (spClientContext != null)
{
List list = spClientContext.Web.Lists.GetByTitle("Documents");
spClientContext.Load(list);
spClientContext.Load(list.RootFolder);
spClientContext.Load(list.RootFolder.Folders);
spClientContext.ExecuteQuery();
FolderCollection fcol = list.RootFolder.Folders;
if (fcol != null)
{
foreach (Folder f in fcol)
{
if (f.Name.Equals(folderName, StringComparison.InvariantCultureIgnoreCase))
{
spClientContext.Load(f.Files,
items => items.Include(
item => item.Name,
item => item.Author,
item => item.ModifiedBy,
item => item.ListItemAllFields["Created"],
item => item.ListItemAllFields["Modified"],
item => item.ListItemAllFields["FileRef"],
item => item.Length));
spClientContext.ExecuteQuery();
FileCollection fileCol = f.Files;
foreach (File file in fileCol)
{
// Do Stuff
}
}
}
}
}
}
当我输出文件创建和修改日期/时间值时,我得到以下信息:
- 创建时间:2021年6月17日下午11:40:28(正确日期/时间(
- 修改时间:2021年6月17日下午11:41:12(正确日期/时间(
下面是我更新的代码,它收集ListItemCollection中的文件并初始化文件属性:
using (ClientContext spClientContext = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, _clientId, _clientSecret))
{
if (spClientContext != null)
{
CamlQuery camlQuery = new CamlQuery();
camlQuery.FolderServerRelativeUrl = getSiteUrlAbsolutePath(siteUrl) + "/Shared Documents/" + folderPath;
camlQuery.ViewXml = "<View Scope="RecursiveAll">" +
"<Query>" +
"<Where>" +
"<Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq>" +
"</Where>" +
"</Query>" +
"</View>";
List list = spClientContext.Web.Lists.GetByTitle("Documents");
ListItemCollection listItems = list.GetItems(camlQuery);
spClientContext.Load(listItems,
items => items.Include(
item => item.DisplayName,
item => item.FileSystemObjectType,
item => item.File,
item => item.File.Name,
item => item.File.Author,
item => item.File.ModifiedBy,
item => item.File.ListItemAllFields["Created"],
item => item.File.ListItemAllFields["Modified"],
item => item.File.ListItemAllFields["FileRef"],
item => item.File.Length));
spClientContext.ExecuteQuery();
if (listItems != null && listItems.Count > 0)
{
foreach (ListItem item in listItems)
{
if (item.FileSystemObjectType.Equals(FileSystemObjectType.File))
{
// Do Stuff
}
}
}
}
}
当我输出文件创建和修改日期/时间值时,我得到以下信息:
- 创建时间:2021年6月18日上午6:40:28(日期/时间不正确(
- 修改时间:2021年6月18日上午6:41:12(日期/时间不正确(
新代码中的所有其他File属性似乎都是正确的。从我在新代码中可以看出,Created和Modified是在输出UTC,而不是在SharePoint网站设置中识别时区设置?或者我在错误的位置初始化文件属性?
感谢您的反馈和帮助!
编辑:
测试以下代码,加载@Antonio Leonardo建议的区域网站设置:
using (ClientContext spClientContext = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, _clientId, _clientSecret))
{
if (spClientContext != null)
{
Web web = spClientContext.Web;
spClientContext.Load(web.RegionalSettings);
spClientContext.ExecuteQuery();
int localId = (int)web.RegionalSettings.LocaleId;
string cultureInfo = (new CultureInfo(localId)).Name;
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(cultureInfo);
CamlQuery camlQuery = new CamlQuery();
camlQuery.FolderServerRelativeUrl = getSiteUrlAbsolutePath(siteUrl) + "/Shared Documents/" + folderPath;
camlQuery.ViewXml = "<View Scope="RecursiveAll">" +
"<Query>" +
"<Where>" +
"<Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq>" +
"</Where>" +
"</Query>" +
"</View>";
List list = spClientContext.Web.Lists.GetByTitle("Documents");
ListItemCollection listItems = list.GetItems(camlQuery);
spClientContext.Load(listItems,
items => items.Include(
item => item.DisplayName,
item => item.FileSystemObjectType,
item => item.File,
item => item.File.Name,
item => item.File.Author,
item => item.File.ModifiedBy,
item => item.File.ListItemAllFields["Created"],
item => item.File.ListItemAllFields["Modified"],
item => item.File.ListItemAllFields["FileRef"],
item => item.File.Length));
spClientContext.ExecuteQuery();
if (listItems != null && listItems.Count > 0)
{
foreach (ListItem item in listItems)
{
if (item.FileSystemObjectType.Equals(FileSystemObjectType.File))
{
// Do Stuff
}
}
}
}
}
当我输出加载了区域站点设置的文件创建和修改日期/时间值时,我得到以下信息:
- 创建时间:2021年6月18日上午6:40:28(日期/时间不正确(
- 修改时间:2021年6月18日上午6:41:12(日期/时间不正确(
对您的代码进行简短分析,我同意您的假设,即第二种方法需要识别SharePoint网站集中定义的时区;然后我建议测试下面的代码,尝试更改输出。下面的代码将捕获区域设置,这将在运行时设置您的应用程序区域性信息(需要在日期捕获之前添加(:
Web web = spClientContext.Web;
spClientContext.Load(web.RegionalSettings);
spClientContext.ExecuteQuery();
int localId = (int) web.RegionalSettings.LocaleId;
string cultureInfo = (new CultureInfo(localId)).Name;
System.Threading.Thread.CurrentThread.CurrentUICulture =
CultureInfo.GetCultureInfo(cultureInfo);
但是,经过测试,您在上面分享的这种方法并没有纠正日期错误。
在研究中,我在这个SharePoint Stack Exchange主题中遇到了同样的问题(ASP.NET中的SharePoint DateTime转换问题,状态已解决(,包含了另一种修复日期输出的方法;请检查一下它是否适合您的情况:
SPRegionalSettings regionalSettings = web.RegionalSettings;
SPTimeZone timeZone = regionalSettings.TimeZone;
timeZone.UTCToLocalTime(dateTimeObject);
为我最初的问题找到了一个强大的解决方案。下面是我正在使用的ConvertUTCToLocalDateTime((方法的副本。我通过它传递所有SharePoint DateTime属性,并检查DateTime是UTC还是本地。如果UTC使用站点时区区域设置转换为本地。这省去了试图弄清楚哪些属性是UTC或Local的痛苦,因为它们与属性不同:
// File object DateTime ListItemAllFields property example calling ConvertUTCToLocalDateTime()
DateTime fileCreated = File.IsObjectPropertyInstantiated("ListItemAllFields") ?
ConvertUTCToLocalDateTime(spClientContext, (DateTime)File.ListItemAllFields["Created"]) : default(DateTime);
.
.
.
// FileVersion object DateTime property example calling ConvertUTCToLocalDateTime()
DateTime versionModified = FileVersion.IsPropertyAvailable("Created") ?
ConvertUTCToLocalDateTime(spClientContext, FileVersion.Created) : default(DateTime);
.
.
.
/// <summary>
/// Converts SharePoint UTC DateTime to Local DateTime using site regional time zone settings.
/// </summary>
/// <remarks>
/// SharePoint DateTime values can be a mix of UTC and Local in API. Need to pass all DateTime values through this method to check.
/// </remarks>
/// <param name="spClientContext">ClientContext</param>
/// <param name="dateObj">DateTime</param>
/// <returns>DateTime</returns>
public static DateTime ConvertUTCToLocalDateTime(ClientContext spClientContext, DateTime dateObj)
{
try
{
if (spClientContext != null)
{
DateTime temp;
if (DateTime.TryParse(dateObj.ToString(), out temp))
{
if (dateObj.Kind == DateTimeKind.Utc)
{
// convert utc datetime to local datetime using sharepoint site regional time zone settings
Microsoft.SharePoint.Client.TimeZone sharePointTimeZone = spClientContext.Web.RegionalSettings.TimeZone;
ClientResult<DateTime> localDateTime = sharePointTimeZone.UTCToLocalTime(dateObj);
spClientContext.ExecuteQuery();
return localDateTime.Value;
}
else if (dateObj.Kind == DateTimeKind.Local)
{
// local datetime just return (no convertion required)
return dateObj;
}
else if(dateObj.Kind == DateTimeKind.Unspecified)
{
// unspecified datetime handle as required
return dateObj;
}
}
}
}
catch (Exception ex)
{
// log exception
}
return dateObj;
}
此外,作为一种替代方法(或额外措施(,如果您使用CamlQuery获取ListItemCollection列表项,则可以将CamlQuery.DatesInUtc属性设置为False,这将返回所有初始化属性的本地日期时间值:
using (ClientContext spClientContext = new AuthenticationManager().GetACSAppOnlyContext(siteUrl, _clientId, _clientSecret))
{
if (spClientContext != null)
{
Web web = spClientContext.Web;
spClientContext.Load(web.RegionalSettings);
spClientContext.ExecuteQuery();
int localId = (int)web.RegionalSettings.LocaleId;
string cultureInfo = (new CultureInfo(localId)).Name;
System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(cultureInfo);
CamlQuery camlQuery = new CamlQuery();
camlQuery.DatesInUtc = false; // uses site regional time zone datetime when set to false
camlQuery.FolderServerRelativeUrl = getSiteUrlAbsolutePath(siteUrl) + "/Shared Documents/" + folderPath;
camlQuery.ViewXml = "<View Scope="RecursiveAll">" +
"<Query>" +
"<Where>" +
"<Eq><FieldRef Name='FSObjType' /><Value Type='Integer'>0</Value></Eq>" +
"</Where>" +
"</Query>" +
"</View>";
List list = spClientContext.Web.Lists.GetByTitle("Documents");
ListItemCollection listItems = list.GetItems(camlQuery);
spClientContext.Load(listItems,
items => items.Include(
item => item.DisplayName,
item => item.FileSystemObjectType,
item => item.File,
item => item.File.Name,
item => item.File.Author,
item => item.File.ModifiedBy,
item => item.File.ListItemAllFields["Created"],
item => item.File.ListItemAllFields["Modified"],
item => item.File.ListItemAllFields["FileRef"],
item => item.File.Length));
spClientContext.ExecuteQuery();
if (listItems != null && listItems.Count > 0)
{
foreach (ListItem item in listItems)
{
if (item.FileSystemObjectType.Equals(FileSystemObjectType.File))
{
// Do Stuff
}
}
}
}
}
希望这些解决方案是有帮助的,因为没有太多的官方文件关于这个问题。感谢所有对帖子的反馈!