【问题标题】:How to convert TDateTime to FILETIME?如何将 TDateTime 转换为 FILETIME?
【发布时间】:2017-05-10 09:16:04
【问题描述】:

标题说明了一切。互联网上充满了如何将FILETIME 转换为TDateTime 的示例,但反之则不然。

【问题讨论】:

  • DateTimeToFileDate(someDateTime);
  • DateTimeToFileDate 返回整数而不是 FILETIME。

标签: delphi delphi-xe5


【解决方案1】:
  1. System.SysUtils 致电DateTimeToSystemTime
  2. Winapi.Windows 致电SystemTimeToFileTime

如果您的原始日期时间值是本地时间,那么您需要在调用DateTimeToSystemTime 之前将其转换为UTC。

【讨论】:

  • 虽然这是有效的,但我不是这个解决方案的忠实拥护者,原因有二: 1. 我需要使用中间结构(SysteTime)和不必要的调用。 2. 我不知道我的时间价值是什么时间标准。
  • 粉丝与否,这是做它的方式。将其包裹在一个辅助方法中以隐藏细节。至于您的第二点,您只需要知道您的日期时间值所在的时区。您不能仅从日期时间值中检索该信息,它根本不是该值的一部分。
  • 因为我们知道FILETIME 表示自 1601 年 1 月 1 日以来 100 纳秒间隔的数量,并且我们知道 TDateTime 表示什么,所以可以通过一个函数将一个值转换为另一个值。这比调用两个并使用中间结构要好。我只是认为somone已经做到了。但是如果没有人提出这个解决方案,我会懒得实施,我会接受你的。
  • 通过使用中间的SYSTEMTIME 结构,您会失去精度。更好的解决方案是直接将TDateTime 转换为FILETIME,并且不会丢失4 个小数位的精度。
  • @IanBoyd 很有趣。我想如果精度很重要,那么我们应该完全避免TDateTime
【解决方案2】:

您可以在System.IOUtils 中查看ConvertDateTimeToFileTime 的实现。 它是TDirectory 记录的私有成员。 但是您可以将其用作参考,以便在一个功能中实现您想要的所有功能。

【讨论】:

  • 不错的发现,类似于@DavidHeffernan 的建议。在这一点上,我不记得我在我的代码中使用了什么:)
【解决方案3】:
function FileTimeToDateTime(AFileTime: FILETIME): TDateTime;
var
    li: ULARGE_INTEGER;
const
    OA_ZERO_TICKS = UInt64(94353120000000000);
    TICKS_PER_DAY = UInt64(864000000000);
begin
    // Convert a FILETIME (which is UTC by definition), into a UTC TDateTime.

    // Copy FILETIME into LARGE_INTEGER to allow UInt64 access without alignment faults.
    li.LowPart := AFileTime.dwLowDateTime;
    li.HighPart := AFileTime.dwHighDateTime;
    Result := (Real(li.QuadPart) - OA_ZERO_TICKS) / TICKS_PER_DAY;
end;

function DateTimeToFileTime(ADateTimeUTC: TDateTime): FILETIME;
var
    li: ULARGE_INTEGER;
const
    OA_ZERO_TICKS = UInt64(94353120000000000);
    TICKS_PER_DAY = UInt64(864000000000);
begin
    // Convert a UTC TDateTime into a FILETIME (which is UTC by definition).

    li.QuadPart := Round(ADateTimeUtc*TICKS_PER_DAY + OA_ZERO_TICKS);
    Result.dwLowDateTime := li.LowPart;
    Result.dwHighDateTime := li.HighPart;
end;

通过避免SYSTEMTIME,我们避免losing precision in milliseconds.

根据定义,SYSTEMTIME 的 dwMilliseconds 被限制为 1 毫秒的分辨率。

| FILETIME                       | SYSTEMTIME              |
|--------------------------------|-------------------------|
| 100ns resolution               | 1,000,000 ns resolution |
| GetSystemTimeAsFileTime        | GetSystemTime           |
| GetSystemTimePreciseAsFileTime | n/a                     |
|                   -- FileTimeToSystemTime -->            |
|                  <-- SystemTimeToFileTime --             |

你应该避免SYSTEMTIMESYSTEMTIME 的目的是为您将日期/时间解码为其组成部分:

  • 年、月、日、时、分、秒、毫秒

阅读奖励

【讨论】:

  • 你所做的 DateTimeToFileTime 函数正是我想要的。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-23
  • 1970-01-01
  • 2013-11-11
  • 2019-04-25
  • 2011-06-28
相关资源
最近更新 更多