Inconsistent SharePoint timestamps with WebDAV

There are situations when moving documents using Explorer mode can retain the correct “Modified” timestamp in the browser, yet show an updated timestamp in Explorer Mode.

This is due to WebDAV showing the date associated with the File (SPFile) rather than the date associated with the SPItem. Explorer mode can update the modified date in the SPFile.

When you probe further, the “Item” has the correct timestamp (item[“Modified”] is in the local timezone. However the SPFile has a property called vti_timelastmodified that has the GMT timestamp.

Note the File has a property called vti_nexttolasttimemodified as well.

Both item.file.properties[“vti_timelastmodified”] and item[“Modified”] are the same type (DateTime) so I can compare them, which is precisely what I did in a special report looking for such timestamp divergence. I generated a filtered report custom written in PowerShell to show files that are more or less than 4 or 5 hours off (depending on the time of year, the hours diverge by either 4 or 5 hours) given my ET timezone. I only look to the “minute” and not the “second” on purpose, so I don’t flag false positives.
Here is how to fix a single instance of this issue:

$docurl = "http ://sharepoint/site/list/TimestampTest/test2.docx"
$site = New-Object Microsoft.SharePoint.SPSite($docurl)
$web = $site.OpenWeb()
$item = $web.GetListItem($docurl)
$list = $item.ParentList
[System.DateTime]$date = $item["Modified"]
$user = New-Object microsoft.SharePoint.SPFieldUserValue($web, $item["Editor"])
$item["Modified"] = $date;
$item["Editor"] = $user;
$item.Update()
try { $item.Versions[1].delete() } catch {write-host -foregroundcolor red "Error (1) could not delete old version of $($item['Name'])"}

Here’s a function that reports on all URLs that suffer from this issue.  Note the use of date comparison, and the check for timestamp being off by either 4 or 5 hours, and matching on the delta of both days and minutes:

function Reset-Dates ($WebUrl, $ListName)
{
#Get web, list and content type objects
$web = Get-SPWeb $WebUrl
$list = $web.Lists[$ListName]
IF ($ReportFile -eq $null) {$reportFile = C:report.csv"}
#Check if the values specified for the content types actually exist on the list
$xSit=$WebUrl;
$xLis=$ListName;
#Go through each item in the list
$list.Items | ForEach-Object {
$item = $_;
$fd = $item.file.properties["vti_timelastmodified"]
$id = $item["Modified"]
$dd = ($id-$fd)
$hoursMatch = (($dd.hours -eq -4) -or ($dd.hours -eq -5))
$daysMatch = ($dd.days -eq 0)
$minutesMatch = ($dd.minutes -eq 0)
if ($hoursMatch -and $daysMatch -and $minutesMatch)
{
Write-Host '.' -NoNewline
}
else
{
$xURL=$item.url;
$xNam=$item['Name']
$xMod=$item["Modified"]
$xfMod = $item.file.properties["vti_timelastmodified"]
try {$xEdi=$item["ows_Modified_x0020_By"].replace("DOMAIN",$null)} catch {$xEdi=$item["ows_Modified_x0020_By"]}
try {$xAut=$item["ows_Created_x0020_By"].replace("DOMAIN",$null)} catch {$xAut=$item["ows_Created_x0020_By"]}
$Line1=$xURL+$sep+$xSit+$sep+$xLis+$sep+$xNam+$sep+$xAut+$sep+$xEdi+$sep+$xMod+$sep+$xfMod+$sep+$dd.days+$sep+$dd.hours+$sep+$dd.minutes+$sep+'1';
$Line1 | Out-file -Filepath $ReportFile -Append
$Line1=$null;
}
}
$web.Dispose()
}
0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *