Разбить число в секундах на дни, часы, минуты и секунды? - PullRequest
10 голосов
/ 11 июня 2011

Я слышал, что это можно сделать, используя оператор модуля %, присутствующий в большинстве языков программирования.Настоящий вопрос в том, как?Я не знаю, как работает модуль, поэтому у меня были трудности с его использованием в прошлом.Учитывая текущее время здесь в секундах с 1970 года, 1307758473.484, как я могу рассчитать, сколько это лет, то есть дней, часов и минут, которые используют модуль?

По сути, я хочу отформатировать его так: «5 лет, 10 дней, 12 часов, 7 минут и 18,56 секунды».Как бы я это сделал?Я действительно заинтересован в изучении логики, лежащей в основе этого, а , а не , заинтересован в простом решении.

Ответы [ 3 ]

25 голосов
/ 11 июня 2011

Когда вы делаете целочисленное деление, вы получаете частное и остаток.Например,

5 divided by 3 is quotient 1 with remainder 2.

В языках программирования это обычно выражается как:

5 / 3   # => 1
5 % 3   # => 2

Требуемое преобразование является лишь повторением этого. Проще начать с нижней единицы и идти выше на .

Сначала у вас есть

  • 1307758473.484 seconds

Так как 60 секунд - это 1 минута, а

1307758473.484 / 60 = 21795974  (intended to be integer division)
1307758473.484 % 60 = 33.484,

- это то же самое, что

  • 21795974 minutes 33.484 seconds

Поскольку 60 минут - 1 часи

21795974 / 60 = 363266
21795974 % 60 = 14

это то же самое, что и

  • 363266 hours 14 minutes 33.484 seconds

Теперь есть небольшая сложность.Большинство дней 24 часа.Когда есть високосная секунда, это не так.Если вы игнорируете високосные секунды и предполагаете, что 1 день равен 24 часам, то, выполнив расчет,

363266 / 24 = 15136
363266 % 24 = 2

, он будет таким же, как

  • 15136 days 2 hours 14 minutes 33.484 seconds.

Аналогично, большинство лет составляют 365 дней.Когда есть високосный день (год), это не так.Если вы игнорируете високосные дни и предполагаете, что 1 год равен 365 дням, то, выполнив расчет,

15136 / 365 = 41
15136 % 365 = 171

он будет таким же, как

  • 41 years 171 days 2 hours 14 minutes 33.483 seconds
4 голосов
/ 11 июня 2011

Модуль возвращает остаток при выполнении целочисленного деления.

Я думаю, что проще всего понять, как использовать Mod, сначала работая с проблемой в обратном порядке.

Давайте начнем с простых часов, минут исекунды - 1 час, 10 минут и 30 секунд, если быть точным.

Сначала у вас есть 30 секунд.Это просто - всего 30. Понятно.Теперь добавьте минуты - чтобы определить минуты как секунды, вы умножаете их на 60. Таким образом, 10 минут и 30 секунд = 630 секунд.

Теперь мы видим, как работает мод - потому что если вы поделите 630 на60 вы получите 10,5, но если вы проигнорируете дробь (целое целое деление), вы получите 10. Остальные - секунды.

Так что, если вы MOD 630 на 60, вы получите 30 - остаток останется при делении 630 на30.

Таким образом, чтобы определить минуты и секунды, разделите на 60 для минут и установите мод на 60 для секунд.

Теперь добавьте час.Один час = 60 минут, а 60 минут - 60 * 60 секунд, поэтому 1 час = 3600 секунд.3600 + 600 + 30 = 4230 секунд.

4230/3600 (1 час) = 1 - поэтому у нас есть один час

4230% (мод) 3600 = 630 - захватите это, и теперь мыпроцесс за минуты.

Так что, если вы укажете это дальше и добавите день - 1 день = 24 часа = 24 * 3600 = 86400 86400 + 3600 + 600 + 30 = 90630

90630 /86400 = 1 -> 1 день

90630% 86400 = 4230 -> секунд осталось

4230/3600 = 1 -> 1 час

и повторите приведенную выше логику.

Надеюсь, что это поможет прояснить ситуацию - вы продолжаете повторять эту итерацию дальше, и вы можете делать недели и годы, но месяцы особенные, поскольку они нерегулярны, и поэтому - високосные годы.

0 голосов
/ 25 марта 2019

Всякий раз, когда вы переходите с небольшой базовой единицы (секунды) на серию больших единиц (минуты / часы / дни / годы / десятилетия / века / тысячелетия), вы можете использовать оператор по модулю (%), чтобы отслеживать оставшуюся базу единицы, как вы извлекаете каждую большую единицу.

Это элегантный / простой способ сохранить некоторый промежуточный итог в базовых единицах. Начните извлекать BaseUnits с самым большим модулем, который вам нужен, и возвращайтесь вниз, пока не доберетесь до исходного BaseUnit.

Это работает, только когда извлеченная единица отлична от нуля. Если он равен нулю, то вы вообще не извлекли базовые единицы и вам не нужен оператор по модулю.

Важно помнить, что результат операции по модулю всегда будет в исходном базовом блоке. Это может запутать.

Давайте пересчитаем 1 миллион секунд как большие единицы времени. Пусть 1 год = 31 536 000 секунд, без високосных лет или других календарных корректировок.

#include <cstdio>
#define SEC2CENT 3153600000
#define SEC2DEC 315360000
#define SEC2YR 31536000
#define SEC2MONTH 2592000
#define SEC2WEEK 604800
#define SEC2DAY 86400
#define SEC2HOUR 3600
#define SEC2MIN 60
main()
{
unsigned int sec = 1000000; //I am 1 million seconds old or...

unsigned int centuries = sec / SEC2CENT;
if (centuries) sec = sec % SEC2CENT; //if nonzero update sec

unsigned int decades = sec / SEC2DEC;
if (decades) sec = sec % SEC2DEC; //the purpose of modulo for units is this running total of base units

unsigned int years = sec / SEC2YR;
if (years) sec = sec % SEC2YR;

unsigned int months = sec / SEC2MONTH;
if (months) sec = sec % SEC2MONTH;

unsigned int weeks = sec / SEC2WEEK;
if (weeks) sec = sec % SEC2WEEK;

unsigned int days = sec / SEC2DAY;
if (days) sec = sec % SEC2DAY;

unsigned int hours = sec / SEC2HOUR;
if (hours) sec = sec % SEC2HOUR;

unsigned int minutes = sec / SEC2MIN;
if (minutes) sec = sec % SEC2MIN;

unsigned int seconds = sec; //seconds should now be less than 60 because of minutes

printf("I am now exactly %u centuries, %u decades, %u years, %u months, %u weeks, %u days, %u hours, %u minutes, %u seconds old and that is very old indeed.", centuries, decades, years, months, weeks, days, hours, minutes, seconds);
}
...