I am having trouble finding a formula - c++

So we are supposed to convert 453456 seconds into years, days, hours, minutes, and seconds.
However, I cannot seem to get past years.
Here is what I have so far:
#include<iostream>
using namespace std;
int main (){
int secDis;
int years;
const int yearsSec = 31536000;
int days;
cout << "Please give me the time of travel in seconds.";
cin >> secDis;
years = secDis/yearsSec;
days = (yearsSec%secDis) / 1440; /*idk if I am on the right track*/
cout << "You have been traveling for: "
<< years << days;
If it is 453456 seconds it should be 0 years 5 days 5 hours 57 minutes and 36 secs.
//I hate my math skills.

You have the order of secDis and yearsSec reversed in the line to compute the number of days.
Also, the number of seconds in a day are: 24 x 60 x 60, which is 86400. You are off by an order of 60.
The number of seconds left after the number of years is (secDis % yearsSec).
Hence, you need to use:
days = (secDis % yearsSec ) / 86400;

#HowardHinnant has provided a Swiss-army-knife date library for such questions, see this Q&A, after which using
std::cout << human_readable_difference(second_point{453456s},
second_point{0s});}
will indeed print:
0 years 0 months 5 days 5 hours 57 minutes 36 seconds

I really like TemplateRex's answer! (upvoted it).
But here's a way to solve this problem with just the <chrono> library, assuming your definition that a year is 365 days (a pretty coarse assumption):
#include <chrono>
#include <iostream>
int
main()
{
using namespace std;
using namespace std::chrono;
using days = duration<int, ratio_multiply<ratio<24>, hours::period>>;
using years = duration<int, ratio_multiply<ratio<365>, days::period>>;
auto s = 453456s;
auto y = duration_cast<years>(s);
s -= y;
auto d = duration_cast<days>(s);
s -= d;
auto h = duration_cast<hours>(s);
s -= h;
auto m = duration_cast<minutes>(s);
s -= m;
std::cout << y.count() << " years "
<< d.count() << " days "
<< h.count() << " hours "
<< m.count() << " minutes "
<< s.count() << " seconds\n";
}
<chrono> already has units hours, minutes and seconds. Just add two more units for days and years, and now you can just use duration_cast to successively truncate the seconds into coarser units, and then subtract that truncation out from the seconds (a modulo operation). Just continue with finer and finer units until you are down to your finest unit (seconds in this example). The above program outputs:
0 years 5 days 5 hours 57 minutes 36 seconds
This lets <chrono> do all the conversions for you, reducing the chance of errors.

You want the remainder from the division secDis / yearsSec, which is secDis % yearsSec – not yearsSec % secDis.
(That is, to get the remainder, replace /with %.)
I believe it gets easier if you define the number of seconds in each unit of time explicitly:
// Let the computer do the computing.
const int perMinute = 60;
const int perHour = 60 * perMinute;
const int perDay = 24 * perHour;
const int perYear = 365 * perDay;
and spell out every step of the computations:
int years = totalSeconds / perYear;
int daySeconds = totalSeconds % perYear;
int days = daySeconds / perDay;
int hourSeconds = daySeconds % perDay;
int hours = hourSeconds / perHour;
// ...

Related

How do I output two zeros for converting Military Time to standard time?

I'm trying to make a program to convert military time to standard time, am just having a problem outputting two zeroes for times such as 1300/1:00pm, it outputs as 1:0pm
int mtime, mins, hrs;
cout<<"Military to Standard Time"<<endl<<"Enter time: ";
cin>>mtime;
if (mtime >= 0 && mtime <= 2400)
{
if (mtime >= 1200)
{
mtime = mtime - 1200;
hrs = mtime / 100;
mins = mtime % 100;
cout<<hrs<<":"<<mins<<" P.M.";
}
else
hrs = mtime / 100;
mins = mtime % 100;
cout<<hrs<<":"<<mins<<" A.M.";
}
else
cout<<"Error, Please Enter Military Time 0000-2400"<<endl;
First, the data is wrong.
Second, if you want to cout 03 rather than 3, you can use
/*
*setw(2):The out put data with is 2 position
*setfill('0'):If the data is not enough 2 position, such 3 is only 1 position,
* so will fill the output data by zero
*/
cout<<setfill('0')<<setw(2)<<mins;
One solution is to conditionally print a 0 if the minutes is less than 10:
#include <iostream>
int main()
{
int hrs = 1;
int mins = 3;
std::cout << hrs << ":" << (mins<10?"0":"") << mins << " A.M.\n";
mins = 15;
std::cout << hrs << ":" << (mins<10?"0":"") << mins << " A.M.\n";
}
Output:
1:03 A.M.
1:15 A.M.
Add curly braces to both the else blocks. Kindly avoid such basic Syntax errors.
else {
hrs = mtime / 100;
mins = mtime % 100;
cout<<hrs<<":"<<mins<<" A.M.";
}
else {
cout<<"Error, Please Enter Military Time 0000-2400<<endl;"
}

Displaying seconds, minutes and hours from total seconds in C++ [duplicate]

This question already has answers here:
Converting seconds to hours and minutes and seconds
(11 answers)
Closed 9 months ago.
I am trying to solve a problem where I have a total seconds variable, from which I am trying to determine the hours, minutes and seconds.
I do not want to use any external libraries for this task.
What I have noticed is that my seconds variable seems to result in 1 less than the actual value when it is in int form,
but when it is in double form the answer is correct. Why is this?
I would welcome a different approach, perhaps using the remainder operator.
// Example program
#include <iostream>
#include <string>
int main()
{
int total_seconds;
total_seconds = 3870;
int hours, minutes, seconds;
double total_h, total_m, total_s;
int total_hours_int, total_minutes_int;
total_h = (double)total_seconds / 3600;
total_hours_int = total_seconds / 3600;
hours = total_hours_int;
total_m = (total_h - total_hours_int) * 60;
total_minutes_int = (total_h - total_hours_int) * 60;
minutes = total_minutes_int;
total_s = ((double)total_m - total_minutes_int) * 60;
seconds = ((double)total_m - total_minutes_int) * 60;
//seconds = (double)total_s;
std:: cout << hours;
std:: cout << minutes;
std:: cout << total_s;
std:: cout << seconds;
}
Output : 143029
Update:
The answer below was given before the C++98 tag was added to the question.
The chono library is available since C++11, so you can use it only from that version onwards.
You haven't given any context for this task.
My asnwer below assumes you need to solve the problem in any valid C++ manner (i.e. that it is not mandatory the caculate the numbers "by hand").
If this is the case, you can use the C++ chrono library for that, as shown below. This solution is shorter and less error-prone, and avoids the type issues you had altogether.
The main class I used is std::chrono::duration and it's helper types (as you can see in the link), as well as std::chrono::duration_cast.
#include <iostream>
#include <chrono>
int main()
{
int total_seconds = 3870;
std::chrono::seconds total_secs(total_seconds);
auto hours = std::chrono::duration_cast<std::chrono::hours>(total_secs);
auto mins = std::chrono::duration_cast<std::chrono::minutes>(total_secs - hours);
auto secs = std::chrono::duration_cast<std::chrono::seconds>(total_secs - hours - mins);
std::cout << "totals seconds: " << total_secs.count() << std::endl;
std::cout << " hours: " << hours.count() << std::endl;
std::cout << " minutes: " << mins.count() << std::endl;
std::cout << " seconds: " << secs.count() << std::endl;
}
Output:
totals seconds: 3870
hours: 1
minutes: 4
seconds: 30
I've reopened answear since it was updated to C++98.
Before C++11 it can be done nicely using standard library:
#include <iostream>
#include <string>
#include <ctime>
int main()
{
int seconds;
while (std::cin >> seconds) {
std::tm t = {};
t.tm_sec = seconds;
t.tm_mday = 1;
mktime(&t);
t.tm_hour += t.tm_yday * 24;
char buf[32];
strftime(buf, sizeof(buf), "%H:%M:%S", &t);
std::cout << t.tm_yday << ' ' << seconds << " = " << buf << '\n';
}
return 0;
}
https://godbolt.org/z/ceWWfoP6P

