I am currently trying to create a program where the user gives two values (times, hh:mm:ss) and gets the difference between the two times. This works, if one would only use 12h formats; however, using the 24h format is a must.
My current time struct looks like the following:
typedef struct time {
int hours;
int minutes;
int seconds;
} time;
And my current function to calculate the difference looks like this:
time calculateTimeDiff(time time1, time time2) {
time timeResult;
timeResult.hours = time1.hours - time2.hours;
if(time1.minutes != 00 && time2.minutes != 00) {
timeResult.minutes = time1.minutes - time2.minutes;
}
else {
timeResult.minutes = 00;
}
if(time1.seconds != 00 && time2.seconds != 00) {
timeResult.seconds = time1.seconds - time2.seconds;
}
else {
timeResult.seconds = 00;
}
while(timeResult.seconds > 60) {
timeResult.seconds -= 60;
timeResult.minutes += 1;
}
while(timeResult.minutes > 60) {
timeResult.minutes -= 60;
timeResult.hours += 1;
}
return timeResult;
}
My attempts to support the 24h format have been to add 12 hours to the time if the hours "exceed" the 12 hour format, and to divide the time by two (haven't been far from complete shots in the dark, just to see what works and what wouldn't work). However, this has only resulted in getting incorrect results.
Any and all answers appreciated!
How to get the time difference between two times (24h format)
Although code could use many if-then-else's as in OP's code, it would be simple to convert the h:m:s time into seconds, subtract, and convert back to h:m:s. So I recommend a re-write:
typedef struct time {
int hours;
int minutes;
int seconds;
} time;
long time_sec(time t) {
return (t.hours * 60L + t.minutes)*60 + t.seconds;
}
time sec_time(long s) {
time t;
t.hours = s / 3600;
s %= 3600;
t.minutes = s / 60;
t.seconds = s %= 60;
return t;
}
time calculateTimeDiff(time time1, time time2) {
long t1 = time_sec(time1);
long t2 = time_sec(time2);
long diff = t1 - t2;
return sec_time(diff);
}
#include <stdio.h>
void test(time t1, time t2) {
printf("t1: %3d:%3d:%3d, ", t1.hours, t1. minutes, t1.seconds);
printf("t2: %3d:%3d:%3d, ", t2.hours, t2. minutes, t2.seconds);
time t3 = calculateTimeDiff(t1, t2);
printf("t1-t2: %3d:%3d:%3d, ", t3.hours, t3. minutes, t3.seconds);
t3 = calculateTimeDiff(t2, t1);
printf("t2-t1: %3d:%3d:%3d\n", t3.hours, t3. minutes, t3.seconds);
}
int main(void) {
test((time){14,00,00}, (time){13,00,00});
test((time){22,00,00}, (time){04,00,00});
}
Output
t1: 14: 0: 0, t2: 13: 0: 0, t1-t2: 1: 0: 0, t2-t1: -1: 0: 0
t1: 22: 0: 0, t2: 4: 0: 0, t1-t2: 18: 0: 0, t2-t1: -18: 0: 0
Note that the difference may result in negative values for the members of time returned in calculateTimeDiff().
You can change to time structure instead of both start and end time integer value
#include<iostream>
using namespace std;
void difftime(int startTime, int iRecordEndTime)
{
int duration_min = 0;
cout<<"iRecordEndTime = "<<iRecordEndTime<<endl;
cout<<"startTime = "<<startTime<<endl;
if ( (iRecordEndTime/100 < startTime/100) || ((iRecordEndTime/100 == startTime/100) && (iRecordEndTime%100 <= startTime%100)) )
{
duration_min = ((iRecordEndTime / 100 + 24)*60 + iRecordEndTime%100) - ((startTime/100)*60 + startTime%100);
}
else
{
duration_min = (iRecordEndTime / 100 - startTime/100)*60 + (iRecordEndTime%100 - startTime%100);
}
cout<<"duration_min = "<<duration_min<<endl;
}
int main()
{
cout<<"enter the start time Hour:Minutes xxxx"<<endl;
int startTime{0};
cin>>startTime;
cout<<"enter the End time Hour:Minutes xxxx"<<endl;
int iRecordEndTime{0};
cin>>iRecordEndTime;
difftime(startTime, iRecordEndTime );
}
Output
enter the start time Hour:Minutes xxxx\
2300\
enter the End time Hour:Minutes xxxx\
0000\
iRecordEndTime = 0\
startTime = 2300\
duration_min = 60
Related
I am trying to add two times like 20:30 + 1:40 = 22h 10m.
I'm having a problem with the remainder after the dot
#include <stdio.h>
float walking (float start,float duration);
int main() {
printf ("finish = %.2f", walking(20.30, 1.40));
return 0;
}
float walking(float start, float duration) {
int finMinuites = (int)(start * 100) % 100 + (int)(duration * 100) % 100;
int finHours = (start * 100) / 100 + (duration * 100) / 100;
if (finMinuites >= 60) {
finMinuites -= 60;
finHours++;
}
if (finHours >= 24)
finHours -= 24;
return finHours + finMinuites / 100;
}
If you really want to store time in a float then here is a solution:
#include<stdio.h>
#include<math.h>
float walking(float start,float duration);
int main() {
printf("finish = %.2f",walking(20.30, 1.40));
return 0;
}
int toMinutes(float time){
int t = (int)round((time*100));
int hours = t/100;
int min = t - hours * 100;
return hours*60+min;
}
float toFloat(int minutes){
int hours = minutes/60;
int min = minutes - hours * 60;
float t = hours * 100;
t += min;
t /= 100;
return t;
}
float walking(float start,float duration){
int mins = toMinutes(start) + toMinutes(duration);
int day = 24*60;
while(mins > day){
mins -= day;
}
return toFloat(mins);
}
But I would suggest storing the minutes as an int instead.
The difficult part is to break a floating point variable (FP) properly.
float/double cannot represent many values like 0.01 exactly and so
(int)(start * 100) fails edge cases when the minutes * 100 are a fraction just less than a whole number as (int) truncates.
Instead break the FP value into whole and fraction parts (modf()) to get the hours and minutes and then form a total single unit time value. Add. Then convert the sum back to hours.minutes.
Makes more sense to use double than float given OP is using double test case constants. Also float should be reserved for compelling conditions that require/benefit from them instead of the default double.
No need to scale to minutes. Makes for simpler code. Easy-peasy.
#include <math.h>
double to_hours(double hours_dot_minutes) {
double h;
double m = modf(hours_dot_minutes, &h) * 100.0;
return h + m/60.0;
}
double reduce_to_a_day(double hours) {
const double hours_per_day = 24.0;
hours = fmod(hours, hours_per_day);
if (hours < 0.0) {
hours += hours_per_day;
}
return hours;
}
double to_hours_dot_minutes(double hours) {
double h;
double m = modf(hours, &h) * 60.0;
return h + m/100.0;
}
double walking(double start, double duration) {
double sum = to_hours(start) + to_hours(duration);
sum = reduce_to_a_day(sum);
return to_hours_dot_minutes(sum);
}
Notice that int math is not used anywhere. IMO, floating point problems best handled with FP math, integer problems with integer math and text problems with text manipulation. Mixing approaches often encounters issues in edge cases - as in OP's use of (int) for a FP problem.
If still wanting to use a cast over a limited range of values,
double walking(double start, double duration) {
int start_h = (int) start;
int duration_h = (int) duration;
double sum = start_h + duration_h +
((start - start_h) + (duration - duration_h)) * 100.0 / 60.0;
while (sum >= 24.0) sum -= 24.0;
int sum_h = (int) sum;
return sum_h + (sum - sum_h) * 60.0 / 100.0;
}
As suggested by #ryyker, you can make life simple with strings without changing the calling parameters:
#include <stdio.h>
#include <stdlib.h>
double walking( double bgn, double dur ) {
printf( "Start = %5.2f duration = %5.2f ", bgn, dur );
char str[32];
sprintf( str, "%.2f %.2f", bgn, dur );
int res = 0, cnt = 1;
for( char *cp = str; ( cp = strtok( cp, " ." ) ) != NULL; cp = NULL )
res += atoi( cp ) * (cnt&1 ? 60 : 1), cnt++;
return res/60%24 + ((res%60)*0.01);
}
int main() {
double pairs[][2] = {
{ 20.30, 1.40 },
{ 1.47, 1.13 },
{ 0.00, 1.13 },
{ 0.00, 0.00 },
{ 23.59, 0.01 },
{ 12.00, 48.27 },
};
for( int i = 0; i < sizeof pairs/sizeof pairs[0]; i++ )
printf ( "finish = %5.2f\n", walking( pairs[i][0], pairs[i][1] ) );
return 0;
}
Output
Start = 20.30 duration = 1.40 finish = 22.10
Start = 1.47 duration = 1.13 finish = 3.00
Start = 0.00 duration = 1.13 finish = 1.13
Start = 0.00 duration = 0.00 finish = 0.00
Start = 23.59 duration = 0.01 finish = 0.00
Start = 12.00 duration = 48.27 finish = 12.27
EDIT:
It has been noted that this approach may not work for Dr Who and other time travellers. The following shows the necessary changes for those for whom the second law of thermodynamics does not apply:
sprintf( str, "%.2f %.2f", bgn, dur );
int res = 0, cnt = 1, sgn = 1;
for( char *cp = str; ( cp = strtok( cp, " ." ) ) != NULL; cp = NULL, cnt++ )
res += atoi( cp )
* (cnt&1 ? 60 : 1)
* sgn,
sgn = *cp == '-' ? -1 : 1;
/* then one additional test case */
{ 12.00, -2.30 },
/* Output of the single test case: */
Start = 12.00 duration = -2.30 finish = 9.30
Since the first parameter shown in the OP seems to use a 24hr clock, no attempt has been made to test starting at "minus eleven-thirty".
Enjoy your walk. Take the garbage out with you when you leave...
I've spent a good hour on this, but I can't create a formula that works for my c program. (I have a new programmer).
I have to convert UTC time to its respective time in a particular city. My code works perfectly except here. Here it gives me the wrong answer. I can't wrap my head around it (I created a formula but it makes no sense to me).
In my program, time is entered as 24 hour time. 9AM = 900, 12PM = 1200, 12am = 0 etc.
If we are asked to convert 2359 to Eucla time (UTC +845) my program outputs 804. The correct answer is 844.
I figured out how to calculate 844, but I make no sense of it.
2359 + 845 = 3204 (adding the timezone offset 845 to the UTC time)
3204 - 60 = 3144 (minus 60 for some reason [I followed my time overflow formula]
3144 - 2400 = 2400 (minus 2400 because time cannot be more than 2359)
How my program works
First plus UTC and offset time
calculatedTime = UTC + offset;
Then under that
if (calculatedTime < 2359) {
calculatedTime = calculatedTime - 2400;
}
I also have another function which checks for overflow time underneath
if (((calculatedTime > 59) && (calculatedTime < 99)) || ((calculatedTime > 159) && (calculatedTime < 199))) {
// All the way to 2359
calculatedTime = calculatedTime - 60 + 100;
}
You need to separate the time into hours and minutes. Then add the time zone offsets to the hours and minutes separately. Handle roll-over. Finally, recombine the hours and minutes into the final answer.
Like this:
int main(void)
{
// inputs
int time = 2359;
int zone = 845;
// separate hours and minutes
int timeHours = time / 100;
int timeMinutes = time % 100;
int zoneHours = zone / 100;
int zoneMinutes = zone % 100;
// add the hours and minutes
int hours = timeHours + zoneHours;
int minutes = timeMinutes + zoneMinutes;
// handle the rollover conditions
if (minutes > 60) {
minutes -= 60;
hours++;
}
if (hours > 24) {
hours -= 24;
}
// recombine the hours and minutes
int adjustedTime = hours * 100 + minutes;
printf("%d\n", adjustedTime);
}
Note that this code only works for timezones with positive offsets. You'll need to figure out how to make it work for negative time zones.
OP's code has various off-by-one errors.
// if (((calculatedTime > 59) && (calculatedTime < 99)) ||
// ((calculatedTime > 159) && (calculatedTime < 199))) {
if (((calculatedTime > 59) && (calculatedTime < 100)) ||
((calculatedTime > 159) && (calculatedTime < 200))) {
// if (hours > 24) {
// hours -= 24;
// }
if (hours >= 24) {
hours -= 24;
}
Also code has more clarity using values like 60, 100
if (((calculatedTime >= 60) && (calculatedTime < 100)) ||
((calculatedTime >= 60*2) && (calculatedTime < 100*2))) {
Yet OP's approach fails with negative numbers.
To cope with positive and negative time values, split the "hhmm" time into a hours and minutes. Look for conditions of "minute" overflow. I recommend 2 helper functions to split and combine results.
#include <stdio.h>
#include <stdlib.h>
void hhmm_split(int hhmm, int *hour, int *min) {
*hour = hhmm / 100;
*min = hhmm % 100;
}
/* `min` may be outside the primary range of (-60 ... 60) */
int hhmm_combine(int hour, int min) {
hour += min / 60;
min %= 60;
if (hour < 0 && min > 0) {
min -= 60;
hour++;
} else if (hour > 0 && min < 0) {
min += 60;
hour--;
}
hour %= 24;
return hour * 100 + min;
}
Test code
void hhmm_add(int t1, int t2) {
int t1_hh, t1_mm, t2_hh, t2_mm;
hhmm_split(t1, &t1_hh, &t1_mm);
hhmm_split(t2, &t2_hh, &t2_mm);
int sum = hhmm_combine(t1_hh + t2_hh, t1_mm + t2_mm);
printf("t1:% 05d + t2:% 05d = sum:% 05d\n", t1, t2, sum);
}
int main(void) {
hhmm_add(2359, 845);
hhmm_add(2359, -845);
hhmm_add(-2359, 845);
hhmm_add(-2359, -845);
}
Output:
t1: 2359 + t2: 0845 = sum: 0844
t1: 2359 + t2:-0845 = sum: 1514
t1:-2359 + t2: 0845 = sum:-1514
t1:-2359 + t2:-0845 = sum:-0844
Essentially the program I've made adds time when the times are listed in the kind of military format (eg. 2300 is equal to 11pm) and then a duration is added (eg. 345, 3 hours 45 minutes.)
I've come across an issue in that when you add time to something that surpasses midnight it will continue to add past that. So for instance if you add 2 hours (200) to 11pm (2300) you will get a result of 2500 which is illogical for this purpose.
What I need my program to do is reach 2400 (midnight) and then reset to 0 but continue to add the remaining amount that needed to be added.
I've been trying to figure this out but I cannot figure out how I'm going to make it add what remains after you reset it to 0.
Since minutes are added modulo 60 and hours modulo 24, you need to handle them separately.
Something like
int add_time(int old_time, int addition)
{
/* Calculate minutes */
int total_minutes = (old_time % 100) + (addition % 100);
int new_minutes = total_minutes % 60;
/* Calculate hours, adding in the "carry hour" if it exists */
int additional_hours = addition / 100 + total_minutes / 60;
int new_hours = (old_time / 100 + additional_hours) % 24;
/* Put minutes and hours together */
return new_hours * 100 + new_minutes;
}
Break 24 hour/minute encode as a 4-digit int into hours and minutes. Avoid assuming values are in their primary range.
Add
Re-form time into the primary range.
Example
typedef struct {
int hour; // Normal range 0 - 23
int minute; // Normal range 0 - 59
} hhmm;
hhmm int_to_hhmm(int src) {
src %= 2400;
if (src < 0) src += 2400;
hhmm dest = { src / 100, src % 100 };
return dest;
}
int hhmm_to_int(hhmm src) {
src.hour += src.minute / 60;
src.minute %= 60;
if (src.minute < 0) {
src.minute += 60;
src.hour--;
}
src.hour %= 24;
if (src.hour < 0) {
src.hour += 24;
}
return src.hour * 100 + src.minute;
}
int add_mill_format_times(int t0, int t1) {
hhmm hhmm0 = int_to_hhmm(t0);
hhmm hhmm1 = int_to_hhmm(t1);
hhmm sum = { hhmm0.hour + hhmm1.hour, hhmm0.minute + hhmm1.minute };
return hhmm_to_int(sum);
}
you can do
addTime(int time1,int time2{
int first,last,addH,addM
last = func1(time1) + func2(time2);
last=last1+last2;
if(last > 60){
addH=last/60;
addM=last%60;
}
first=func2(time1)+func2(time2);
first+= addH;
last += addM;
first/=24;
return first*100 + addM;
}
func2(int time){
int i;
for(i=0;i<2;i++)
time/=10;
return time;
}
func1(int time){
int l=time%10;
time/=10;
int m=time%10;
return m*10 + l;
}
//import library
#include <stdio.h>
#include <stdlib.h>
//declare variable structure
struct time{
int hour;
int min;
int sec;
}startTime, endTime, different, elapsed;
//mould struct and compute elapsedTime
struct time elapsedTime(struct time start, struct time end){
int secondStart, secondEnd, secondDif;
secondEnd = end.hour * 60 * 60 + end.min * 60 + end.sec;
secondStart = start.hour * 60 * 60 + start.min * 60 + start.sec;
if (secondEnd>secondStart)
secondDif = secondEnd - secondStart;
else
secondDif = secondStart - secondEnd;
different.hour = secondDif / 60 / 60;
different.min = secondDif / 60;
return different;
}
//main function
void main(){
printf("Enter start time (Hour Minute Second) using 24 hours system : ");
scanf("%d %d %d", startTime.hour, startTime.min, startTime.sec);
printf("Enter end time (Hour Minute Second) using 24 hours system : ");
scanf("%d %d %d", endTime.hour, endTime.min, endTime.sec);
elapsed = elapsedTime(startTime, endTime);
}
Can someone help me check and run the code to check whether it is working or not?
You have a mistakes in main function, you should use in scanf int * instead of int so you must add &, you can see below:
//main function
void main(){
printf("Enter start time (Hour Minute Second) using 24 hours system : ");
scanf("%d %d %d", &startTime.hour, &startTime.min, &startTime.sec);
printf("Enter end time (Hour Minute Second) using 24 hours system : ");
scanf("%d %d %d", &endTime.hour, &endTime.min, &endTime.sec);
elapsed = elapsedTime(startTime, endTime);
}
I assume you would want to calculate different.sec so I think the correct calculation of the different time is:
secPerHr = 60 * 60;
secPerMin = 60;
if (secondDif >= secPerHr) {
different.hour = secondDif / secPerHr;
secondDif -= different.hour * secPerHr;
}
if (secondDif >= secPerMin) {
different.min = secondDif / secPerMin;
secondDif -= different.min * secPerMin;
}
different.sec = secondDif;
Also, for testing purposes you would probably want to display the result in your main function.
I am trying to calculate time in C language and i have the following program:
#include <stdio.h>
#include <time.h>
int main(void) {
int hours, minutes;
double diff;
time_t end, start;
struct tm times;
times.tm_sec = 0;
times.tm_min = 0;
times.tm_hour = 0;
times.tm_mday = 1;
times.tm_mon = 0;
times.tm_year = 70;
times.tm_wday = 4;
times.tm_yday = 0;
time_t ltt;
time(<t);
struct tm *ptm = localtime(<t);
times.tm_isdst = ptm->tm_isdst;
printf("Start time (HH:MM): ");
if((scanf("%d:%d", ×.tm_hour, ×.tm_min)) != 2){
return 1;
}
start = mktime(×);
printf("End time (HH:MM): ");
if((scanf("%d:%d", ×.tm_hour, ×.tm_min)) != 2){
return 1;
}
end = mktime(×);
diff = difftime(end, start);
hours = (int) diff / 3600;
minutes = (int) diff % 3600 / 60;
printf("The difference is %d:%d.\n", hours, minutes);
return 0;
}
The program works almost ok:
Output 1:
./program
Start time (HH:MM): 05:40
End time (HH:MM): 14:00
The difference is 8:20.
Output 2:
./program
Start time (HH:MM): 14:00
End time (HH:MM): 22:20
The difference is 8:20.
Output 3:
/program
Start time (HH:MM): 22:20
End time (HH:MM): 05:40
The difference is -16:-40.
As you can see, I got -16:-40 instead of 7:20.
I cannot figure out how to fix this.
If end is after midnight and start before, add 24 hours to the end value:
if( end < start )
{
end += 24 * 60 * 60 ;
}
diff = difftime(end, start);
Note too that all the code related to mktime and tm struct is unnecessary. Those are useful when you require time normalisation (for example if you set tm_hour to 25, mktime will generate a time_t value that is 0100hrs the following day, rolling over the month and year too if necessary), but here you are dealing with just time of day in hours and minutes, so you need just:
int hour ;
int minute ;
if((scanf("%d:%d", &hour, &minute)) != 2){
return 1;
}
start = (time_t)((hour * 60 + minute) * 60) ;
printf("End time (HH:MM): ");
if((scanf("%d:%d", &hour, &minute)) != 2){
return 1;
}
end = (time_t)((hour * 60 + minute) * 60) ;