diff --git a/sdk/core/azure-core/inc/azure/core/datetime.hpp b/sdk/core/azure-core/inc/azure/core/datetime.hpp index 4ed531473c..53eecb5f9f 100644 --- a/sdk/core/azure-core/inc/azure/core/datetime.hpp +++ b/sdk/core/azure-core/inc/azure/core/datetime.hpp @@ -269,7 +269,7 @@ inline bool operator>=(std::chrono::system_clock::time_point const& tp, DateTime namespace Core { namespace _internal { /** - * @brief Provides convertion methods for POSIX time to an #Azure::DateTime. + * @brief Provides conversion methods for POSIX time to an #Azure::DateTime. * */ class PosixTimeConverter final { @@ -311,6 +311,51 @@ namespace Core { namespace _internal { */ ~PosixTimeConverter() = delete; }; + + /** + * @brief Provides conversion methods for Win32 FILETIME to an #Azure::DateTime. + * + */ + class Win32FileTimeConverter final { + public: + /** + * @brief Converts Win32 FILETIME to an #Azure::DateTime. + * + * @param win32Filetime The number of 100-nanoseconds since 1601-01-01. + * @return Calculated #Azure::DateTime. + */ + static DateTime Win32FileTimeToDateTime(int64_t win32Filetime) + { + auto t = DateTime(1601) + Azure::_detail::Clock::duration(win32Filetime); + return DateTime(t); + } + + /** + * @brief Converts a DateTime to Win32 FILETIME. + * + * @param dateTime The `%DateTime` to convert. + * @return The number of 100-nanoseconds since 1601-01-01. + */ + static int64_t DateTimeToWin32FileTime(DateTime const& dateTime) + { + return std::chrono::duration_cast(dateTime - DateTime(1601)) + .count(); + } + + private: + /** + * @brief An instance of `%Win32FileTimeConverter` class cannot be created. + * + */ + Win32FileTimeConverter() = delete; + + /** + * @brief An instance of `%Win32FileTimeConverter` class cannot be destructed, because no + * instance can be created. + * + */ + ~Win32FileTimeConverter() = delete; + }; }} // namespace Core::_internal } // namespace Azure diff --git a/sdk/core/azure-core/test/ut/datetime_test.cpp b/sdk/core/azure-core/test/ut/datetime_test.cpp index 2496819925..02534134f2 100644 --- a/sdk/core/azure-core/test/ut/datetime_test.cpp +++ b/sdk/core/azure-core/test/ut/datetime_test.cpp @@ -895,3 +895,44 @@ TEST(DateTime, LeapYear) EXPECT_NO_THROW(static_cast(DateTime(2021, 2, 28))); EXPECT_THROW(static_cast(DateTime(2021, 2, 29)), std::invalid_argument); } + +TEST(DateTime, Win32FileTimeConverter) +{ + using namespace Azure::Core::_internal; + + EXPECT_EQ( + Win32FileTimeConverter::DateTimeToWin32FileTime( + Win32FileTimeConverter::Win32FileTimeToDateTime(0)), + 0); + EXPECT_EQ( + Win32FileTimeConverter::DateTimeToWin32FileTime( + Win32FileTimeConverter::Win32FileTimeToDateTime(1)), + 1); + EXPECT_EQ( + Win32FileTimeConverter::DateTimeToWin32FileTime( + Win32FileTimeConverter::Win32FileTimeToDateTime(133080315699856412)), + 133080315699856412); + EXPECT_EQ( + Win32FileTimeConverter::DateTimeToWin32FileTime( + Win32FileTimeConverter::Win32FileTimeToDateTime(2650467743995784569)), + 2650467743995784569); + + EXPECT_EQ( + Win32FileTimeConverter::Win32FileTimeToDateTime(0).ToString( + Azure::DateTime::DateFormat::Rfc3339, Azure::DateTime::TimeFractionFormat::AllDigits), + "1601-01-01T00:00:00.0000000Z"); + EXPECT_EQ( + Win32FileTimeConverter::Win32FileTimeToDateTime(1).ToString( + Azure::DateTime::DateFormat::Rfc3339, Azure::DateTime::TimeFractionFormat::AllDigits), + "1601-01-01T00:00:00.0000001Z"); + EXPECT_EQ( + Win32FileTimeConverter::Win32FileTimeToDateTime(133080315699856412) + .ToString( + Azure::DateTime::DateFormat::Rfc3339, Azure::DateTime::TimeFractionFormat::AllDigits), + "2022-09-19T03:26:09.9856412Z"); + EXPECT_EQ( + Win32FileTimeConverter::Win32FileTimeToDateTime(2650467743995784569) + .ToString( + Azure::DateTime::DateFormat::Rfc3339, Azure::DateTime::TimeFractionFormat::AllDigits), + "9999-12-31T23:59:59.5784569Z"); +}