微软的 WinUI3 C++/WinRT 版本的 DateTime 有问题

微软的 WinUI3 C++/WinRT 版本的 DateTime 有问题


下面的代码功能很简单,遍历 C:\users\<username>\local\notes 文件夹中的所有文件,读取每个文件的内容和创建时间。问题出在把获取到的文件创建时间转换为字符串时。

当把获取到的文件创建时间转换为字符串时,用 C++/WinRT 提供的方法,总比用 Windows 原生 API 提供的方法 1 秒或 2 秒。

// 这是 C++/WinRT 方法:
 wchar_t buf[128]{};
 struct tm atm;
 __time64_t tim64{winrt::clock::to_time_t((*it).DateCreated())};
 _localtime64_s(&atm, &tim64);
 size_t length{wcsftime(buf, std::size(buf), L"%x %X", &atm)};
// 这是 Windows 原生 API 方法:
 WIN32_FILE_ATTRIBUTE_DATA wfad{};
        GetFileAttributesExW(path.c_str(), GetFileExInfoStandard, &wfad);
        SYSTEMTIME system_time{};
        FILETIME local_file_time{};
        FileTimeToLocalFileTime(&wfad.ftCreationTime, &local_file_time);
        FileTimeToSystemTime(&local_file_time, &system_time);
 
        (void)_snwprintf_s(&buf[length], std::size(buf) - length,
                           _countof(buf) - length - 1,
                           L"\r\n%hu-%hu-%hu %hu:%hu:%hu", system_time.wYear,
                           system_time.wMonth, system_time.wDay,
                           system_time.wHour, system_time.wMinute,
                           system_time.wSecond);

下面是完整的代码:

winrt::Windows::Foundation::IAsyncAction
NoteViewModel::GetFilesInFolderAsync()
{
    _wsetlocale(LC_ALL, L"");
  winrt::Windows::Storage::StorageFolder storage_folder{nullptr};
  storage_folder
    = co_await winrt::Windows::Storage::StorageFolder::GetFolderFromPathAsync(
      m_storage_folder);

  winrt::Windows::Foundation::Collections::IVectorView<
    winrt::Windows::Storage::IStorageItem>
    storage_items;

  storage_items = co_await storage_folder.GetItemsAsync();

  for (winrt::impl::fast_iterator<
         winrt::Windows::Foundation::Collections::IVectorView<
           winrt::Windows::Storage::IStorageItem>>
         it{storage_items.begin()};
       it != storage_items.end();
       ++it) {
    winrt::WinUI3DefaultIcon::Note note{
      winrt::make<winrt::WinUI3DefaultIcon::implementation::Note>(
        L"这是书名")};
    note.set_storage_folder(m_storage_folder);
    // 这个无所谓,后面会把这个名字覆盖掉。
    note.FileName((*it).Name());
    note.set_added_date_time((*it).DateCreated());
    {
      wchar_t buf[128]{};
      struct tm atm;
      __time64_t tim64{winrt::clock::to_time_t((*it).DateCreated())};
      _localtime64_s(&atm, &tim64);
      size_t length{wcsftime(buf, std::size(buf), L"%x %X", &atm)};

      std::wstring path{m_storage_folder + LR"raw(\)raw"};
      path += (*it).Name().c_str();

      WIN32_FILE_ATTRIBUTE_DATA wfad{};
      GetFileAttributesExW(path.c_str(), GetFileExInfoStandard, &wfad);
      SYSTEMTIME system_time{};
      FILETIME local_file_time{};
      FileTimeToLocalFileTime(&wfad.ftCreationTime, &local_file_time);
      FileTimeToSystemTime(&local_file_time, &system_time);
 
      (void)_snwprintf_s(&buf[length], std::size(buf) - length,
                         _countof(buf) - length - 1,
                         L"\r\n%hu-%hu-%hu %hu:%hu:%hu", system_time.wYear,
                         system_time.wMonth, system_time.wDay,
                         system_time.wHour, system_time.wMinute,
                         system_time.wSecond);

      MessageBoxW(MainWindow::hwnd, buf, buf, MB_OK);
    }
    co_await note.LoadNoteAsync();
    m_many_notes.Append(note);
  }
}

下面是个运行结果:
这是测试结果
可以看到,同样的文件创建时间,C++/WinRT 转换后的时间,比 Windows 原生 API 快了一秒。我估计问题出在 winrt::Windows::Foundation::DateTimewinrt::clock::to_time_t上。

下面是其代码:

WINRT_EXPORT namespace winrt::Windows::Foundation
{
    using TimeSpan = std::chrono::duration<int64_t, impl::filetime_period>;
    using DateTime = std::chrono::time_point<clock, TimeSpan>;
}
WINRT_EXPORT namespace winrt
{

    struct clock
    {
    ...
         using time_point = Windows::Foundation::DateTime;
    ...
    }
static time_t to_time_t(time_point const& time) noexcept
{
    return static_cast<time_t>(std::chrono::system_clock::to_time_t(std::chrono::time_point_cast<std::chrono::system_clock::duration>(to_sys(time))));
}

但是我先不去分析具体问题了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dowhileprogramming

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值