【问题标题】:From milliseconds to hour, minutes, seconds and milliseconds从毫秒到小时、分钟、秒和毫秒
【发布时间】:2012-06-08 02:20:53
【问题描述】:

我需要从毫秒到代表相同时间量的(小时、分钟、秒、毫秒)的元组。例如:

10799999ms = 2h 59m 59s 999ms

下面的伪代码是我唯一能想到的:

# The division operator below returns the result as a rounded down integer
function to_tuple(x):
    h = x / (60*60*1000)
    x = x - h*(60*60*1000)
    m = x / (60*1000)
    x = x - m*(60*1000)
    s = x / 1000
    x = x - s*1000
    return (h,m,s,x)

我确信它一定可以做得更智能/更优雅/更快/更紧凑。

【问题讨论】:

  • 您可以使用模运算符(C 和朋友中的 % )稍微简化 x 的计算(例如 x = x % (60*60*1000) )
  • 确保您使用的标准语言库中没有此类功能。

标签: algorithm date pseudocode


【解决方案1】:

这是我在 Java 中的做法:

int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours   = (int) ((milliseconds / (1000*60*60)) % 24);

【讨论】:

  • 在java中使用TimeUnit让代码更具可读性是值得的。
  • long millis = 12884983; System.out.println(((millis / (1000 * 60)) % 60)); System.out.println(java.util.concurrent.TimeUnit.MILLISECONDS.toMinutes(millis)); 输出:34 | 214
【解决方案2】:

好问题。是的,可以更有效地做到这一点。您的 CPU 可以在一次操作中提取两个整数之比的商和余数。在<stdlib.h> 中,公开此CPU 操作的函数称为div()。在你的伪代码中,你会像这样使用它:

function to_tuple(x):
    qr = div(x, 1000)
    ms = qr.rem
    qr = div(qr.quot, 60)
    s  = qr.rem
    qr = div(qr.quot, 60)
    m  = qr.rem
    h  = qr.quot

效率较低的答案是分别使用/% 运算符。但是,无论如何,如果您需要商和余数,那么您不妨调用更高效的div()

