Split down a number in seconds to days, hours, minutes, and seconds?

前端 未结 3 989
天涯浪人
天涯浪人 2021-02-02 17:06

I\'ve heard that it\'s possible to accomplish this using the modulus % operator present in most programming languages. The real question is, how? I\'m unfamiliar wi

相关标签:
3条回答
  • 2021-02-02 17:45

    Whenever converting from a small base unit (seconds) to a series of larger units (minutes/hours/days/years/decades/centuries/millennia) you can use the modulo (%) operator to keep track of the remaining base units as you extract each large unit.

    It is an elegant/simple way to keep a sort of running total in base units. Start extracting BaseUnits with the largest unit you want and work your way back down until you get to the original BaseUnit.

    This only works when the extracted unit is nonzero. If it's zero then you have extracted no base units at all and don't need the modulo operator.

    It is important to remember that the result of the modulo operation will always be in the original base unit. That can get confusing.

    Let's restate 1 million seconds as larger time units. Let 1 year = 31,536,000 seconds and no leap years or other calendar adjustments.

    #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);
    }
    
    0 讨论(0)
  • 2021-02-02 17:47

    When you do integer division, you get quotient and remainder. For example,

    5 divided by 3 is quotient 1 with remainder 2.
    

    In programming languages, this is usually expressed as:

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

    The conversion you want is just a repeatation of this. It's easier to to start from the lower unit and go higher on.

    First, you have

    • 1307758473.484 seconds

    Since 60 seconds is 1 minute, and

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

    it is the same as

    • 21795974 minutes 33.484 seconds

    Since 60 minutes is 1 hour, and

    21795974 / 60 = 363266
    21795974 % 60 = 14
    

    it is further the same as

    • 363266 hours 14 minutes 33.484 seconds

    Now, there is a little bit of difficulty. Most days are 24 hours. When there is a leap second, it is not. If you ignore leap seconds and assume 1 day is 24 hours, then, by doing the calculation,

    363266 / 24 = 15136
    363266 % 24 = 2
    

    it is further the same as

    • 15136 days 2 hours 14 minutes 33.484 seconds.

    Similarly, Most years are 365 days. When there is a leap day (year), it is not. If you ignore leap days and assume that 1 year is 365 days, then by doing the calculation,

    15136 / 365 = 41
    15136 % 365 = 171
    

    it is further the same as

    • 41 years 171 days 2 hours 14 minutes 33.483 seconds
    0 讨论(0)
  • 2021-02-02 18:02

    Modulus returns the remainder when performing integer division.

    I think its easiest to understand how to use Mod by working backwards through a problem first.

    Lets start simple with hours, minutes and seconds - 1 hour, 10 minutes and 30 seconds to be precise.

    First, you have 30 seconds. This is easy - it's just 30. No brainer. Now add minutes - to determine minutes as seconds you multiply them times 60. Thus 10 minutes and 30 seconds = 630 seconds.

    Now we see how mod works - because if you divide 630 by 60 you get 10.5 but if you ignore the fraction (whole integer division) you get 10. The remainder is the seconds.

    So if you MOD 630 by 60 you get 30 - the remainder left over when dividing 630 by 30.

    So to determine minutes and seconds, divide by 60 for the minutes, and mod by 60 for the seconds.

    Now add an hour. One hour = 60 minutes and 60 minutes is 60*60 seconds so 1 hour = 3600 seconds. 3600 + 600 + 30 = 4230 seconds.

    4230 / 3600 (1 hour) = 1 - so we have one hour

    4230 % (mod) 3600 = 630 - grab this and now we process for minutes.

    So if you flesh this out further and add a day - 1 day = 24 hours = 24*3600 = 86400 86400+3600+600+30 = 90630

    90630 / 86400 = 1 -> 1 day

    90630 % 86400 = 4230 -> seconds left over

    4230 / 3600 = 1 -> 1 hour

    and repeat the above logic.

    Hope that helps clear it up - you keep repeating that iteration further and you can do weeks and years, but months are special since they're irregular, and so are leap years.

    0 讨论(0)
提交回复
热议问题