创建和修改的文件对象 属性 值不同于 ListItemCollection 和 FileCollection

File object created and modified property values vary from ListItemCollection and FileCollection

我注意到在从 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
                    }
                }
            }
        }
    }
}

当我输出文件创建和修改的 date/time 值时,我得到以下信息:

下面是我更新的代码,它在 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
                }
            }
        }
    }
}

当我输出文件创建和修改的 date/time 值时,我得到以下信息:

新代码中的所有其他文件属性似乎都是正确的。据我所知,新代码 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
                }
            }
        }
    }
}

当我输出加载了区域站点设置的文件创建和修改 date/time 值时,我得到以下信息:

对您的代码进行简短分析,我同意您假设第二种方法需要识别 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 主题(SharePoint DateTime conversion issue in ASP.NET,状态已解决)中遇到了同样的问题,其中包含另一种修复日期输出的方法;请检查它是否适合您的情况:

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,这将 return 所有初始化属性的本地 DateTime 值:

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
                }
            }
        }
    }
}

希望这些解决方案对您有所帮助,因为关于此事的官方文档不多。感谢您对 post!

的所有反馈