I need a function that can calculate the difference between two datetime (year, month, day, hours, minute, seconds). and then return the difference in the same format.
int main (){
struct datetime dt_from;
init_datetime(&dt_from, 1995, 9, 15, 10, 40, 15);
struct datetime dt_to;
init_datetime(&dt_to, 2004, 6, 15, 10, 40, 20);
struct datetime dt_res;
datetime_diff(&dt_from, &dt_to, &dt_res);
return 0;
}
void datetime_diff(struct datetime *dt_from, struct datetime *dt_to
, struct datetime *dt_res) {
//What can I do here to calculate the difference, and get it in the dt_res?
}
Please have a look and try this example which uses time.h and should be portable. It calculates the difference in days between the dates in your question. You can change the program a little so that it works the way you want.
#include <stdio.h>
#include <time.h>
#include <math.h>
int main() {
time_t start_daylight, start_standard, end_daylight, end_standard;;
struct tm start_date = {0};
struct tm end_date = {0};
double diff;
printf("Start date: ");
scanf("%d %d %d", &start_date.tm_mday, &start_date.tm_mon, &start_date.tm_year);
printf("End date: ");
scanf("%d %d %d", &end_date.tm_mday, &end_date.tm_mon, &end_date.tm_year);
/* first with standard time */
start_date.tm_isdst = 0;
end_date.tm_isdst = 0;
start_standard = mktime(&start_date);
end_standard = mktime(&end_date);
diff = difftime(end_standard, start_standard);
printf("%.0f days difference\n", round(diff / (60.0 * 60 * 24)));
/* now with daylight time */
start_date.tm_isdst = 1;
end_date.tm_isdst = 1;
start_daylight = mktime(&start_date);
end_daylight = mktime(&end_date);
diff = difftime(end_daylight, start_daylight);
printf("%.0f days difference\n", round(diff / (60.0 * 60 * 24)));
return 0;
}
Test
Start date: 15 9 1995
End date: 15 6 2004
3195 days difference
Or even simpler for non-interactive code and with standard or daylight savings time:
#include <stdio.h>
#include <time.h>
#include <math.h>
int main()
{
time_t start_daylight, start_standard, end_daylight, end_standard;;
struct tm start_date = {0};
struct tm end_date = {0};
double diff;
start_date.tm_year = 1995;
start_date.tm_mon = 9;
start_date.tm_mday = 15;
start_date.tm_hour = 10;
start_date.tm_min = 40;
start_date.tm_sec = 15;
end_date.tm_mday = 15;
end_date.tm_mon = 6;
end_date.tm_year = 2004;
end_date.tm_hour = 10;
end_date.tm_min = 40;
end_date.tm_sec = 20;
/* first with standard time */
start_date.tm_isdst = 0;
end_date.tm_isdst = 0;
start_standard = mktime(&start_date);
end_standard = mktime(&end_date);
diff = difftime(end_standard, start_standard);
printf("%.0f days difference\n", round(diff / (60.0 * 60 * 24)));
/* now with daylight time */
start_date.tm_isdst = 1;
end_date.tm_isdst = 1;
start_daylight = mktime(&start_date);
end_daylight = mktime(&end_date);
diff = difftime(end_daylight, start_daylight);
printf("%.0f days difference\n", round(diff / (60.0 * 60 * 24)));
return 0;
}
Here is the basic idea:
Convert your datetime into an integral type (preferable long long or unsigned long long) which represents your datetime value as it's smallest unit (second in your case). How to achieve that? Easy transform the single values into seconds and add everything together. (seconds + minutes * 60 + hours * 3600 ...)
Do this for both values and then subtract the integer values.
Now convert the single integer value, the time difference, back to a datetime. How? Start with the biggest unit (years) and divide the difference by the amount of seconds within one year (60 * 60 * 24 * 365). Now you know how many years are in between your two datetimes. Take the rest and divide it by the amount of seconds per month, and so on...
(Obviously I ignored everything rather complicated, like daylight saving time for example)
However I would highly recommend using struct tm from time.h as mentioned in the comments. It is portable and you can use difftime.
Related
I am trying to calculate number of days elapsed from a given GMT time.
Well, I am able to make it work with iterative approach of calculation (finding number of normal years
and leap years)
The function get_number_of_leap_years_from_base_year is iterating over all the years from 1970 till the given date and checking every year whether its a leap or not and finally add all days.
Is there any other way (formula) based to calculating number normal & leap years elapsed.
/* so-prg-2: Calculating number normal & leap years passed */
#include <stdio.h>
#include <string.h>
#include <time.h>
#define BASE_YEAR 1970
void print_time_readable_format(struct tm tm);
int convert_gmt_date_time_to_tm_format(char* gmt_time_fmt);
int get_number_of_leap_years_from_base_year(int start_year, int end_year);
int calculate_days_elapsed_from_epoch(struct tm tm);
int main()
{
int days = 0;
char gmt_time_fmt[] = "Dec 28 18:40:01 2020 GMT";
//char gmt_time_fmt[] = "Jan 20 19:00:01 2019 GMT";
//char gmt_time_fmt[] = "Dec 27 14:52:30 2020 GMT";
//char gmt_time_fmt[] = "Jan 01 00:00:01 1970 GMT";
days = convert_gmt_date_time_to_tm_format(gmt_time_fmt);
printf("GMT = %s and days are %d\n", gmt_time_fmt, days);
return 0;
}
int convert_gmt_date_time_to_tm_format(char* gmt_time_fmt)
{
struct tm tm;
char tm_time_fmt[255];
//set tm struture to 0
memset(&tm, 0, sizeof(struct tm));
// convert gmt_time_fmt to format required by 'tm' structure
strptime(gmt_time_fmt, "%B %d %H:%M:%S %Y GMT", &tm);
strftime(tm_time_fmt, sizeof(tm_time_fmt), "%s", &tm);
printf("tm_time_fmt = %s\n", tm_time_fmt);
print_time_readable_format(tm);
return calculate_days_elapsed_from_epoch(tm);
}
int calculate_days_elapsed_from_epoch(struct tm tm)
{
int days_by_month [2][12] = {
/* normal years */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
/* leap years */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}
};
int current_year = tm.tm_year+1900;
int total_years_passed = current_year - BASE_YEAR;
/* -1, to skip the current year */
int nleap_years_passed = get_number_of_leap_years_from_base_year(BASE_YEAR, current_year-1);
int normal_years = total_years_passed - nleap_years_passed;
int total_days_passed = (normal_years*365 + nleap_years_passed*366 );
printf(" **Years total_days_passed =%d\n", total_days_passed);
total_days_passed += days_by_month[(current_year%4 == 0) - (current_year%100 == 0) + (current_year%400 == 0)][tm.tm_mon];
total_days_passed += tm.tm_mday - 1; /* to skip the current day */
printf(" **total_days_passed =%d\n", total_days_passed);
return total_days_passed;
}
int get_number_of_leap_years_from_base_year(int start_year, int end_year)
{
int leap_year_count = 0;
int year = start_year;
while( year <= end_year)
{
if( (year%4 == 0) - (year%100 == 0) + (year%400 == 0) )
leap_year_count++;
year++;
}
printf("leap_year_count = %d\n", leap_year_count);
return leap_year_count;
}
void print_time_readable_format(struct tm tm)
{
printf("tm.tm_year = %d ", tm.tm_year);
printf("tm.tm_mon = %d ", tm.tm_mon);
printf("tm.tm_mday = %d ",tm.tm_mday);
printf("tm.tm_hour = %d ", tm.tm_hour);
printf("tm.tm_min = %d ", tm.tm_min );
printf("tm.tm_sec = %d\n", tm.tm_sec );
}
Use mktime()
Since your code is allowed to use both Standard C strftime() and POSIX strptime(), there's no reason not to use Standard C mktime() either.
It gives you a time_t value which is the number of seconds since The Epoch.
int calculate_days_elapsed_from_epoch(struct tm tm)
{
time_t t = mktime(&tm);
return t / 86400; // 24 * 60 * 60 = 86400
}
But if the goal is to calculate the seconds since The Epoch, you have the answer immediately from mktime().
Note that mktime() is passed a struct tm pointer, and it accepts values that are 'out of range' and normalizes the result. See also the example code in the section 'Demonstrating mktime()'.
Calculating leap days
I have a function jl_dmy_conversion() lurking in my library which converts a combination of year, month, day to a number of days since 1899-12-31 (so in this system, day 1 was 1900-01-01). But it includes a calculation for number of leap days. This code is internal to a package where the parameters are already validated as valid within the date range 0001-01-01 .. 9999-12-31, so it does not do much to protect itself from invalid data. There is another function that invokes this that does the data validation. Some of the information shown here comes from a header, most from the source file containing the implementation.
typedef int Date;
enum { DATE_NULL = -2147483648 }; /* Informix NULL DATE */
#define LEAPYEAR(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
#define PRId_Date "d"
/*
** In 400 years, there are 97 leap years (because the three years
** divisible by 100 but not by 400 are not leap years). This also
** happens to be exactly 20871 weeks.
*/
#define DAYS_IN_400_YEARS (400*365+97)
#define DAYS_IN_2000_YEARS (5*DAYS_IN_400_YEARS)
enum
{
DAYS_IN_JANUARY = 31,
DAYS_IN_FEBRUARY = 28,
DAYS_IN_MARCH = 31,
DAYS_IN_APRIL = 30,
DAYS_IN_MAY = 31,
DAYS_IN_JUNE = 30,
DAYS_IN_JULY = 31,
DAYS_IN_AUGUST = 31,
DAYS_IN_SEPTEMBER = 30,
DAYS_IN_OCTOBER = 31,
DAYS_IN_NOVEMBER = 30,
DAYS_IN_DECEMBER = 31
};
static const int days_in_month[][2] =
{
{ 0, 0 },
{ DAYS_IN_JANUARY, DAYS_IN_JANUARY },
{ DAYS_IN_FEBRUARY, DAYS_IN_FEBRUARY+1 },
{ DAYS_IN_MARCH, DAYS_IN_MARCH },
{ DAYS_IN_APRIL, DAYS_IN_APRIL },
{ DAYS_IN_MAY, DAYS_IN_MAY },
{ DAYS_IN_JUNE, DAYS_IN_JUNE },
{ DAYS_IN_JULY, DAYS_IN_JULY },
{ DAYS_IN_AUGUST, DAYS_IN_AUGUST },
{ DAYS_IN_SEPTEMBER, DAYS_IN_SEPTEMBER },
{ DAYS_IN_OCTOBER, DAYS_IN_OCTOBER },
{ DAYS_IN_NOVEMBER, DAYS_IN_NOVEMBER },
{ DAYS_IN_DECEMBER, DAYS_IN_DECEMBER }
};
/* Return date as number of days since 31st December 1899 - no range check */
static Date jl_dmy_conversion(int d, int m, int y)
{
int leap;
int i;
Date daynum;
/* No need to assert here - calling functions have checked basics */
DB_TRACE(1, "[[-- jl_dmy_conversion (d = %2d, m = %2d, y = %4d) ", d, m, y);
leap = LEAPYEAR(y);
if (d > days_in_month[m][leap])
{
DB_TRACE(1, "<<-- NULL (invalid day of month)\n");
return(DATE_NULL);
}
/* Number of days so far this month */
daynum = d;
/* Days so far this year prior to this month */
for (i = 1; i < m; i++)
daynum += days_in_month[i][leap];
DB_TRACE(4, "YDAY = %3ld ", daynum);
/*
** Now compute number of days to 1st of January of this year. Add
** 2000 years (5 periods of 400 years) to ensure that numbers
** resulting from subtraction are positive, even when dates back to
** 0001-01-01 are allowed, and then remove the number of days found
** in 2000 years. This assumes int is 32-bit or longer.
**
** NB: Things begin to go haywire when (y - 1901) yields -4, which
** is when y == 1897. Things get worse before 1601. The result is
** usually, but not always, off by one. Adding 2000 years and then
** subtracting the appropriate number of days sidesteps the
** problems.
*/
y += 2000;
daynum += 365 * (y - 1900); /* Ignoring leap years */
DB_TRACE(4, "INC1 = %7d ", 365 * (y - 1900));
daynum += (y - 1901) / 4; /* Allowing for leap years */
DB_TRACE(4, "INC2 = %4d ", (y - 1901) / 4);
daynum -= (y - 1901) / 100; /* Allowing for non-leap years */
DB_TRACE(4, "INC3 = %3d ", -(y - 1901) / 100);
daynum += (y - 1601) / 400; /* Allowing for leap years */
DB_TRACE(4, "INC4 = %2d ", (y - 1601) / 400);
daynum -= DAYS_IN_2000_YEARS;
DB_TRACE(1, " (r = %7" PRId_Date ") --]]\n", daynum);
return(daynum);
}
The DB_TRACE macro is derived from the code shown in #define a macro for debug printing in C?. The DB_TRACE macro is available in my SOQ (Stack Overflow Questions) repository on GitHub as files debug.c and debug.h in the src/libsoq sub-directory.
The formatting gives a single line showing the calculation steps.
The code above compiles with the debug.h header and <stdio.h> included, and a minimal main(), plus linking with the code from debug.c:
int main(void)
{
int dd = 28;
int mm = 12;
int yyyy = 2020;
Date dt = jl_dmy_conversion(dd, mm, yyyy);
printf("%.4d-%.2d-%.2d = %d\n", yyyy, mm, dd, dt);
return 0;
}
Demonstrating mktime()
As mentioned above, mktime() is passed a struct tm pointer, and it is documented that it accepts values that are 'out of range' and normalizes the result — modifying the structure it is passed. It also sets the tm_wday and tm_yday fields — it ignores them as inputs.
If you have a struct tm value for 2020-12-28 08:20:26 and you want to know the time_t value for 6 days, 18 hours, 43 minutes, 32 seconds later, you can use code like this:
#include <stdio.h>
#include <time.h>
static void print_time(time_t t, const struct tm *tm)
{
char buffer[32];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S %A", tm);
printf("%lld: %s (%d)\n", (long long)t, buffer, tm->tm_yday);
}
int main(void)
{
struct tm tm = { .tm_year = 2020 - 1900, .tm_mon = 12 - 1, .tm_mday = 28,
.tm_hour = 8, .tm_min = 20, .tm_sec = 26 };
time_t t0 = mktime(&tm);
print_time(t0, &tm);
tm.tm_mday += 6;
tm.tm_hour += 18;
tm.tm_min += 43;
tm.tm_sec += 32;
time_t t1 = mktime(&tm);
print_time(t1, &tm);
return 0;
}
When run (in US/Mountain standard time zone — UTC-7), it produces:
1609168826: 2020-12-28 08:20:26 Monday (362)
1609754638: 2021-01-04 03:03:58 Monday (3)
The conditions for leap year are summarized as:
leap year if perfectly visible by 400
not a leap year if visible by 100 but not divisible by 400
leap year if not divisible by 100 but divisible by 4
all other years are not leap year
So the logic could be expressed as:
if (((year%4 == 0) && (year%100 != 0)) || (year%400 == 0))
{
leap_year_count++;
}
year++;
But not sure if re-factoring your existing logic will add any speed advantage.
I am asking what exactly what title says. Obviously something goes wrong in my following code:
#include <stdio.h>
#include <time.h>
int main(void){
struct tm t1 , t2;
t1.tm_sec = 0;
t1.tm_min = 0;
t1.tm_hour = 0;
t1.tm_isdst = -1;
t2 = t1;
printf("Enter 2 dates:\n");
scanf("%d/%d/%d %d/%d/%d" , &t1.tm_mday , &t1.tm_mon , &t1.tm_year ,// Sorry for
&t2.tm_mday , &t2.tm_mon , &t2.tm_year);// lazy coding here
time_t tm1 , tm2;
tm1 = mktime(&t1);
tm2 = mktime(&t2);
printf("%d" , (int) difftime(tm1 , tm2));
}
The output is always zero. The output when I try to run it like this is:
C:\Users\...>program
Enter 2 dates:
3/2/2016 12/2/2017
0
I suspect that your problems are a consequence of two factors:
You don't subtract 1900 from the year values entered by the user, nor do you subtract 1 from the month number — see C11 §7.27.1 components of time for information about the slightly weird encoding for the tm_year and tm_mon elements of struct tm.
Your system uses 32-bit time_t, rather than 64-bit time_t.
Here's a variant of your code, running on a 64-bit system (a MacBook Pro running macOS Mojave 10.14.6, using GCC 9.3.0).
#include <stdio.h>
#include <time.h>
static void dump_time(const char *tag, time_t t);
static void dump_struct_tm(const char *tag, const struct tm *tm);
int main(void)
{
struct tm t1 = { 0 }; /* Probably not essential, but a good idea */
printf("sizeof(time_t) = %d\n", (int)sizeof(time_t));
t1.tm_sec = 0;
t1.tm_min = 0;
t1.tm_hour = 0;
t1.tm_isdst = -1;
struct tm t2 = t1;
printf("Enter 2 dates:\n");
int n = scanf("%d/%d/%d %d/%d/%d", &t1.tm_mday, &t1.tm_mon, &t1.tm_year,
&t2.tm_mday, &t2.tm_mon, &t2.tm_year);
if (n != 6)
{
fprintf(stderr, "failed to read two dates (n = %d)\n", n);
return 1;
}
struct tm t3 = t1;
struct tm t4 = t2;
time_t tm1, tm2;
tm1 = mktime(&t1);
tm2 = mktime(&t2);
dump_struct_tm("t1", &t1);
dump_struct_tm("t2", &t2);
dump_time("time-1", tm1);
dump_time("time-2", tm2);
printf("%d\n", (int) difftime(tm1, tm2));
t3.tm_year -= 1900;
t3.tm_mon -= 1;
t4.tm_year -= 1900;
t4.tm_mon -= 1;
time_t tm3 = mktime(&t3);
time_t tm4 = mktime(&t4);
dump_struct_tm("t3", &t3);
dump_struct_tm("t4", &t4);
dump_time("time-3", tm3);
dump_time("time-4", tm4);
printf("%d\n", (int) difftime(tm3, tm4));
return 0;
}
static void dump_time(const char *tag, time_t t)
{
char buffer[32];
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", localtime(&t));
printf("%s = %lld (%s)\n", tag, (long long)t, buffer);
}
static void dump_struct_tm(const char *tag, const struct tm *tm)
{
printf("%s: year = %5d, month = %2d, day = %2d, "
"hour = %2d, minute = %2d, second = %2d, DST = %d\n",
tag, tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_isdst);
}
The two dumping functions are illustrative of a handy technique I use when debugging — a function that dumps a structure, along with a tag that identifies what the code is dumping this time.
When run (as date37, compiled from date37.c), I get:
$ date37
sizeof(time_t) = 8
Enter 2 dates:
3/2/2016 12/2/2017
t1: year = 2016, month = 2, day = 3, hour = 0, minute = 0, second = 0, DST = 0
t2: year = 2017, month = 2, day = 12, hour = 0, minute = 0, second = 0, DST = 1
time-1 = 61415132400 (3916-03-03 00:00:00)
time-2 = 61447442400 (3917-03-12 00:00:00)
-32310000
t3: year = 116, month = 1, day = 3, hour = 0, minute = 0, second = 0, DST = 0
t4: year = 117, month = 1, day = 12, hour = 0, minute = 0, second = 0, DST = 0
time-3 = 1454482800 (2016-02-03 00:00:00)
time-4 = 1486882800 (2017-02-12 00:00:00)
-32400000
$
The difference between the two values that result from difftime() is 90000 seconds, the number of seconds in a day (86400) plus the number of seconds in an hour (3600). The "1 day" component is because 2016 was a leap year and the difference spans 2016-02-29, but even though 3916 is a leap year, the difference is between two dates in March in consecutive years, which doesn't span 3916-02-29. The "1 hour" component is because the time zone I'm in, US/Mountain or America/Denver (UTC-07:00 in standard time, UTC-06:00 in daylight saving time), switches between winter time (standard time) and summer time (daylight saving time) on Sunday 3917-03-11 at 02:00. Note that strftime() assumes local time; using gmtime() instead of localtime() changes the apparent time values.
Try this code on your machine. I expect that you're running into overflows because you have 32-bit time_t and the dates in the fourth millennium have overflowed. I would not be surprised to find that mktime() returns -1 for both dates in the first (uncorrected) fragment because the values cannot be represented accurately (and the difference between -1 and -1 is indeed 0).
If you have 32-bit time_t values, you run into trouble after a time_t value reaches:
0x7FFFFFFF = 2147483647 = 2038-01-19 03:14:07Z (aka UTC)
A machine with 64-bit time_t does not run into that problem.
I am trying to find differentiation between two date(i.e. 14:49:41 and 15:50:42) using below code:
Action()
{
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
};
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 hours, minutes, seconds;
// Save example dates to a parameter.
// capture these values using web_reg_save_param or similar.
// date format: hh:mm:ss
lr_save_string("14:49:41", "Param_Date1");
lr_save_string("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",&date1.tm_hour, &date1.tm_min, &date1.tm_sec);
// Repeat the above steps for Date2
rc = sscanf(lr_eval_string("{Param_Date2}"), "%d:%d:%d", &date2.tm_hour, &date2.tm_min, &date2.tm_sec);
time_difference = mktime(&date2) - mktime(&date1);
lr_output_message("Total number of seconds difference: %d", time_difference);
// Calculate time difference in hours, minutes and seconds.
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("Hours: %d, Minutes: %d, Seconds: %d", hours, minutes, seconds);
return 0;
}
Actual output should return : Hours: 1, Minutes: 1, Seconds: 1
But output returns : Hours: 0, Minutes: 0, Seconds: 0
Please help me fix this problem. Or Else any other alternative achieve it?
hours, minutes and seconds should not be declared as Integers as you are dividing the value by 3600. If you declare them as floating point numbers it may work. Other than that everything looks good
The difference between two times in seconds is easy to compute:
int secs1 = ((time1.hour * 60) + time1.min) * 60 + time1.sec;
int secs1 = ((time2.hour * 60) + time2.min) * 60 + time2.sec;
int sec_dif = secs1 - secs2;
Or this way:
int sec_dif =
((time1.hour - time2.hour) * 60 + (time1.min - time2.min)) * 60 + (time1.min - time2.min);
int min_dif = sec_dif / 60;
int hour_dif = sec_dif / (60 * 60);
No need to bother with converting the times into time_t types.
I'm working through an example for Advanced Programming in the Unix Environment and the following questions was asked:
If the process time is stored as a 32bit signed integer, and the system counts 100 ticks per second, after how many days will the value overflow?
void proc_ovf()
{
int sec = 60;
int min = 60;
int hour = 24;
int tick = 100;
int epoch_time = (((INT_MAX / (sec * tick)) / min) / hour);
struct tm * timeinfo;
time_t epoch_time_as_proc_t = epoch_time;
timeinfo = localtime(&epoch_time_as_proc_t);
printf("3] overflow date of proc: %s", asctime(timeinfo));
}
Is the following solution a reasonable calculation for how many days before overflow?
(((INT_MAX / (sec * tick)) / min) / hour)
This calculation yielded 248 days.
248 days looks good.
But your code doesn't. Your variables have the wrong names. They should be:
int ticks_per_second = 100;
int seconds_per_minute = 60;
int minutes_per_hour = 60;
int hours_per_day = 24;
int ticks = INT_MAX;
int seconds = ticks / ticks_per_second;
int minutes = seconds / seconds_per_minute;
int hours = minutes / minutes_per_hour;
int days = hours / hours_per_day;
printf("overflow after %d days\n", days);
The above code takes care of mentioning the measurement units. Can you see how nicely the measurement units cancel out in each line of the second part of the code?
What's the simplest way to calculate the number of minutes until 9pm (being today or tomorrow)?
Was looking over mktime() but seemed a hassle to get the day # and month, dealing with all that.
Just calculate the delta to today's 9pm. If it's negative, add 24hrs to get the delta to tomorrow's 9pm.
#include <stdio.h>
#include <time.h>
int main(int argc, char* argv[]) {
struct tm* tm;
time_t ts=time(NULL);
if(tm=localtime(&ts)) {
long int delta;
tm->tm_hour = 21;
tm->tm_min = 0;
tm->tm_sec = 0;
delta = mktime(tm) - ts;
if(delta<0) {
delta+=24*60*60;
}
printf("%d minutes til (next)9pm\n",delta/60);
}
return 0;
}
This will give you the minutes until 9pm.:
time_t currenttime;
time_t ninePM;
struct tm * timeinfo;
int minutesUntilNine;
// Fill currenttime + convert to struct tm
time ( ¤ttime );
timeinfo = localtime ( &rawtime );
// Check for after 9pm...
if (timeinfo->tm_hour >= 21) // Are we after 9pm?
timeinfo->tm_day++; // increment our day
// Set timeinfo to the time you want...
timeinfo->tm_sec = 0;
timeinfo->tm_min = 0;
timeinfo->tm_hour = 21; // 9pm
ninePM = mktime( timeinfo );
minutesUntilNine = (ninePM - currenttime) / 60;
A simple way is to calculate the number of hours and minutes (given what the time is now, plus the fact that there are 24 hours in a day), and multiply the number of hours by 60 to make it a number of minutes. Alternatively, instead of using a 24-hour clock to express the time, use a 1440 minute clock: it's easy to subtract one time from another, to get a time difference.
Here it is (output in seconds...)
#include <stdio.h>
#include <time.h>
int main(void)
{
double dt = 0.0f;
time_t ti = time(NULL);
time_t tf;
struct tm *pt_actual = localtime(&ti);
struct tm t_actual = *pt_actual;
struct tm t_target = *pt_actual;
t_target.tm_hour = 21; // 09:00 pm
t_target.tm_min = 0;
tf = mktime(&t_target);
dt = difftime(tf, ti);
if (dt < 0)
dt += (24*60*60); // if negative, just consider **next** 9pm target, add a day
printf("difftime = %f seconds\n", dt );
return 0;
}
The guy's asking for the simplest way. All your ways are unnecessarily complex. Just use modular arithmetic:
#include <stdio.h>
#include <time.h>
#define TARGET_TIME 21*60 // 9:00 PM, in format HH * 60 + MM
int main(int argc, char* argv[])
{
struct tm* tm;
time_t ts = time(NULL);
int minutes_until_9pm;
tm = localtime(&ts);
minutes_until_9pm = 24*60 - (tm->tm_min + tm->tm_hour * 60 + TARGET_TIME)%(24*60);
//alternatively, the following is slightly faster
//minutes_until_9pm = 24*60 - (tm->tm_min + tm->tm_hour * 60 + TARGET_TIME) + (tm->tm_min+tm->tm_hour*60+TARGET_TIME>24*60?24*60:0);
printf("%d minutes til (next)9pm\n", minutes_until_9pm);
return 0;
}
If you know your timezone , it all becomes even simpler:
#include <stdio.h>
#include <time.h>
#define TARGET_TIME 21*60 // 9:00 PM, in format HH * 60 + MM
#define TIMEZONE (-6) // This is CST; replace with your own timezone
int main(int argc, char* argv[])
{
int minutes_until_9pm = 24*60 - (time(NULL)/60 + TARGET_TIME + (24+TIMEZONE)*60)%(24*60);
printf("%d minutes til (next)9pm\n", minutes_until_9pm);
return 0;
}
What's going on here is that, modulo one day, we're getting number of minutes since midnight. Then we're adding 9:00 PM to get the the number of minutes since 9:00 PM. Then we're subtracting that from 24 hours to get the number of minutes until the next 9:00 PM.
If you need higher accuracy (i.e. rounded to the nearest number of minutes, rather than simply number of minutes), simply subtract (tm->tm_sec>=30?0:1) from minutes_until_9pm, or replace time(NULL)/60 with (time(NULL)+30)/60, respectively.
C99 version:
#include <math.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
struct tm now = *localtime(&(time_t){ time(NULL) });
struct tm then = now;
then.tm_hour = 21;
then.tm_min = 0;
then.tm_sec = 0;
int dt = ((int)round(
difftime(mktime(&then), mktime(&now)) / 60) + 24 * 60) % (24 * 60);
printf("time till 9pm: %i minutes\n", dt);
}
The more profound, if less helpful, answer is that there is no simple answer.
How do you even know that today will have a 9pm? OK, sure, I'm sure all the time zones that exist never skip 21:00, but they skip hours in the middle of the night once a year.
Calendrics is a disaster of complexity. Beware.