【讨论】:

    【解决方案3】:

    也许可以更短更优雅。但我做到了。

    public String getHumanTimeFormatFromMilliseconds(String millisecondS){
        String message = "";
        long milliseconds = Long.valueOf(millisecondS);
        if (milliseconds >= 1000){
            int seconds = (int) (milliseconds / 1000) % 60;
            int minutes = (int) ((milliseconds / (1000 * 60)) % 60);
            int hours = (int) ((milliseconds / (1000 * 60 * 60)) % 24);
            int days = (int) (milliseconds / (1000 * 60 * 60 * 24));
            if((days == 0) && (hours != 0)){
                message = String.format("%d hours %d minutes %d seconds ago", hours, minutes, seconds);
            }else if((hours == 0) && (minutes != 0)){
                message = String.format("%d minutes %d seconds ago", minutes, seconds);
            }else if((days == 0) && (hours == 0) && (minutes == 0)){
                message = String.format("%d seconds ago", seconds);
            }else{
                message = String.format("%d days %d hours %d minutes %d seconds ago", days, hours, minutes, seconds);
            }
        } else{
            message = "Less than a second ago.";
        }
        return message;
    }
    

    【讨论】:

      【解决方案4】:

      不是很优雅,但会更短一些

      function to_tuple(x):
         y = 60*60*1000
         h = x/y
         m = (x-(h*y))/(y/60)
         s = (x-(h*y)-(m*(y/60)))/1000
         mi = x-(h*y)-(m*(y/60))-(s*1000)
      
         return (h,m,s,mi)
      

      【讨论】:

        【解决方案5】:
        milliseconds = x
        total = 0
        while (milliseconds >= 1000) {
          milliseconds = (milliseconds - 1000)
          total = total + 1
        }
        hr = 0
        min = 0
        while (total >= 60) {
          total = total - 60
          min = min + 1
          if (min >= 60) hr = hr + 1
          if (min == 60) min = 0
        }
        sec = total
        

        这是 groovy,但我认为这对你来说不是问题。方法完美。

        【讨论】:

          【解决方案6】:
          milliseconds = 12884983  // or x milliseconds
          hr = 0
          min = 0
          sec = 0 
          day = 0
          while (milliseconds >= 1000) {
            milliseconds = (milliseconds - 1000)
            sec = sec + 1
            if (sec >= 60) min = min + 1
            if (sec == 60) sec = 0
            if (min >= 60) hr = hr + 1
            if (min == 60) min = 0
            if (hr >= 24) {
              hr = (hr - 24)
              day = day + 1
            }
          }
          

          希望我的短方法能帮到你

          【讨论】:

            【解决方案7】:
            import java.text.SimpleDateFormat;
            import java.util.Date;
            import java.util.concurrent.TimeUnit;
            
            public class MyTest {
            
                public static void main(String[] args) {
                    long seconds = 360000;
            
                    long days = TimeUnit.SECONDS.toDays(seconds);
                    long hours = TimeUnit.SECONDS.toHours(seconds - TimeUnit.DAYS.toSeconds(days));
            
                    System.out.println("days: " + days);
                    System.out.println("hours: " + hours);
                }
            }
            

            【讨论】:

              【解决方案8】:

              基于 Valentinos 答案的 Arduino (c++) 版本

              unsigned long timeNow = 0;
              unsigned long mSecInHour = 3600000;
              unsigned long TimeNow =0;
              int millisecs =0;  
              int seconds = 0;
              byte minutes = 0;
              byte hours = 0;
              
              void setup() {
              Serial.begin(9600);
              Serial.println (""); // because arduino monitor gets confused with line 1
              Serial.println ("hours:minutes:seconds.milliseconds:");
              }
              
              void loop() {
              TimeNow = millis(); 
              hours = TimeNow/mSecInHour;
              minutes = (TimeNow-(hours*mSecInHour))/(mSecInHour/60);
              seconds = (TimeNow-(hours*mSecInHour)-(minutes*(mSecInHour/60)))/1000;
              millisecs = TimeNow-(hours*mSecInHour)-(minutes*(mSecInHour/60))-       (seconds*1000);
              
              Serial.print(hours);  
              Serial.print(":");
              Serial.print(minutes);
              Serial.print(":"); 
              Serial.print(seconds); 
              Serial.print("."); 
              Serial.println(millisecs); 
              }
              

              【讨论】:

                【解决方案9】:

                只是另一个 java 示例:

                long dayLength = 1000 * 60 * 60 * 24;
                long dayMs = System.currentTimeMillis() % dayLength;
                double percentOfDay = (double) dayMs / dayLength;
                int hour = (int) (percentOfDay * 24);
                int minute = (int) (percentOfDay * 24 * 60) % 60;
                int second = (int) (percentOfDay * 24 * 60 * 60) % 60;
                

                如果你调整dayLength,你可以模拟更短的天数

                【讨论】:

                  【解决方案10】:

                  Kotlin 示例,其前导零的小时/分钟/秒小于 10。因此,如果您想在 UI 中将该值用作字符串,那么您最终会得到相同的持续时间。

                  这给出了 01:57:01 而不是 1:57:1,这可能会混淆 hh:mn:ss 注释。

                  val timeInMilliSec = 45600030
                  
                  val hours = timeInMilliSec.div(3600).rem(24)
                  val minutes = timeInMilliSec.div(60).rem(60)
                  val seconds = timeInMilliSec.rem(60)
                  
                  val hoursFormatted = if (hours < 10) "0$hours" else "$hours"
                  val minutesFormatted = if (minutes < 10) "0$minutes" else "$minutes"
                  val secondsFormatted = if (seconds < 10) "0$seconds" else "$seconds"
                  
                  "$hoursFormatted:$minutesFormatted:$secondsFormatted"
                  
                                          
                  

                  【讨论】: