我有一个Windows C程序,可以从unix服务器下载文件及其修改时间。然后,它将本地副本保存在缓存中,并将其时间戳设置为与服务器上的时间戳匹配 - 因此,如果本地副本是最新的,则无需提取新副本。
无论如何,它使用utime()将时间戳设置为unix主机报告的二进制值,然后使用stat()读回时间戳以检查文件是否过期。这曾经有用,但我注意到它不再起作用了。
对于它的价值,时间的差异是3600秒(1小时),所以我猜这与utime和/或stat如何处理时区有关。我只是认为stat会向我报告我在utime中设置的相同修改时间值,但显然是(不再是?)true。我在这里看过另一篇帖子,提到Windows实施统计数据会让人节省夏令时 - 所以可能就是这样。
是否有更正确的方法在Windows中执行此操作 - 同时仍使用POSIX时间函数。请记住,我正在尝试获取本地文件的二进制mod时间(由Windows报告)以匹配主机文件的mod时间(由unix上的stat报告)。
以下是一些显示问题的示例代码。 fc-> timestamp是从服务器发送的值。我将它复制到utimes,调用utime()和stat(),并且statbuf.st_mtime与其他人不同3600秒:
// Set the local file's timestamp to the host's value
utimes.actime = utimes.modtime = fc->timestamp;
utime(szTempPath2, &utimes);
// Now call stat to see what time registers there.
if (stat(szTempPath2, &statbuf) == 0) {
if (fc->timestamp != statbuf.st_mtime)
fc->timestamp = statbuf.st_mtime;
}
When I'm done the values are:
fc->timestamp = 1359772839
utimes.modtime = 1359772839
statbuf.st_mtime = 1359776439 <<== this is 3600 more than the others
答案 0 :(得分:0)
原来,utime()是罪魁祸首。
如果你使用utime来设置mod时间,如果NTFS夏令时问题生效,stat()和GetFileTime()都将返回你的时间+ 1小时。但是如果你使用SetFileTime,stat()和GetFileTime都将返回你设置的时间 - 无论NTFS如何处理夏令时。
所以,它就像上面评论中描述的erkysun一样,除了你需要反转windows-to-unix时间戳计算,而是将unix时间戳转换为自1/1/1601以来的windows UTC微秒(使用常数erkysun提供)。像这样:
ulong unix_timestamp;
ULONGLONG win_timestamp;
ULARGE_INTEGER li;
HFILE hFile;
FILETIME filetime;
if (hFile = CreateFile(szTempPath2, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL)) {
// Convert the unix timestamp to Windows UTC time
// 1/1/1970 unix base date (seconds) to 1/1/1601 windows base date
win_timestamp = unix_timestamp + 11644473600;
// seconds to 100's of nanoseconds
win_timestamp *= 10000000;
// Copy the long long int into filetime high/low and
// use to set the access and mod times.
li.QuadPart = win_timestamp;
filetime.dwHighDateTime = li.HighPart;
filetime.dwLowDateTime = li.LowPart;
SetFileTime(hFile, NULL, &filetime, &filetime);
CloseHandle(hFile);
}