Get proper term of person life using gmtime()

I'm trying to calculate exact age of person using difference between now and the date of birth. I'm getting difference in seconds, which, I suppose is correct value. Then i'd like to convert seconds into struct tm, using gmtime(). But it is giving me a tm_year on 70 bigger than it must be, and tm_mday on 1 bigger than must be. It seems to be clear about tm_mday- the range of it is from 1 to 31, I can just subtract 1 from, whereas tm_year is the years from 1900. OK, so why does gmtime() give me +70 years?
#include <iostream>
#include <ctime>
using namespace std;
int main() {
int min,h,d,m,y;
struct tm bd = {0};
cout << "Enter birth date in the format: hh:min/dd.mm.yyyy"<<endl;
scanf("%d:%d/%d.%d.%d",&h,&min,&d,&m,&y);
bd.tm_year = y-1900;
bd.tm_mon = m-1;
bd.tm_mday = d;
bd.tm_hour = h;
bd.tm_min = min;
time_t now = time(NULL);
cout << "NOW: "<<now<<" BD: "<<mktime(&bd)<<endl;
time_t seconds = difftime(now,mktime(&bd));//(end,beginning)
cout <<"seconds elapsed: "<< seconds<<endl;
struct tm * age;
age = gmtime (&seconds);
cout << "year" << age->tm_year << endl;
cout << "mon" << age->tm_mon << endl;
cout << "mday" << age->tm_mday << endl;
cout << "hour" << age->tm_hour << endl;
cout << "min" << age->tm_min << endl;
cout << "sec" << age->tm_sec << endl;
}
output:
Enter birth date in the format: hh:min/dd.mm.yyyy
13:28/04.03.2021
NOW: 1614853702 BD: 1614853680
seconds elapsed: 22
year 70
mon 0
mday 1
hour 0
min 0
sec 22
It is translating "unix epoch time", which is seconds since 1970, to a date.
It is not converting seconds to an amount of days/months/years. There is fundamentally no such conversion. 30 days can be less than or more than a month. 365 days can be a year, or 1 day less than a year. 24 times 60 times 60 seconds can be less than a day when a leap second happens.
Seconds after a point in time is a date. But seconds does not uniquely map to a number of days/months/years.
Find the two points in time - dates - and compare/subtract components to do that.

Convert milliseconds to hours:minutes:seconds:milliseconds in C++

