【问题标题】:Arithmetic and comparison with ctime library data type time_t算术和与 ctime 库数据类型 time_t 的比较
【发布时间】:2015-01-12 22:36:11
【问题描述】:

我正在尝试使用 ctime 库在 C++ 中实现我自己的小型闹钟桌面应用程序。起初看起来很容易,但我遇到了几个意想不到的问题,这些问题同样出乎意料地消失了。现在我的 time_t 变量 timeAlarm 没有被正确初始化。 由于 time_t 就像一个时间戳,表示自 00:00:00 1.1.1970 以来经过的秒数,并且在 ctime 库中声明为 long(有符号整数类型),因此我将 timeAlarm 初始化为 22 点(晚上 10 点) ) 为(time_t)(22*60*60)

但是,当我通过strftime() 将带有SetWindowText() 的静态窗口文本设置为timeAlarm 时,它总是输出“01:00:00”。 “剩余时间”的下一个午夜为零时间。

那么我是错误地初始化了timeAlarm,还是出于错误的目的使用了difftime?可能出了什么问题?

以下是应用程序显示的图片:

以下是全部代码

#include <windows.h>
#include <ctime>
#include <string>
#include "resources.h"

HWND hwndMain;
HWND hwndTimeNow;
    time_t timeNow;
HWND hwndTimeAlarm;
    time_t timeAlarm;
HWND hwndTimeRemaining;
    time_t timeRemaining;
UINT_PTR timerID;

// Converts time_t to std::string
std::string time_tToStr(time_t * ptr){
    char timeString[16];
    strftime(timeString,sizeof(timeString),"%X",localtime(ptr));
    return timeString;
};

// Sets window text to time string from time_t value
void time_tToWindowText(HWND hwnd, time_t * ptr){
    SetWindowText(hwnd,time_tToStr(ptr).c_str());
};

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
    switch(Message) {
        case WM_CREATE: {
            // Present time
            CreateWindow("STATIC", "Zeit", WS_CHILD | WS_VISIBLE, 10, 10, 100, 15, hwnd, NULL, NULL, NULL);
            hwndTimeNow = CreateWindow("STATIC", NULL, WS_CHILD | WS_VISIBLE, 120, 10, 200, 15, hwnd, NULL, NULL, NULL);
            // Alarm time
            CreateWindow("STATIC", "Alarmzeit", WS_CHILD | WS_VISIBLE, 10, 35, 100, 15, hwnd, NULL, NULL, NULL);
            hwndTimeAlarm = CreateWindow("STATIC", NULL, WS_CHILD | WS_VISIBLE, 120, 35, 200, 15, hwnd, NULL, NULL, NULL);
            time_tToWindowText(hwndTimeAlarm,&timeAlarm);
            // Remaining time
            CreateWindow("STATIC", "Countdown", WS_CHILD | WS_VISIBLE, 10, 60, 100, 15, hwnd, NULL, NULL, NULL);
            hwndTimeRemaining = CreateWindow("STATIC", NULL, WS_CHILD | WS_VISIBLE, 120, 60, 200, 15, hwnd, NULL, NULL, NULL);
            break;
        }
        case WM_TIMER: { // Runs once a second

            timeNow = time(NULL);
            timeNow = (time_t)(timeNow%(60*60*24)); // Get only daytime
            time_tToWindowText(hwndTimeNow,&timeNow);

            timeRemaining = (time_t)difftime(timeAlarm, timeNow);
            time_tToWindowText(hwndTimeRemaining,&timeRemaining);

            if (timeRemaining <= 0){
                int ans = MessageBox(hwndMain, "22:00:00 - Alarm time reached.", "Alarm", MB_OK|MB_ICONINFORMATION);
                PostQuitMessage(0);
                break;
            }
            else
                timerID = SetTimer(hwndMain, 0, 1000, NULL);

            break;
        }
        case WM_DESTROY: {
            KillTimer(hwnd,timerID);
            PostQuitMessage(0);
            break;
        }
        default:
            return DefWindowProc(hwnd, Message, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    MSG Msg;

    memset(&wc,0,sizeof(wc));
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.lpfnWndProc   = WndProc;
    wc.hInstance     = hInstance;
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);

    wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND);
    wc.lpszClassName = "WindowClass";
    wc.hIcon         = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MAINICON));
    wc.hIconSm       = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MAINICON), IMAGE_ICON, 16, 16, 0);

    if (!RegisterClassEx(&wc)) {
        MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
        return 0;
    }

    hwndMain = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Heia",WS_VISIBLE|WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        350,
        150,
        NULL,NULL,hInstance,NULL);

    if (hwndMain == NULL) {
        MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
        return 0;
    }

    timeAlarm = (time_t)(22*60*60); // Set alarm time to 22 o'clock (10 pm)
    PostMessage(hwndMain, WM_TIMER,0,0); // Kick off timer loop

    while (GetMessage(&Msg, NULL, 0, 0) > 0) { 
        TranslateMessage(&Msg); 
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

【问题讨论】:

  • 您确定&lt;ctime&gt; 标头将time_t 定义为double?它通常是一些有符号整数类型。 C 标准只要求它是算术类型(C++ 标准继承了该要求)。
  • 定义为long。我在想这和double 一样,但正如你所说,它是一个有符号整数类型。感谢您的提示。
  • 请注意,difftime 函数接受两个 time_t 类型的参数并返回 double 类型的结果。
  • 是的,我将返回值从 difftime() 转换为 time_t
  • 这样的转换是否有意义取决于您需要代码的可移植性。 C 标准只保证time_t 是一种能够表示时间的算术类型;它没有说它如何代表时间。这些信息不足以确定两个time_t 值之间的秒数,这就是difftime() 存在的原因。如果您能够假设 time_t 是自 1970 年以来的秒数,您可以直接减去 time_t 值。如果你不能假设,将difftime() 的结果转换为time_t 值可能没有意义。

标签: c++ ctime


【解决方案1】:

localtime 应用时区校正,假设您输入的时间是 UTC。您处于 UTC+1 时区,因此会增加一小时。

当前时间没问题,因为time 也适用于 UTC。在您的示例中,UTC 时间应为 17:11:00。

显示的警报时间是错误的,因为您直到在 WM_CREATE 处理程序中设置文本之后才将其初始化为 22:00。显然它初始化为 0,当你添加一个小时时,它是 01:00。

22:00:00 和 17:11:00 之间的时间差是 4:49:00。时区调整加一小时,现在是 5:59。

如果您不想在每次转化时应用时区调整,您应该使用gmtime 而不是localtime

【讨论】:

    猜你喜欢
    • 2023-03-26
    • 2010-12-16
    • 2016-04-25
    • 2012-02-16
    • 1970-01-01
    • 2014-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多