views:

512

answers:

7

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.

+2  A: 

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;
}
codehead
I've posted a solution with difftime function used. It would ensure portability across various *nix flavors. Also "delta" even if long int, is not checked against underlying architecture (x86 or x86_64 or whatever)
ZZambia
A: 

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 ( &currenttime );
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;
Reed Copsey
This couldn't work when wrapping end of month (tm_day++).
ZZambia
A: 

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.

ChrisW
+1  A: 

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;
}
ZZambia
A: 

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.

Zarel
Really simpler...sadly "time(NULL)/60" would offer 59 chances to get bad result falling into truncation of result. Moreover, have you ever looked for asm code of remainder by (21*60) ??!?! A sum if negative would be far easier to poor compiler, and by far more portable on **any** C flavor.
ZZambia
Well, you act like the other solutions don't have the truncation problem. They do. I've added instructions for getting them to round, but in general, it's not that big of a deal.`(21*60)` was a typo, I meant `(24*60)`. Sure, the performance isn't great, but it's no worse than any other method of calculation, such as `localtime()`, which is what others are using. I'll optimize the first one nod to use modular arithmetic, though.
Zarel
Furthermore, considering `localtime()` is slower than a single modulus, I doubt the difference is meaningful.
Zarel
But we're comparing apples to pears... localtime() is needed if you want to ignore your TimeZone, unneeded in other case (known TZ, as in your example). For your reference, when I posted the solution with difftime, I left the result in a "double" variable, to deal with /60 truncation. Be polite when making replies, please.
ZZambia
Apologies if I sounded impolite; I didn't mean to.Even without `localtime()`, your own method need some way to get a `struct tm`, which requires many division operations which add up to much longer than a modulus (you could use other operations, but as far as I know they wouldn't be any faster than my modulus).
Zarel
Also, "number of minutes" can easily be interpreted to mean "number of whole minutes", and presumably being off by half a minute isn't a big deal.
Zarel
A: 

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);
}
Christoph
A: 

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.

Andy Ross