LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Handle a time event correctly when Daylight saving time change

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

Davide Vittorio G. - TLGB S.R.L.
Italian SW Developer
0 Kudos
Message 1 of 9
(3,034 Views)

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

 

 

Davide Vittorio G. - TLGB S.R.L.
Italian SW Developer
0 Kudos
Message 2 of 9
(3,019 Views)

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.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 3 of 9
(3,004 Views)

i actually want the event at a certain time, not 24 hour from now.

the problem is only in the hour 2-3 AM

Davide Vittorio G. - TLGB S.R.L.
Italian SW Developer
0 Kudos
Message 4 of 9
(3,001 Views)

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:

  • Calculate present time DST flag
  • Calculate target time DST flag
  • If different, accomodate target hour properly

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.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 5 of 9
(2,996 Views)

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.

 

Davide Vittorio G. - TLGB S.R.L.
Italian SW Developer
0 Kudos
Message 6 of 9
(2,986 Views)

@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 ?

0 Kudos
Message 7 of 9
(2,983 Views)

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

Davide Vittorio G. - TLGB S.R.L.
Italian SW Developer
0 Kudos
Message 8 of 9
(2,978 Views)

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;
}

 

Davide Vittorio G. - TLGB S.R.L.
Italian SW Developer
0 Kudos
Message 9 of 9
(2,958 Views)