Конвертация из секунд в дни, часы, минуты и секунды

struct my_time {
    long long day, hour, minute, second;
    void set(long long t) {
        if (t>=0) {
            day = t/60/60/24;   
            hour = t/60/60-day*24;
            minute = t/60-hour*60-day*24*60;
            second = t-minute*60-hour*60*60-day*60*60*24;
        } else if (t%86400==0) {
            day=t/86400;
            hour=0;
            minute=0;
            second=0;
        } else  {
            day = -1;
            day += t/86400;
            hour = abs(t/60/60-24*day-1);
            minute = abs(t/60-hour*60-24*60*day-1);
            second = (abs(t-minute*60-hour*60*60-60*60*24*day-1)+1)%60;
        }
    }
};

Требуется написать структуру времени, метод set получает в параметры кол-во секунд в единицах. Ошибка возникает когда ввожу в метод, к примеру, -600. Поля становятся равными -1 23 49 0, а должны -1 23 50 0. Подскажите, в чём проблема.


Ответы (2 шт):

Автор решения: Павел Ериков

Напишу в виде ответа, только потому что мест в комментарии не хватает и не красиво. Вообще не презентую на правильный ответ) просто как идея.

Согласен с @wololo очень странная арифметика.

Но попробуйте сделать так:

Если t < 0, то

  1. Избавляемся от знака. -t
  2. Находим кол-во дней в t секундах, пусть будет day.
  3. Прибавляем к day + 1 и возьмем со знаком -.
  4. Отнимаем от t секунд, столько секунд, сколько их в day дней.
  5. Последняя операция это 1 0 0 0 - t(секунд). То есть 1 день - t секунд.

Надеюсь понятно объяснил идею.

Теперь проверим на примере. Пусть t = -2.

  1. t = -t = 2
  2. day = 0
  3. -(day + 1) = -1 - итоговое кол-во дней
  4. t - day * 24 * 60 * 60 = t, т.к. day = 0
  5. 1 0 0 0 - 0 0 0 2 = 0 23 59 58

Получаем ответ: -1 23 59 58

Еще один пример. Пусть t = -179429

  1. t = -t = 179429
  2. day = t / (24 * 60 * 60) = 2`
  3. -(day + 1) = -3 - итоговое кол-во дней
  4. t - day * 24 * 60 * 60 = 6629
  5. 1 0 0 0 - 0 1 50 29 = 0 22 09 31

Получаем ответ: -3 22 09 31 ???

То есть прибавим к этому времени 6629 секунд и получим -2 0 0 0, а потом останется еще 172800, ну и получим 0 0 0 0, вроде идея имеет место быть.

P.s. вместо 1 0 0 0 - t можно 0 23 59 59 так проще т.к. нужно всего лишь 23 - hours, 59 - minutes, 59 - seconds, и это будет работать потому что t < 86400

→ Ссылка
Автор решения: wololo

Полагаю, вам нужно что-то вроде такого:

#include <iostream>
#include <iomanip>
using std::cout;
using std::endl;

struct my_time {
    long long day, hour, minute, second;
    my_time& set(long long t) {
        const long long SECONDS_IN_MINUTE = 60LL;
        const long long SECONDS_IN_HOUR   = SECONDS_IN_MINUTE * 60LL;
        const long long SECONDS_IN_DAY    = SECONDS_IN_HOUR   * 24LL;
        
        day = t / SECONDS_IN_DAY;
        t -= day * SECONDS_IN_DAY;
        if (t < 0) {
            --day;
            t += SECONDS_IN_DAY;
        }
        
        hour = t / SECONDS_IN_HOUR;
        t -= hour * SECONDS_IN_HOUR;
        
        minute = t / SECONDS_IN_MINUTE;
        t -= minute * SECONDS_IN_MINUTE;
            
        second = t;
        
        return *this;
    }
};

std::ostream& operator<<(std::ostream& out, const my_time& mt) {
    out              << " " << std::setw(3);
    out << mt.day    << " " << std::setw(2);
    out << mt.hour   << " " << std::setw(2);
    out << mt.minute << " " << std::setw(2);
    out << mt.second;
    return out;
}

void print(long long t) {
    cout << "t: " << std::setw(7) << t << "     my_time: " << my_time().set(t) << endl;
}

int main() {
    const long long test[] = {
        600, -600, 0,
         1,  86399,  86400,  86401,  172799,  172800,  172801,
        -1, -86399, -86400, -86401, -172799, -172800, -172801
    };
    for (auto t: test)
        print(t);
}

Вывод:

t:     600     my_time:    0  0 10  0
t:    -600     my_time:   -1 23 50  0
t:       0     my_time:    0  0  0  0
t:       1     my_time:    0  0  0  1
t:   86399     my_time:    0 23 59 59
t:   86400     my_time:    1  0  0  0
t:   86401     my_time:    1  0  0  1
t:  172799     my_time:    1 23 59 59
t:  172800     my_time:    2  0  0  0
t:  172801     my_time:    2  0  0  1
t:      -1     my_time:   -1 23 59 59
t:  -86399     my_time:   -1  0  0  1
t:  -86400     my_time:   -1  0  0  0
t:  -86401     my_time:   -2 23 59 59
t: -172799     my_time:   -2  0  0  1
t: -172800     my_time:   -2  0  0  0
t: -172801     my_time:   -3 23 59 59
→ Ссылка