ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# Windows API 中的日期和时间 > 原文: [http://zetcode.com/gui/winapi/datetime/](http://zetcode.com/gui/winapi/datetime/) 在 Windows API 教程的这一部分中,我们将使用日期和时间。 ZetCode 的[文章](http://zetcode.com/articles/cdatetime/)处理 ANSI C 中的日期和时间。 `SYSTEMTIME`结构用于 Windows API 中的日期和时间。 时间可以是协调世界时(UTC)或本地时间。 它具有以下成员: ```c WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds; ``` `SYSTEMTIME`结构用`GetSystemTime()`函数或`GetLocalTime()`函数填充。 然后,我们可以访问结构的成员以获取当前日期或时间。 `FILETIME`结构包含一个 64 位的值,该值表示自 1601 年 1 月 1 日(UTC)起 100 纳秒间隔的数量。 使用此值,我们可以计算 Windows API 纪元或日期时间差。 ```c DWORD dwLowDateTime; DWORD dwHighDateTime; ``` `FILETIME`结构具有两个成员:`dwLowDateTime`是文件时间的低阶部分,`dwHighDateTime`是文件时间的高阶部分。 为了从两个成员中获得单个值,我们利用了`LARGE_INTEGER`并集。 `FileTimeToSystemTime()`和`SystemTimeToFileTime()`函数用于在两个结构之间进行转换。 ## 当地时间 本地时间定义为用户所在时区中的当前时间。 `localtime.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { SYSTEMTIME lt = {0}; GetLocalTime(&lt); wprintf(L"The local time is: %02d:%02d:%02d\n", lt.wHour, lt.wMinute, lt.wSecond); return 0; } ``` 程序将打印本地时间。 ```c SYSTEMTIME lt = {0}; ``` 我们声明`SYSTEMTIME`结构。 通过调用特定的时间函数来填充此结构的成员。 ```c GetLocalTime(&lt); ``` `GetLocalTime()`检索当前的本地日期和时间。 它用当前日期&时间值填充`SYSTEMTIME`结构的成员。 ```c wprintf(L"The local time is: %02d:%02d:%02d\n", lt.wHour, lt.wMinute, lt.wSecond); ``` 我们以`hh:mm:ss`格式打印当前本地时间。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\LocalTime>LocalTime.exe The local time is: 20:20:07 ``` 这是示例输出。 ## UTC 时间 我们的星球是一个球体。 它绕其轴旋转。 地球向东旋转。 因此,太阳在不同位置的不同时间升起。 地球大约每 24 小时旋转一次。 因此,世界被划分为 24 个时区。 在每个时区,都有一个不同的本地时间。 夏令时通常会进一步修改此本地时间。 实际需要一个全球时间。 全球时间可以避免时区和夏令时的混淆。 UTC(世界标准时间)被选为主要时间标准。 UTC 用于航空,天气预报,飞行计划,空中交通管制通关和地图。 与当地时间不同,UTC 不会随季节变化而变化。 Windows API 具有`GetSystemTime()`函数以获取 UTC 时间。 `utctime.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { SYSTEMTIME st = {0}; GetSystemTime(&st); wprintf(L"The UTC time is: %02d:%02d:%02d\n", st.wHour, st.wMinute, st.wSecond); return 0; } ``` 在示例中,我们计算 UTC 时间。 ```c SYSTEMTIME st = {0}; ``` UTC 时间将存储在`SYSTEMTIME`结构中。 ```c GetSystemTime(&st); ``` 我们使用`GetSystemTime()`函数检索 UTC 时间。 ```c wprintf(L"The UTC time is: %02d:%02d:%02d\n", st.wHour, st.wMinute, st.wSecond); ``` UTC 时间以`hh:mm:ss`格式打印到控制台。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\UtcTime>UtcTime.exe The UTC time is: 19:25:20 ``` 这是 UTC 时间的输出。 ## 算术 不建议对`SYSTEMTIME`结构中的值进行算术运算以获得相对时间。 相反,我们将`SYSTEMTIME`结构转换为`FILETIME`结构,将所得的`FILETIME`结构复制到`ULARGE_INTEGER`结构,并对`ULARGE_INTEGER`值使用常规的 64 位算术。 最后,我们将`FILETIME`结构转换回`SYSTEMTIME`结构。 `arithmetic.c` ```c #include <windows.h> #include <wchar.h> #define NSECS 60*60*3 int wmain(void) { SYSTEMTIME st = {0}; FILETIME ft = {0}; GetLocalTime(&st); wprintf(L"%02d/%02d/%04d %02d:%02d:%02d\n", st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond); SystemTimeToFileTime(&st, &ft); ULARGE_INTEGER u = {0}; memcpy(&u, &ft, sizeof(u)); u.QuadPart += NSECS * 10000000LLU; memcpy(&ft, &u, sizeof(ft)); FileTimeToSystemTime(&ft, &st); wprintf(L"%02d/%02d/%04d %02d:%02d:%02d\n", st.wDay, st.wMonth, st.wYear, st.wHour, st.wMinute, st.wSecond); return 0; } ``` 在示例中,我们将三个小时添加到当前本地时间值。 ```c #define NSECS 60*60*3 ``` 三个小时以秒表示。 ```c GetLocalTime(&st); ``` 使用`GetLocalTime()`函数,我们可以获取当前本地时间。 ```c SystemTimeToFileTime(&st, &ft); ``` 我们调用`SystemTimeToFileTime()`函数将`SYSTEMTIME`结构转换为`FILETIME`结构。 ```c ULARGE_INTEGER u = {0}; ``` `ULARGE_INTEGER`结构已创建。 ```c memcpy(&u, &ft, sizeof(u)); u.QuadPart += NSECS * 10000000LLU; memcpy(&ft, &u, sizeof(ft)); ``` 我们向`ULARGE_INTEGER`结构的`QuadPart`成员添加了三个小时。 成员以 100 纳秒刻度表示; 因此,我们将`NSECS`乘以`10000000LLU`。 ```c FileTimeToSystemTime(&ft, &st); ``` 我们将`FILETIME`结构转换回`SYSTEMTIME`结构。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\Arithmetic>Arithmetic.exe 01/02/2016 13:28:13 01/02/2016 16:28:13 ``` 这是`Arithmetic.exe`的示例输出。 已将三个小时正确地添加到当前本地时间。 ## 日期 `GetLocalTime()`函数还用于确定当前日期。 `today.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { SYSTEMTIME st = {0}; GetLocalTime(&st); wprintf(L"Today is: %d-%02d-%02d\n", st.wYear, st.wMonth, st.wDay); return 0; } ``` 上面的程序打印今天的日期。 ```c SYSTEMTIME st = {0}; ``` 我们声明一个`SYSTEMTIME`结构。 ```c GetLocalTime(&st); ``` 我们用当前的本地时间和日期值填充`SYSTEMTIME`成员。 ```c wprintf(L"Today is: %d-%02d-%02d\n", st.wYear, st.wMonth, st.wDay); ``` 当前日期将打印到控制台。 我们选择了公历大端日期格式。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\Today>Today.exe Today is: 2016-01-30 ``` 这是`Today.exe`程序的输出。 ## 格式化日期 `GetDateFormatEx()`函数将日期格式化为指定语言环境的日期字符串。 `date_format.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { PDWORD cChars = NULL; HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE); if (std == INVALID_HANDLE_VALUE) { wprintf(L"Cannot retrieve standard output handle %d\n", GetLastError()); return 1; } SYSTEMTIME lt = {0}; GetLocalTime(&lt); wchar_t buf[128] = {0}; int r = GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_LONGDATE, &lt, NULL, buf, sizeof(buf)/sizeof(buf[0]), NULL); if (r == 0) { wprintf(L"GetDateFormatEx function failed %d\n", GetLastError()); CloseHandle(std); return 1; } WriteConsoleW(std, buf, wcslen(buf), cChars, NULL); r = CloseHandle(std); if (r == 0) { wprintf(L"Cannot close console handle %d\n", GetLastError()); return 1; } CloseHandle(std); return 0; } ``` 程序以本地化格式打印当前本地时间。 ```c SYSTEMTIME lt = {0}; GetLocalTime(&lt); ``` 检索当地时间。 ```c int r = GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_LONGDATE, &lt, NULL, buf, sizeof(buf)/sizeof(buf[0]), NULL); ``` `GetDateFormatEx()`以区域和语言选项中指定的默认语言环境格式化日期。 日期以长日期格式打印。 ```c WriteConsoleW(std, buf, wcslen(buf), cChars, NULL); ``` 日期将打印到控制台。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\DateFormat>DateFormat.exe 1\. februára 2016 ``` 程序以斯洛伐克语打印日期。 ## 确定闰年 闰年是包含额外一天的年份。 日历中额外一天的原因是天文日历年与日历年之间的差异。 日历年正好是 365 天,而天文学年(地球绕太阳公转的时间)是 365.25 天。 相差 6 个小时,这意味着在四年的时间里,我们一天中都没有。 因为我们希望日历与季节同步,所以每四年将 2 月增加一天。 (有例外。)在公历中,February 年的 2 月有 29 天,而不是通常的 28 天。该年持续 366 天,而不是通常的 365 天。 `leapyear.c` ```c #include <windows.h> #include <stdbool.h> #include <wchar.h> bool isLeapYear(int); int wmain(void) { // Assume year >= 1582 in the Gregorian calendar. int years[] = { 2000, 2002, 2004, 2008, 2012, 2016, 2020, 1900, 1800, 1600 }; int size = sizeof(years) / sizeof(int); for (int i=0; i<size; i++) { if (isLeapYear(years[i])) { wprintf(L"%ld is a leap year\n", years[i]); } else { wprintf(L"%ld is not a leap year\n", years[i]); } } return 0; } bool isLeapYear(int year) { if (year % 4 != 0) { return false; } else if (year % 400 == 0) { return true; } else if (year % 100 == 0) { return false; } else { return true; } } ``` 我们有很多年。 我们检查所有年份是否为闰年。 没有内置函数可以检查闰年。 我们创建了一个自定义的`isLeapYear()`函数。 ```c // Assume year >= 1582 in the Gregorian calendar. int years[] = { 2000, 2002, 2004, 2008, 2012, 2016, 2020, 1900, 1800, 1600 }; ``` 这是我们要检查的年份。 年份必须在公历中。 ```c for (int i=0; i<size; i++) { if (isLeapYear(years[i])) { wprintf(L"%ld is a leap year\n", years[i]); } else { wprintf(L"%ld is not a leap year\n", years[i]); } } ``` 使用 for 循环,我们遍历数组。 我们使用`isLeapYear()`函数检查年份是否为闰年。 ```c bool isLeapYear(int year) { if (year % 4 != 0) { return false; } else if (year % 400 == 0) { return true; } else if (year % 100 == 0) { return false; } else { return true; } } ``` 这是确定闰年的功能。 年是 4 的整数倍。年份是 100 的整数倍,则不是闰年,除非它也是 400 的整数倍,在这种情况下,它也是闰年。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\LeapYear>LeapYear.exe 2000 is a leap year 2002 is not a leap year 2004 is a leap year 2008 is a leap year 2012 is a leap year 2016 is a leap year 2020 is a leap year 1900 is not a leap year 1800 is not a leap year 1600 is a leap year ``` `LeapYear.exe`程序的输出。 ## 正常运行时间 `GetTickCount()`函数可用于获取计算机的正常运行时间。 它检索自系统启动以来经过的毫秒数。 ```c DWORD WINAPI GetTickCount(void); ``` 该函数返回`DWORD`值,因此返回的最大天数为 49.7。 为了克服这个限制,我们可以使用`GetTickCount64()`。 从 Windows Vista 开始,该函数可用。 `uptime.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { DWORD tc = GetTickCount(); short seconds = tc / 1000 % 60; short minutes = tc / 1000 / 60 % 60; short hours = tc / 1000 / 60 / 60 % 24; short days = tc / 1000 / 60 / 60 / 24 % 7; short weeks = tc / 1000 / 60 / 60 / 24 / 7 % 52; wprintf(L"Computer has been running for: "); if (weeks > 0 && weeks != 1) { wprintf(L"%hi weeks ", weeks); } else if (weeks == 1) { wprintf(L"1 week "); } if (days > 0 && days != 1) { wprintf(L"%hi days ", days); } else if (days == 1) { wprintf(L"1 day "); } if (hours > 0 && hours != 1) { wprintf(L"%hi hours ", hours); } else if (hours == 1) { wprintf(L"1 hour "); } if (minutes > 0 && minutes != 1) { wprintf(L"%hi minutes ", minutes); } else if (minutes == 1) { wprintf(L"1 minute "); } wprintf(L"and %hi seconds\n", seconds); return 0; } ``` 该程序将打印计算机的正常运行时间。 我们使用`GetTickCount()`函数。 如果计算机运行的时间少于 49.71 天或 4294967296 ms,它将正常工作。 之后,`DWORD`值溢出。 ```c DWORD tc = GetTickCount(); ``` 我们得到计算机正在运行的毫秒数。 `DWORD`变量可以存储的最大数量为`ULONG_MAX`。 ```c short seconds = tc / 1000 % 60; short minutes = tc / 1000 / 60 % 60; short hours = tc / 1000 / 60 / 60 % 24; short days = tc / 1000 / 60 / 60 / 24 % 7; short weeks = tc / 1000 / 60 / 60 / 24 / 7 % 52; ``` 我们计算秒,分钟,小时,天和周。 ```c if (weeks > 0 && weeks != 1) { wprintf(L"%hi weeks ", weeks); } else if (weeks == 1) { wprintf(L"1 week "); } ``` 如果计算机正在运行一个或多个星期,则可以在控制台上打印`week`变量或`"1 week"`字符串。 ```c C:\winapi\examples2\datetime\Uptime>Uptime.exe Computer has been running for: 3 hours 31 minutes and 7 seconds ``` 样本输出。 ## 星期几 `SYSTEMTIME`结构的`wDayOfWeek`成员存储星期几。 值是`1..7`,其中 1 是星期日,2 星期一,... 7 星期六。 `dayofweek.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { SYSTEMTIME st = {0}; wchar_t *dn[] = { L"Sunday", L"Monday", L"Tuesday", L"Wednesday", L"Thursday", L"Friday", L"Saturday" }; GetLocalTime(&st); wprintf(L"Today is %ls\n", dn[st.wDayOfWeek]); return 0; } ``` 该代码将星期几显示在控制台上。 ```c wchar_t *dn[] = { L"Sunday", L"Monday", L"Tuesday", L"Wednesday", L"Thursday", L"Friday", L"Saturday" }; ``` 我们将日期名称存储在字符串数组中。 ```c GetLocalTime(&st); wprintf(L"Today is %ls\n", dn[st.wDayOfWeek]); ``` 这些行检索并打印星期几。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\DayOfWeek>DayOfWeek.exe Today is Sunday ``` 这是输出。 ## 纪元 纪元是选择作为特定纪元起源的时间瞬间。 例如,在西方基督教国家,时期从耶稣出生(据信出生)的第 0 天开始。 另一个例子是法国共和党日历,使用了十二年。 这个时期是 1792 年 9 月 22 日宣布的共和纪元的开始,即宣布成立第一共和国并废除君主制的那一天。 电脑也有自己的纪元。 最受欢迎的时间之一是 Unix 时间。 Unix 纪元是 1970 年 1 月 1 日 UTC 时间 00:00:00(或`1970-01-01T00:00:00Z ISO8601`)。 计算机中的日期和时间是根据自该计算机或平台的定义时期以来经过的秒数或时钟滴答数确定的。 Windows 操作系统有几个时期。 Microsoft Excel,MS SQL Server 或 FAT32 文件系统具有不同的时间纪元。 Windows API 纪元是 UTC 1601 年 1 月 1 日 00:00:00。 选择此日期的原因是接受公历 400 周年。 周年纪念日是在 Windows NT 设计之初。 `FILETIME`结构包含一个 64 位的值,该值表示自 1601 年 1 月 1 日(UTC)起 100 纳秒间隔的数量。 `windows_epoch.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { FILETIME ft = {0}; GetSystemTimeAsFileTime(&ft); LARGE_INTEGER li = {0}; li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; long long int hns = li.QuadPart; wprintf(L"%lli hundreds of nanoseconds have elapsed " "since Windows API epoch\n", hns); return 0; } ``` 该代码示例计算从 Windows API 纪元到现在为止经过的 100 纳秒间隔的数量。 ```c FILETIME ft = {0}; ``` 我们声明`FILETIME`结构。 它有两个成员。 `dwLowDateTime`保留文件时间的低位部分。 `dwHighDateTime`保留文件时间的高位部分。 ```c LARGE_INTEGER li = {0}; ``` `LARGE_INTEGER`是一个联合,可帮助我们将`FILETIME`结构的成员转换为 100 纳秒的间隔。 ```c li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; ``` `FILETIME`结构的值将复制到大整数联合成员。 ```c long long int hns = li.QuadPart; ``` `QuadPart`成员存储从`LowPart`和`HighPart`成员确定的数百纳秒数。 它是一个巨大的数字,存储为 64 位整数。 ```c wprintf(L"%lli hundreds of nanoseconds have elapsed " "since Windows API epoch\n", hns); ``` 该值将打印到控制台。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\WindowsEpoch>WindowsEpoch.exe 130987330019489987 hundreds of nanoseconds have elapsed since Windows API epoch ``` 这是示例输出。 以下示例将 Windows API 时间转换为 Unix 时间。 `unix_time.c` ```c #include <windows.h> #include <wchar.h> #define WINDOWS_TICKS_PER_SEC 10000000 #define EPOCH_DIFFERENCE 11644473600LL long long WindowsTicksToUnixSeconds(long long); int wmain(void) { FILETIME ft = {0}; GetSystemTimeAsFileTime(&ft); LARGE_INTEGER li = {0}; li.LowPart = ft.dwLowDateTime; li.HighPart = ft.dwHighDateTime; long long int hns = li.QuadPart; wprintf(L"Windows API time: %lli\n", hns); long long int utm = WindowsTicksToUnixSeconds(hns); wprintf(L"Unix time: %lli\n", utm); return 0; } long long int WindowsTicksToUnixSeconds(long long windowsTicks) { return (windowsTicks / WINDOWS_TICKS_PER_SEC - EPOCH_DIFFERENCE); } ``` 该示例显示 Windows API 时间和 Unix 控制台时间。 ```c #define EPOCH_DIFFERENCE 11644473600LL ``` 两个时期之间的差是`11644473600LL`。 请注意,闰秒是 1972 年引入的,因此我们没有将它们考虑在内。 ```c long long int WindowsTicksToUnixSeconds(long long windowsTicks) { return (windowsTicks / WINDOWS_TICKS_PER_SEC - EPOCH_DIFFERENCE); } ``` 该函数将 Windows 刻度转换为 Unix 时间秒。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\UnixTime>UnixTime.exe Windows API time: 130987431026414297 Unix time: 1454269502 ``` 这是`UnixTime.exe`示例的输出。 ## 直到 XMas 的天数 Windows API 没有任何函数来计算两天之间的差异。 我们必须自己做数学。 `days_to_xmas.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { FILETIME ft1 = {0}; FILETIME ft2 = {0}; SYSTEMTIME st = {0}; LARGE_INTEGER li1 = {0}; LARGE_INTEGER li2 = {0}; st.wYear = 2016; st.wMonth = 12; st.wDay = 25; int r = SystemTimeToFileTime(&st, &ft1); if (r == 0) { wprintf(L"Failed to convert system time to file time\n (%d)", GetLastError()); return 1; } GetSystemTimeAsFileTime(&ft2); li1.LowPart = ft1.dwLowDateTime; li1.HighPart = ft1.dwHighDateTime; li2.LowPart = ft2.dwLowDateTime; li2.HighPart = ft2.dwHighDateTime; long long int dif = li1.QuadPart - li2.QuadPart; int days2xmas = dif / 10000000L / 60 / 60 / 24; if (days2xmas == 1) { wprintf(L"There is one day until Christmas\n", days2xmas); } else if (days2xmas == 0) { wprintf(L"Today is Chritmas\n"); } else { wprintf(L"There are %d days until Christmas\n", days2xmas); } return 0; } ``` 该代码示例计算直到圣诞节的天数。 ```c FILETIME ft1 = {0}; FILETIME ft2 = {0}; SYSTEMTIME st = {0}; LARGE_INTEGER li1 = {0}; LARGE_INTEGER li2 = {0}; ``` 我们需要`FILETIME`,`SYSTEMTIME`结构和`LARGE_INTEGER`并集来进行计算。 ```c st.wYear = 2016; st.wMonth = 12; st.wDay = 25; ``` `SYSTEMTIME`结构填充了圣诞节的值。 ```c int r = SystemTimeToFileTime(&st, &ft1); ``` 圣诞节的系统时间将转换为文件时间。 ```c GetSystemTimeAsFileTime(&ft2); ``` 我们使用`GetSystemTimeAsFileTime()`函数将当前日期作为文件时间。 ```c li1.LowPart = ft1.dwLowDateTime; li1.HighPart = ft1.dwHighDateTime; li2.LowPart = ft2.dwLowDateTime; li2.HighPart = ft2.dwHighDateTime; ``` 我们用文件时间的低位和高位部分填充两个并集。 ```c long long int dif = li1.QuadPart - li2.QuadPart; ``` 计算两个日期之间的差。 ```c int days2xmas = dif / 10000000L / 60 / 60 / 24; ``` 差异以 100 纳秒表示。 此值转换为天。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\DaysToXmas>DaysToXmas.exe There are 328 days until Christmas ``` 在 2016 年 1 月 31 日,我们获得了此输出。 ## 比较时间 `CompareFileTime()`函数可用于比较两个文件时间。 当指定的第一次时间较早时,该函数返回 -1。 当两次相等时,它返回 0。 当第一次晚于第二个文件时间时,它将返回 1。 `compare_time.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { SYSTEMTIME st1 = {0}; SYSTEMTIME st2 = {0}; FILETIME ft1 = {0}; FILETIME ft2 = {0}; st1.wYear = 2015; st1.wMonth = 4; st1.wDay = 12; st2.wYear = 2015; st2.wMonth = 5; st2.wDay = 12; int r1 = SystemTimeToFileTime(&st1, &ft1); if (r1 == 0) { wprintf(L"Failed to convert system time to file time\n (%d)", GetLastError()); return 1; } int r2 = SystemTimeToFileTime(&st2, &ft2); if (r2 == 0) { wprintf(L"Failed to convert system time to file time\n (%d)", GetLastError()); return 1; } short ct = CompareFileTime(&ft1, &ft2); if (ct == -1) { wprintf(L"4/12/2015 comes before 5/12/2015\n"); } else if (ct == 0) { wprintf(L"4/12/2015 is equal to 5/12/2015\n"); } else if (ct == 1) { wprintf(L"4/12/2015 comes after 5/12/2015\n"); } return 0; } ``` 我们有两个时间值。 我们使用`CompareFileTime()`来确定哪个时间更早。 ```c st1.wYear = 2015; st1.wMonth = 4; st1.wDay = 12; st2.wYear = 2015; st2.wMonth = 5; st2.wDay = 12; ``` 两次定义。 ```c int r1 = SystemTimeToFileTime(&st1, &ft1); if (r1 == 0) { wprintf(L"Failed to convert system time to file time\n (%d)", GetLastError()); return 1; } int r2 = SystemTimeToFileTime(&st2, &ft2); if (r2 == 0) { wprintf(L"Failed to convert system time to file time\n (%d)", GetLastError()); return 1; } ``` 使用`SystemTimeToFileTime()`函数调用将系统时间转换为文件时间。 ```c short ct = CompareFileTime(&ft1, &ft2); ``` 将两个文件时间与`CompareFileTime()`函数进行比较。 ```c if (ct == -1) { wprintf(L"4/12/2015 comes before 5/12/2015\n"); } else if (ct == 0) { wprintf(L"4/12/2015 is equal to 5/12/2015\n"); } else if (ct == 1) { wprintf(L"4/12/2015 comes after 5/12/2015\n"); } ``` 根据返回的值,我们将消息打印到控制台。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\CompareTime>CompareTime.exe 4/12/2015 comes before 5/12/2015 ``` 这是`CompareTime.exe`程序的输出。 ## 时区 时区是一个使用相同标准时间的区域。 世界上有 24 个时区。 ```c UTC = local time + bias ``` 偏差是 UTC 时间与本地时间之间的差异(以分钟为单位)。 ### 检索时区 `GetTimeZoneInformation()`用于获取时区信息。 信息存储在`TIME_ZONE_INFORMATION`结构中。 `get_time_zone.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { TIME_ZONE_INFORMATION tzi = {0}; int r = GetTimeZoneInformation(&tzi); if (r == TIME_ZONE_ID_INVALID) { wprintf(L"Failed to get time zone %d", GetLastError()); return 1; } wprintf(L"Time zone: %ls\n", tzi.StandardName); wprintf(L"The bias is: %ld minutes\n", tzi.Bias); return 0; } ``` 该示例显示用户的时区。 ```c TIME_ZONE_INFORMATION tzi = {0}; ``` `TIME_ZONE_INFORMATION`结构存储时区的设置。 ```c int r = GetTimeZoneInformation(&tzi); ``` `GetTimeZoneInformation()`函数检索当前时区设置。 ```c wprintf(L"Time zone: %ls\n", tzi.StandardName); ``` `TIME_ZONE_INFORMATION`结构的`StandardName`成员存储我们时区的名称。 ```c wprintf(L"The bias is: %ld minutes\n", tzi.Bias); ``` 我们打印偏差值。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\GetTimeZone>GetTimeZone.exe Time zone: Central Europe Standard Time The bias is: -60 minutes ``` 我们的时区是中欧标准时间(CEST),偏差是 -60 分钟。 ### 将当地时间转换为世界时间 `TzSpecificLocalTimeToSystemTime()`函数将本地时间转换为 UTC 时间。 该函数考虑了夏令时(DST)对于要转换的当地时间是否有效。 `localtime_to_universaltime.c` ```c #include <windows.h> #include <wchar.h> int wmain(void) { SYSTEMTIME lt = {0}; GetLocalTime(&lt); TIME_ZONE_INFORMATION tzi = {0}; GetTimeZoneInformation(&tzi); SYSTEMTIME utm = {0}; int r = TzSpecificLocalTimeToSystemTime(&tzi, &lt, &utm); if (r == 0) { wprintf(L"Failed to convert local time to system time %d\n)", GetLastError()); return 1; } wprintf(L"Date: %d/%d/%d\n", lt.wMonth, lt.wDay, lt.wYear); wprintf(L"The local time is: %02d:%02d:%02d\n", lt.wHour, lt.wMinute, lt.wSecond); wprintf(L"The universal time is: %02d:%02d:%02d\n", utm.wHour, utm.wMinute, utm.wSecond); return 0; } ``` 该示例将本地时间转换为世界时间。 ```c SYSTEMTIME lt = {0}; GetLocalTime(&lt); ``` 当前的本地时间通过`GetLocalTime()`函数获取。 ```c TIME_ZONE_INFORMATION tzi = {0}; GetTimeZoneInformation(&tzi); ``` 时区设置由`GetTimeZoneInformation()`函数确定。 ```c int r = TzSpecificLocalTimeToSystemTime(&tzi, &lt, &utm); ``` `TzSpecificLocalTimeToSystemTime()`将夏令时考虑在内,将当地时间转换为世界时间。 ```c wprintf(L"The local time is: %02d:%02d:%02d\n", lt.wHour, lt.wMinute, lt.wSecond); ``` 将本地时间打印到控制台。 ```c wprintf(L"The universal time is: %02d:%02d:%02d\n", utm.wHour, utm.wMinute, utm.wSecond); ``` 世界时间打印到控制台。 ```c C:\Users\Jano\Documents\Pelles C Projects\timedate\LocalTimeToUniversalTime>LocalTimeToUniversalTime.exe Date: 2/1/2016 The local time is: 11:39:48 The universal time is: 10:39:48 ``` 在 2016 年 2 月 1 日的 CEST 时区,我们得到了上述输出。 在 Windows API 教程的这一部分中,我们使用日期&时间。