-3

I've got a double containing a number of seconds, which may be negative, and I'd like a string in the format H:mm:ss.hhh or -H:mm:ss.hhh

std::string getFormattedTime(double seconds)
{
 // magic voodoo
}

I'm going to need to omit the hour if it's zero.

I've buggered it up twice with various rounding and precision problems, so I figured it was time to ask for help :)

std::string getLabelForPosition(double seconds)
{
    bool negative = seconds < 0.0;

    if (negative)
        seconds *= -1.0;

    double mins = std::floor(std::round(seconds) / 60.0);
    double secs = seconds - mins * 60.0;

    std::stringstream s; 

    if (negative)
        s << "-";

    s << mins << ":" << std::fixed << std::setprecision(decimalPlaces) << secs; 


    return s.str();
}
JCx
  • 2,689
  • 22
  • 32
  • Well first, you would want to create a blanks string inside the function. Then I would refer to this page for appending ints to strings. https://stackoverflow.com/questions/45505477/append-int-to-stdstring After reading that, its just a matter of doing all the unit conversions and appending them together with the appropriate punctuation. –  Aug 25 '17 at 15:48

3 Answers3

2

Let me know if this works for you. I bet there is an easier way.

std::string getFormattedTime(double seconds)
{
    double s(fabs(seconds));
    int h(s/3600);
    int min(s/60 - h*60);
    double sec(s - (h*60 + min)*60);
    std::ostringstream oss;
    oss<<std::setfill('0')<<std::setw(2)<<fabs(seconds)/seconds*h<<":"<<std::setw(2)<<min<<":";
    if (sec/10<1)
        oss<<"0";
    oss<<sec;
    return oss.str().c_str();
}
apalomer
  • 1,895
  • 14
  • 36
  • 1
    More or less. I'll post the working solution as an answer, but it pretty much follows this pattern. – JCx Aug 25 '17 at 16:41
1

Here is a solution using boost. Suppose you have boost::uint64_t secondsSinceEpoch representing the number of seconds since epoch ( personally I didn't get your idea for using double in this case, sorry ). Then to get a string representation just use boost::posix_time::to_simple_string(secondsSinceEpoch);

Dmitry
  • 1,912
  • 2
  • 18
  • 29
  • It's close actually. I've not got boost as a dependency right now otherwise this might be a great solution. Seconds are in doubles because we are dealing with fractions of seconds. – JCx Aug 25 '17 at 16:11
  • 1
    dealing with time is a peace of cake for boost::posix_time::ptime. do not reinvent the wheel – Dmitry Aug 25 '17 at 16:19
  • I've just found this which looks very close: https://stackoverflow.com/questions/42138599/how-to-format-stdchrono-durations – JCx Aug 25 '17 at 16:23
0
std::string getLabelForPosition(double doubleSeconds)
{
    int64 msInt = int64(std::round(doubleSeconds * 1000.0));

    int64 absInt = std::abs(msInt);

    std::stringstream s; 

    if (msInt < 0)
        s << "-";

    auto hours = absInt / (1000 * 60 * 60);
    auto minutes = absInt / (1000 * 60) % 60;
    auto secondsx = absInt / 1000 % 60;
    auto milliseconds = absInt % 1000;


    if (hours > 0)
        s << std::setfill('0')
        << hours
        << "::";

    s << minutes
        << std::setfill('0')
        << ":"
        << std::setw(2)
        << secondsx
        << "."
        << std::setw(3)
        << milliseconds;

    return s.str();
}

This is pretty much right. The actual implementation uses a cache to avoid doing all the manipulation all over again when the screen re-renders.

JCx
  • 2,689
  • 22
  • 32