Calculating the difference between two dates or timestamps
Let’s say that you have to determine the difference between two dates (represented as strings) and express the result in seconds (which could be positive or negative). How would you do this in VuGen?
Being a smart person who is not interested in reinventing the wheel, you would look first to the functions that are available to you in VuGen.
You could read the values from your time/date string using sscanf, which extracts values from a formatted string.
1 | sscanf("02/10/2009 14:49:41", "%d/%d/%d %d:%d:%d", month, day, year, hour, min, sec); |
You could then save these values to a special “calendar time” structure defined in the time.h standard C library.
1 2 3 4 5 6 7 8 9 10 11 | struct tm { int tm_sec; // seconds after the minute - [0,59] int tm_min; // minutes after the hour - [0,59] int tm_hour; // hours since midnight - [0,23] int tm_mday; // day of the month - [1,31] int tm_mon; // months since January - [0,11] int tm_year; // years since 1900 int tm_wday; // days since Sunday - [0,6] int tm_yday; // days since January 1 - [0,365] int tm_isdst; // daylight savings time flag }; |
Once the date/timestamp is in the required format, it could be easily converted to a Unix timestamp by using the mktime() function, which is also in time.h.
Here is the example code…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | Action() { // The "calendar time" structure has the following members struct tm { int tm_sec; // seconds after the minute - [0,59] int tm_min; // minutes after the hour - [0,59] int tm_hour; // hours since midnight - [0,23] int tm_mday; // day of the month - [1,31] int tm_mon; // months since January - [0,11] int tm_year; // years since 1900 int tm_wday; // days since Sunday - [0,6] int tm_yday; // days since January 1 - [0,365] int tm_isdst; // daylight savings time flag }; int rc; // return code struct tm date1; struct tm date2; long time_difference; // the number of time ticks (seconds) that separate date1 and date2. int days, hours, minutes, seconds; // Save example dates to a parameter. In real life, you might // capture these values using web_reg_save_param or similar. // date format: mm/dd/yyyy hh:mm:ss lr_save_string("02/10/2009 14:49:41", "Param_Date1"); lr_save_string("02/11/2009 15:50:42", "Param_Date2"); // Read the values from the string into the date variables rc = sscanf(lr_eval_string("{Param_Date1}"), "%d/%d/%d %d:%d:%d", &date1.tm_mon, &date1.tm_mday, &date1.tm_year, &date1.tm_hour, &date1.tm_min, &date1.tm_sec); if (rc != 6) { lr_error_message("Problem reading date format. Expected 6 values in string, but found %d", rc); lr_abort(); } // As the "calendar time" structure defines tm_year as "years since 1900" and // tm_mon as "months since January", we must "fix" these values in the structure. date1.tm_mon = date1.tm_mon - 1; date1.tm_year = date1.tm_year - 1900; // Repeat the above steps for Date2 rc = sscanf(lr_eval_string("{Param_Date2}"), "%d/%d/%d %d:%d:%d", &date2.tm_mon, &date2.tm_mday, &date2.tm_year, &date2.tm_hour, &date2.tm_min, &date2.tm_sec); if (rc != 6) { lr_error_message("Problem reading date format. Expected 6 values in string, but found %d", rc); lr_abort(); } date2.tm_mon = date2.tm_mon - 1; date2.tm_year = date2.tm_year - 1900; // Use mktime() to convert the "calendar time" structure to time ticks. // Even though this function is not in the VuGen function reference, it is still available to use. // Note that Unix time ticks are defined between 1/Jan/1970 and // 19/Jan/2038, so odd things may happen with dates outside these ranges. time_difference = mktime(&date2) - mktime(&date1); lr_output_message("Total number of seconds difference: %d", time_difference); // Calculate time difference in days, hours, minutes and seconds. days = time_difference/86400; time_difference = time_difference - (days * 86400); hours = time_difference/3600; time_difference = time_difference - (hours * 3600); minutes = time_difference/60; time_difference = time_difference - (minutes * 60); seconds = time_difference; lr_output_message("Days: %d, Hours: %d, Minutes: %d, Seconds: %d", days, hours, minutes, seconds); return 0; } |
UPDATE: Calculating the difference between timestamps in milliseconds
Someone has asked how they calculate the difference between two timestamps that are in milliseconds like those that are returned by the JavaScript getTime() method, or the LoadRunner web_save_timestamp_param() function.
You would naturally think that you should be able to convert the timestamps to a number, and then just subtract them, but doing this, you run into a limitation of VuGen.
1 2 3 4 | lr_output_message("The size of a long in VuGen is %d bytes", sizeof(unsigned long)); lr_output_message("The size of an int in VuGen is %d bytes", sizeof(unsigned int)); // Action.c(3): The size of a long in VuGen is 4 bytes // Action.c(4): The size of an int in VuGen is 4 bytes |
The size of both int and long is 32 bits, so the largest number they can store is 4294967295 (2n-1). Unfortunately this is narrower than a timestamp in milliseconds e.g. 1234567890123 (Friday the 13th, 2009 at 11:31:30pm and 123 milliseconds UTC), so trying to store this value inside an int will cause an overflow.
However, using a double will not cause an overflow, so the code looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | double atof (const char *string); // must explicitly declare functions which do not return an int Action() { char* start_time = "1234567890123"; // Friday the 13th, 2009 at 11:31:30pm and 123 milliseconds UTC double time_difference; web_save_timestamp_param("TimeNow", LAST); time_difference = atof(lr_eval_string("{TimeNow}")) - atof(start_time); // odd results if time_difference is greater than 2,147,483,647 (max value for signed int) lr_output_message("Time difference: %d milliseconds", (int)time_difference); return 0; } |
Related posts:
- Parameterising Unix/Posix timestamps in VuGen A common question from people creating web-based VuGen scripts is...
- VuGen String Comparison Behaviour Anyone who works with VuGen should know that they should...
- Think time that cannot be ignored Someone asked me once if there was a way of...
- Querying a MySQL database with LoadRunner Let’s imagine that you want to execute arbitary SELECT, INSERT,...
- Global variables aren’t really global in LoadRunner If you studied programming, you probably know a few little...
You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.
September 9th, 2009 at 10:40 pm
This is a very good function but I wanted to alter this to give me only the working days excluding the weekendsand then maybe extending it a bit further to negate the bank holidays. Any ideas?
September 10th, 2009 at 7:27 am
You probably want to use the Date/Time parameter type instead of a function like this. The Date/Time parameter allows you to specify “working days only”.
If you wanted to also exclude holidays, you could make an array of holiday dates, and write some code that would compare the value in your Date/Time parameter with the dates in your exclusion list. If there was a match, you could call lr_advance_param() to get the next date value.
September 11th, 2009 at 10:08 pm
Hi Thanks for your reply.
I cannot really use the working days option because I cant use the date time parameter. The problem being that this parameter will allow me to look at the present time and offset it with a given number of days or working days.
What was really looking for is a function where we can get the number of working days from any given date range. I have worked out the logic for any date range greater than or equal to 7 days but the problem is with when the difference is less than 7 days. There can be 1 Saturday only, one Sunday only, or a Saturday and a Sunday. The only way this can be done is if can find out the weekdays for those 6 days and then negate the Saturdays and Sundays.
September 12th, 2009 at 9:51 am
So, you are really looking for a C function just like the NETWORKDAYS(start_date, end_date, holidays) function that is available in Excel.
I had a quick look for available libraries and couldn’t find anything, so I whipped up a quick and dirty function that should be good enough, providing you only want to calculate the number of working days over a small number of years.
Here is the function:
September 16th, 2009 at 7:22 pm
Hi,
Thank you very much for this. I have now (with a little modification) created a script which will read & get the dates from a .csv file instead of getting the values declared directly in VuGen. The advantage is that we can put in an entire list of working dates extraced by excel and read the file. So this takes care of the problem of no of years.We can have the list as long as we want.( I have put it for 10 yrs.)
Many Thanks once again.
Anustup Ray
September 16th, 2009 at 8:36 pm
Happy to help. Good luck with your load testing. :)
Cheers,
Stuart.