11-21-2017 03:52 AM - edited 11-21-2017 03:56 AM
hello everyone, maybe someone already have a solution to my problem.
in my software i want that the user put an hour and when i reach that hour i have to do something, let's keep it more general possible.
so i have put a numeric cell with hour and another with minute and comparing it with the actual time, but what happen when we reach the DST change time?
let's assume that the user put 02:30 AM (locatime) and the hour increase, i jump from 2:00 AM to 3:00 AM without doing the event.
in the other case, if the hour go back from 3:00 AM to 2:00 AM i do the event 2 time in the same day
i can write in the description to work with UTC time but it's not simple for the user, any suggestion?
i have done some test with this function
MakeDateTime doens't care about DST
29/10/2017 1:59:59 = 3718231199
29/10/2017 2:00:00 = 3718231200
29/10/2017 2:01:00 = 3718231260
29/10/2017 2:30:00 = 3718233000
29/10/2017 3:00:00 = 3718234800
29/10/2017 3:01:00 = 3718234860
29/10/2017 2:00:00 DST
time 3718224000 utc
GetCurrentDateTime 3718231200 localtime
29/10/2017 2:59:00 DST
time 3718227540 utc
GetCurrentDateTime 3718234740 localtime
29/10/2017 2:00:00
time 3718227600 utc
GetCurrentDateTime 3718231200 localtime jump back to the same with DST
thank you
11-21-2017 04:29 AM - edited 11-21-2017 04:42 AM
maybe i got it by myself, it can be useful for other so i post it and please check it and let me know.
char ResponseBuffer[255] = {0}; time_t CurrentCalendarTime = {0}; time_t ReturnedCalendarTime = {0}; time_t CreatedCalendarTime = {0}; struct tm *Time_Pointer = {0}; struct tm Local_Time = {0}; // restituisce l-ora attuale in formato UTC ReturnedCalendarTime = time (&CurrentCalendarTime); // lo visualizzo sprintf(ResponseBuffer, "%u", ReturnedCalendarTime); MessagePopup("time", ResponseBuffer); // lo converto nella struttura tm globale localtime Time_Pointer = localtime (&ReturnedCalendarTime); // lo copio in una struttura tm locale localtime Local_Time = *Time_Pointer; // inserisco l-ora da sostituire PromptPopup("Scegli ora", "inserire da 0 a 23", ResponseBuffer, sizeof(ResponseBuffer) - 1); Local_Time.tm_hour = atoi(ResponseBuffer); // lo scrivo nella struttura tm globale localtime *Time_Pointer = Local_Time; // lo converto in formato time_t UTC CreatedCalendarTime = mktime (Time_Pointer); // lo visualizzo sprintf(ResponseBuffer, "%u", CreatedCalendarTime); MessagePopup("mktime", ResponseBuffer);
in this way when i get the time i know if we are in DST and replacing the hour with the one i want to check is converted correctly in UTC time_t
edit... same problem also here, when the DST change also the returned UTC time_t change and to the same as before
11-21-2017 08:21 AM
This is more a philosophical post, not a direct answer to your question.
If I ask somebody to set the expiration time for an event and he says "Tomorrow at 3 PM", are you assuming that he intends "24 hours from now" or he automatically compensates for DST changeover and effectively wants the event to fire tomorrow at 3 o'clock, local time?
Because in the first case you can detect whether DST changes in between and adapt the target hour accordingly, while in the second case you have to do nothing.
11-21-2017 09:18 AM
i actually want the event at a certain time, not 24 hour from now.
the problem is only in the hour 2-3 AM
11-21-2017 10:46 AM
In this case you can leverage tm_isdst field in tm struct, which should be calculated by time functions; in case the hour is 2 or 3 you can:
Prerequisite for all this is that the computer automatically adjust the clock for DST: there must be a command to query this parameter but I don't seem to remember such an attribute is available in CVI environment, you should search for it in Windows SDK.
11-22-2017 12:54 AM
holly7787 ha scritto:
maybe i got it by myself, it can be useful for other so i post it and please check it and let me know.
char ResponseBuffer[255] = {0}; time_t CurrentCalendarTime = {0}; time_t ReturnedCalendarTime = {0}; time_t CreatedCalendarTime = {0}; struct tm *Time_Pointer = {0}; struct tm Local_Time = {0}; // restituisce l-ora attuale in formato UTC ReturnedCalendarTime = time (&CurrentCalendarTime); // lo visualizzo sprintf(ResponseBuffer, "%u", ReturnedCalendarTime); MessagePopup("time", ResponseBuffer); // lo converto nella struttura tm globale localtime Time_Pointer = localtime (&ReturnedCalendarTime); // lo copio in una struttura tm locale localtime Local_Time = *Time_Pointer; // inserisco l-ora da sostituire PromptPopup("Scegli ora", "inserire da 0 a 23", ResponseBuffer, sizeof(ResponseBuffer) - 1); Local_Time.tm_hour = atoi(ResponseBuffer); // lo scrivo nella struttura tm globale localtime *Time_Pointer = Local_Time; // lo converto in formato time_t UTC CreatedCalendarTime = mktime (Time_Pointer); // lo visualizzo sprintf(ResponseBuffer, "%u", CreatedCalendarTime); MessagePopup("mktime", ResponseBuffer);in this way when i get the time i know if we are in DST and replacing the hour with the one i want to check is converted correctly in UTC time_t
edit... same problem also here, when the DST change also the returned UTC time_t change and to the same as before
so this way is almost correct... i just have to check if the next day will change the DST and so do some calculation.
11-22-2017 01:44 AM - edited 11-22-2017 01:46 AM
@holly7787 wrote:
i actually want the event at a certain time, not 24 hour from now.
the problem is only in the hour 2-3 AM
What to you intend to happen if you chose a time between 2 AM and 3 AM at the day when time switches to DST and the time jumps from 2 AM to 3 AM ?
11-22-2017 02:33 AM
mkossmann ha scritto:
@holly7787 wrote:
i actually want the event at a certain time, not 24 hour from now.
the problem is only in the hour 2-3 AM
What to you intend to happen if you chose a time between 2 AM and 3 AM at the day when time switches to DST and the time jumps from 2 AM to 3 AM ?
i try to explain better.
if you work with localtime and the hour change from non DST to DST at 2:00 AM it will jump to 3:00 AM and if you have an event at 2:30 AM it will be ignored.
if the hour change from DST to non DST at 3:00 AM the hour will go back to 2:00 AM and if you have an event at 2:30 AM it will be processed 2 times.
this doesn't happen if you work with UTC time because it's continously increasing and doesn't consider DST or timezone.
i have done some test and the function MakeDateTime() doesn't care about DST, in this day we have the hour from 2:00 AM to 3:00 AM repeated
29/10/2017 1:59:59 = 3718231199 29/10/2017 2:00:00 = 3718231200 29/10/2017 2:01:00 = 3718231260 29/10/2017 2:30:00 = 3718233000 29/10/2017 3:00:00 = 3718234800 29/10/2017 3:01:00 = 3718234860
this is other test result from the function time() and GetCurrentDateTime()
29/10/2017 2:00:00 DST time 3718224000 utc GetCurrentDateTime 3718231200 localtime 29/10/2017 2:59:00 DST time 3718227540 utc GetCurrentDateTime 3718234740 localtime 29/10/2017 2:00:00 time 3718227600 utc -> correct GetCurrentDateTime 3718231200 localtime -> Repeated
and finally other test with the function mktime() where you can set the parameter isdst
29/10/2017 2:00:00 DST mktime 3718224000 29/10/2017 2:00:00 mktime 3718227600
what i have understand from this is that the only way to deal correctly with time without going crazy is using UTC time, but this is not simple for the end user.
now i want to do some more test with mktime, create some date to test and check the result
11-23-2017 08:16 AM
i have done some test with the function mktime() and this function is great.
if you put the date and time that you want and pass -1 to isdst it will automatically calculate the correct value.
the excpetion 2:00AM - 3:00AM can be handled calculating actual isdst and tomorrow isdst, if this change you can chose what to do, for example delay or anticipate the event 30 minute or do it at the correct time with DST manually set
this is my test code for mktime()
int CVICALLBACK test (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { char ResponseBuffer[255] = {0}; time_t CurrentCalendarTime = {0}; time_t ReturnedCalendarTime = {0}; time_t CreatedCalendarTime = {0}; struct tm *Time_Pointer = {0}; struct tm Local_Time = {0}; switch (event) { case EVENT_COMMIT: // restituisce l-ora attuale in formato UTC ReturnedCalendarTime = time (&CurrentCalendarTime); // lo converto nella struttura tm globale localtime Time_Pointer = localtime (&ReturnedCalendarTime); // inserisco i dati PromptPopup("Scegli secondi", "inserire da 0 a 59", ResponseBuffer, sizeof(ResponseBuffer) - 1); Local_Time.tm_sec = atoi(ResponseBuffer); PromptPopup("Scegli minuti", "inserire da 0 a 59", ResponseBuffer, sizeof(ResponseBuffer) - 1); Local_Time.tm_min = atoi(ResponseBuffer); PromptPopup("Scegli ora", "inserire da 0 a 23", ResponseBuffer, sizeof(ResponseBuffer) - 1); Local_Time.tm_hour = atoi(ResponseBuffer); PromptPopup("Scegli giorno", "inserire da 1 a 31", ResponseBuffer, sizeof(ResponseBuffer) - 1); Local_Time.tm_mday = atoi(ResponseBuffer); PromptPopup("Scegli mese", "inserire da 1 a 12", ResponseBuffer, sizeof(ResponseBuffer) - 1); Local_Time.tm_mon = atoi(ResponseBuffer) - 1; // vanno da 0 a 11 PromptPopup("Scegli anno", "inserire ad esempio 2017", ResponseBuffer, sizeof(ResponseBuffer) - 1); Local_Time.tm_year = atoi(ResponseBuffer) - 1900; // parte dal 1900 quindi 2017 = 117 PromptPopup("Scegli se e' DST", "inserire -1 se non conosciuto, 0 se non DST (inverno), 1 se DST (estate)", ResponseBuffer, sizeof(ResponseBuffer) - 1); Local_Time.tm_isdst = atoi(ResponseBuffer); //Local_Time.tm_wday; // vengono calcolati in automatico //Local_Time.tm_yday; // vengono calcolati in automatico // lo scrivo nella struttura tm globale localtime *Time_Pointer = Local_Time; // lo converto in formato time_t UTC CreatedCalendarTime = mktime (Time_Pointer); // lo visualizzo sprintf(ResponseBuffer, "%u", CreatedCalendarTime); MessagePopup("mktime", ResponseBuffer); } return 0; }