I'm looking for a way to print out milliseconds in this format using C++:
cout << hours << " Hours : " << minutes << " Minutes : " << seconds << " Seconds : " << milliseconds << " Milliseconds" << endl;
I know there are a ton of duplicate questions about this. But none of them really handle how to get the remainder in milliseconds. There are a few that do this using Java, but I want a solution in C++.
Edit:
I wanted to clarify the question. I'm looking to take a time value that I get for the time it takes a program to run and print out that time in a legible format for the user. Getting the standard hr:min:sec was straight forward. But including any remaining milliseconds was tripping me up.
std::string format_duration( std::chrono::milliseconds ms ) {
using namespace std::chrono;
auto secs = duration_cast<seconds>(ms);
ms -= duration_cast<milliseconds>(secs);
auto mins = duration_cast<minutes>(secs);
secs -= duration_cast<seconds>(mins);
auto hour = duration_cast<hours>(mins);
mins -= duration_cast<minutes>(hour);
std::stringstream ss;
ss << hour.count() << " Hours : " << mins.count() << " Minutes : " << secs.count() << " Seconds : " << ms.count() << " Milliseconds";
return ss.str();
}
live example.
Extending this to days/years/etc should be easy (there isn't a predefined std::chrono duration type for days/years/etc prior to c++20 however).
But I can do better.
template<class Duration>
struct split_duration {
Duration d;
std::chrono::milliseconds leftover;
split_duration( std::chrono::milliseconds ms ):
d( std::chrono::duration_cast<Duration>(ms) ),
leftover( ms - std::chrono::duration_cast<std::chrono::milliseconds>(d) )
{}
};
template<class...Durations>
std::tuple<Durations...> durations( std::chrono::milliseconds ms ) {
std::tuple<std::optional<split_duration<Durations>>...> tmp;
( (void)(
(void)std::get<std::optional<split_duration<Durations>>>(tmp).emplace( ms ),
ms = std::get<std::optional<split_duration<Durations>>>(tmp)->leftover
), ...
);
return std::make_tuple( std::get<std::optional<split_duration<Durations>>>( tmp )->d... );
}
template<class T>
struct tag_t {};
template<class T>
constexpr tag_t<T> tag = {};
inline std::string duration_name( tag_t<std::chrono::milliseconds> ) { return "ms"; }
inline std::string duration_name( tag_t<std::chrono::seconds> ) { return "Seconds"; }
inline std::string duration_name( tag_t<std::chrono::minutes> ) { return "Minutes"; }
inline std::string duration_name( tag_t<std::chrono::hours> ) { return "Hours"; }
// inline std::string duration_name( tag_t<std::chrono::days> ) { return "Days"; }
// inline std::string duration_name( tag_t<std::chrono::years> ) { return "Years"; }
template<class...Durations>
std::string format_duration( std::chrono::milliseconds ms ) {
auto split = durations<Durations...>(ms);
std::stringstream ss;
(
(void)( ss << duration_name(tag<Durations>) << ": " << std::get<Durations>(split).count() << " " ), ...
);
return ss.str();
}
Days/Years requires c++20, everything else is c++17.
You just call format_durations<Durations...>( some_ms ) and out comes a formatted string based off the Durations.... You do have to do it from most-to-least significant.
durations<Durations...> gives you a tuple breakdown of the time that has to be most-to-least; you could then reorder that before formatting if you chose.
Duplicate duration types leads to compile time errors, as std::get dies a horrible ambiguous death.
Live example.
Maybe you're looking for something like this:
#include <iostream>
using namespace std;
int main() {
//Value chosen to be 1 hour, 1 minute, 1 second, and 1 millisecond
long milli = 3661001;
//3600000 milliseconds in an hour
long hr = milli / 3600000;
milli = milli - 3600000 * hr;
//60000 milliseconds in a minute
long min = milli / 60000;
milli = milli - 60000 * min;
//1000 milliseconds in a second
long sec = milli / 1000;
milli = milli - 1000 * sec;
cout << hr << " hours and " << min << " minutes and " << sec << " seconds and " << milli << " milliseconds." << endl;
}
int milliseconds = ...;
int seconds = milliseconds / 1000;
milliseconds %= 1000;
int minutes = seconds / 60;
seconds %= 60;
int hours = minutes / 60;
minutes %= 60;
cout << hours << " Hours : " << minutes << " Minutes : " << seconds << " Seconds : " << milliseconds << " Milliseconds" << endl;
Not exactly what you're looking for, but if you're only accessing the current time, this will work:
#include <chrono>
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch());
const auto seconds = std::chrono::duration_cast<std::chrono::seconds>(ms);
ms -= seconds;
You can then add ms.count() to your cout, even if it isn't the actual remainder of the time you originally look at.
Edit: This method should be faster than using a modulus.
// Online IDE - Code Editor, Compiler, Interpreter
#include <stdio.h>
#include <stdint.h>
uint32_t DAYS_IN_MILLISECONDS = 86400000;
uint32_t HOURS_IN_MILLISECONDS = 3600000;
uint16_t MINUTES_IN_MILLISECONDS = 60000;
uint16_t SECONDS_IN_MILLISECONDS = 1000;
int main()
{
uint32_t total_milliseconds = 23*60*60000 + 100 + 1000;
uint8_t days = total_milliseconds / DAYS_IN_MILLISECONDS;
uint8_t hours = (total_milliseconds - days*DAYS_IN_MILLISECONDS) / HOURS_IN_MILLISECONDS;
uint8_t minutes = (total_milliseconds - days*DAYS_IN_MILLISECONDS - hours*HOURS_IN_MILLISECONDS) / MINUTES_IN_MILLISECONDS;
uint8_t seconds = (total_milliseconds - days*DAYS_IN_MILLISECONDS - hours*HOURS_IN_MILLISECONDS - minutes*MINUTES_IN_MILLISECONDS) / SECONDS_IN_MILLISECONDS;
uint8_t milliseconds = total_milliseconds - days*DAYS_IN_MILLISECONDS - hours*HOURS_IN_MILLISECONDS - minutes*MINUTES_IN_MILLISECONDS - seconds*SECONDS_IN_MILLISECONDS;
printf("%i:days %i:hours %i:minutes %i:seconds %i:milliseconds", days, hours, minutes, seconds, milliseconds);
return 0;
}
#ifndef DATETIME_H_
#define DATETIME_H_
/* Useful Constants */
#define SECS_PER_MIN (60UL)
#define SECS_PER_HOUR (3600UL)
#define SECS_PER_DAY (SECS_PER_HOUR * 24L)
#define DAYS_PER_WEEK (7L)
#define SECS_PER_WEEK (SECS_PER_DAY * DAYS_PER_WEEK)
#define SECS_PER_YEAR (SECS_PER_WEEK * 52L)
#define SECS_YR_2000 (946681200UL)
/* Useful Macros for getting elapsed time */
/** Get just seconds part of given Unix time */
#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN)
/** Get just minutes part of given Unix time */
#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN)
/** Get just hours part of given Unix time */
#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR)
/** Get day of week from given Unix time */
#define dayOfWeek(_time_) (( _time_ / SECS_PER_DAY + 4) % DAYS_PER_WEEK) // 0 = Sunday
/** Get elapsed days since 1970-01-01 from given Unix time */
#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY) // this is number of days since Jan 1 1970
/** Get quantity of seconds since midnight from given Unix time */
#define elapsedSecsToday(_time_) (_time_ % SECS_PER_DAY) // the number of seconds since last midnight
/** Get Unix time of midnight at start of day from given Unix time */
#define previousMidnight(_time_) (( _time_ / SECS_PER_DAY) * SECS_PER_DAY) // time at the start of the given day
/** Get Unix time of midnight at end of day from given just Unix time */
#define nextMidnight(_time_) ( previousMidnight(_time_) + SECS_PER_DAY ) // time at the end of the given day
/** Get quantity of seconds since midnight at start of previous Sunday from given Unix time */
#define elapsedSecsThisWeek(_time_) (elapsedSecsToday(_time_) + (dayOfWeek(_time_) * SECS_PER_DAY) )
#endif /* DATETIME_H_ */
Sample Code :
unsigned long long s = 1 * 10 ;
unsigned long long m = 1 * 60 * 20;
unsigned long long h = 1 * 60 * 60 * 3;
unsigned long long d = 1 * 60 * 60 * 24 * 60;
unsigned long long M = 1 * 60 * 60 * 24 * 30 * 5;
unsigned long long y = 1 * 60 * 60 * 24 * 30 * 12 * 6;
//unsigned long long timeInSec = s + m + h + d + M + y;
unsigned long long timeInSec = s + m + h + d;
long long seconds = numberOfSeconds(timeInSec);
long long minutes = numberOfMinutes(timeInSec);
long long hours = numberOfHours(timeInSec);
long long day = dayOfWeek(timeInSec);
long long _elapsedDays = elapsedDays(timeInSec);
long long _elapsedSecsToday = elapsedSecsToday(timeInSec);
Not that I do not find interesting the other solutions, and it is my humble monkey way of working... always very near of the assembly code ... in the previous solutions, there is way too many variables created to achieve the goal.. in my exemple, only 2 variables are created, a string: result, an int8_t: n, plus a parameter in the function declaration, so the milliseconds are passed to the function using a INT: value
#include <string>
using namespace std;
// milliseconds to DDD HH:MM:SS.mmm , days are displayed if > 0
string ToDDHHMMSSmmm(int value)
{
string result=""; uint8_t n=value/86400000;
if (n>0) {result=to_string(n)+' ';}
value-=86400000*n; n=value/3600000; if(n<10) result+='0';
result+=to_string(n); value-=3600000*n;
n=value/60000; result+=':'; if(n<10) result+='0';
result+=to_string(n); value-=60000*n;
n=value/1000; result+=':'; if(n<10) result+='0';
result+=to_string(n); value-=1000*n;
result+='.'; if(value<100) result+='0';
if(value<10) result+='0';
result+=to_string(value);
return result;
}
1- a string result is created empty
2- a byte (8 bit int) is created(n) as the milliseconds passed to the
int parameter named value is divided by 86400000 (representing
the quantity of millisec per day)
3- if n is greater than 0, the numbers of days(max 255 days !) is added
to the string result.
4- using the same variables, n(the previously calculated days) will be
multiplied by the same number, and the result is subtracted from the
variable value. now n is set to the value divided by 3600000.
5- if n<10, we have only one digit for the hours, so add a char '0' to
the string result.
6- and convert + add to the string the value of n.
7- same principle for the minutes, the seconds, and the last part
the 3 digit milliseconds.
8- the string is built as the calculation are done, and the return
string is always in the perfect format (DDD) HH:MM:SS.mmm
The bytes used are as follow int32 for the value 4
int8 for the work 1
String 13 to 16 max (if days > 0)
...for a total of 21 Bytes, the large numbers are never stored in variables, they remain in the code and are calculated in the register of the cpu or mcu only. To be even nearer of ASSEMBLY, I should not used std::string and std::to_string, instead, pointers and using 0x20 for spaces, 0x3a for semi colons, and adding 0x30 to any digit values to create the ASCII directly in memory.
Two types of output
#include <iostream>
using namespace std;
int main() {
//Value chosen to be 1 hour, 1 minute, 1 second, and 1 millisecond
long milli = 3661001;
// hours
int hr = (milli / (1000 * 60 * 60)) % 24;
// minutes
int min = (milli / (1000 * 60)) % 60;
// seconds
int sec = (milli / 1000) % 60;
// milliseconds
int mill = milli % 1000;
char msg[10];
sprintf(
msg,
"%02d hours and %02d minutes and %02d seconds and %02d milliseconds.\n",
hr,
min,
sec,
mill
);
printf(msg);
cout << hr << " hours and " << min << " minutes and " << sec << " seconds and " << mill << " milliseconds." << endl;
}

How to include a leading zero when converting seconds to minutes and the remainder is less than 10 seconds?

My function turns seconds to minutes. The problem is, if I have a number where the remainder is less than 10, it will just give give me remainder without a 0 before the remainder.
For example,
368 seconds would just turn to 6:8
360 would turn to 6:0
361 to 6:1
I would like
368 seconds to turn to 6:08
360 to 6:00
361 to 6:01
void toMinutesAndSeconds(int inSeconds, int &outMinutes, int &outSeconds) {
outMinutes = inSeconds / 60;
outSeconds = inSeconds % 60;
}
I'm outputting to a text file.
That's a matter of how you output your values. That value itself doesn't have "leading zeros".
#include <iostream>
#include <iomanip>
void toMinutesAndSeconds(int inSeconds, int &outMinutes, int &outSeconds)
{
outMinutes = inSeconds / 60;
outSeconds = inSeconds % 60;
}
int main()
{
int minutes = 0;
int seconds = 0;
toMinutesAndSeconds(368, minutes, seconds);
std::cout << std::setfill('0') << std::setw(2) << minutes << ":"
<< std::setfill('0') << std::setw(2) << seconds;
return 0;
}
prints
06:08