【问题标题】:milliseconds to days毫秒到天
【发布时间】:2011-10-19 23:45:59
【问题描述】:

我做了一些研究,但仍然找不到如何获得这些日子...这是我得到的:

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

请帮忙,我数学很烂,谢谢。

【问题讨论】:

  • 来自wikipedia:86,400,000 (24×60×60×10×10×10) 毫秒——一天

标签: java math time milliseconds


【解决方案1】:

对于这种简单的情况,应该使用TimeUnit。与显式执行所有算术计算相比,TimeUnit 的使用对所表示的内容更加明确,并且也更容易读写。例如,要从毫秒计算天数,可以使用以下语句:

    long days = TimeUnit.MILLISECONDS.toDays(milliseconds);

对于更高级的情况,需要在处理时间的上下文中表示更细粒度的持续时间,应使用包罗万象的现代日期/时间 API。对于 JDK8+,现在包含 java.time(这里是 tutorialsjavadocs)。对于早期版本的 Java,joda-time 是一个可靠的替代方案。

【讨论】:

  • 如果您使用的是 Android,这需要 API 级别 9
  • TimeUnit 不会正确舍入。所以 129600000l,即 1.5 天,将返回 1,而不是 2。
  • @katsharp 这可能取决于特定情况下舍入的正确定义。我最初的答案只是为了解决原始问题中的简单案例。对于更复杂的情况,例如准确表示 1.5 天,我建议使用 JDK8+ 中的 java.time 或 joda-time(如果您使用的是较旧的 java 版本)。我会修改我的答案以提出建议。
【解决方案2】:

如果您没有大于天的其他时间间隔:

int days = (int) (milliseconds / (1000*60*60*24));

如果你也有几个星期:

int days = (int) ((milliseconds / (1000*60*60*24)) % 7);
int weeks = (int) (milliseconds / (1000*60*60*24*7));

可能最好避免使用月份和年份,因为它们没有明确定义的固定长度。严格来说,天也不行:夏令时意味着天的长度可以不是 24 小时。

【讨论】:

【解决方案3】:

在 java 中使用 TImeUnit

为了导入使用,java.util.concurrent.TimeUnit

long millisec=System.currentTimeMillis();
long seconds=TimeUnit.MILLISECONDS.toSeconds(millisec);
long minutes=TimeUnit.MILLISECONDS.toMinutes(millisec);
long hours=TimeUnit.MILLISECONDS.toMinutes(millisec);
long days=TimeUnit.MILLISECONDS.toDays(millisec);

【讨论】:

    【解决方案4】:

    java.time

    您可以使用java.time.Duration,它以ISO-8601 standards 为蓝本,并作为JSR-310 implementation 的一部分引入Java-8Java-9 引入了一些更方便的方法。

    演示:

    import java.time.Duration;
    
    public class Main {
        public static void main(String[] args) {
            // Duration between the two instants
            Duration duration = Duration.ofMillis(1234567890L);
    
            // Print Duration#toString
            System.out.println(duration);
    
            // Custom format
            // ####################################Java-8####################################
            String formattedElapsedTime = String.format(
                    "%d Day %02d Hour %02d Minute %02d Second %d Millisecond (%d Nanosecond)", duration.toDays(),
                    duration.toHours() % 24, duration.toMinutes() % 60, duration.toSeconds() % 60,
                    duration.toMillis() % 1000, duration.toNanos() % 1000000000L);
            System.out.println(formattedElapsedTime);
            // ##############################################################################
    
            // ####################################Java-9####################################
            formattedElapsedTime = String.format("%d Day %02d Hour %02d Minute %02d Second %d Millisecond (%d Nanosecond)",
                    duration.toDaysPart(), duration.toHoursPart(), duration.toMinutesPart(), duration.toSecondsPart(),
                    duration.toMillisPart(), duration.toNanosPart());
            System.out.println(formattedElapsedTime);
            // ##############################################################################
        }
    }
    

    示例运行:

    PT342H56M7.89S
    14 Day 06 Hour 56 Minute 07 Second 890 Millisecond (890000000 Nanosecond)
    14 Day 06 Hour 56 Minute 07 Second 890 Millisecond (890000000 Nanosecond)
    

    Trail: Date Time 了解有关现代日期时间 API 的更多信息。

    【讨论】:

      【解决方案5】:
      int days = (int) (milliseconds / 86 400 000 )
      

      【讨论】:

        【解决方案6】:
        public static final long SECOND_IN_MILLIS = 1000;
        public static final long MINUTE_IN_MILLIS = SECOND_IN_MILLIS * 60;
        public static final long HOUR_IN_MILLIS = MINUTE_IN_MILLIS * 60;
        public static final long DAY_IN_MILLIS = HOUR_IN_MILLIS * 24;
        public static final long WEEK_IN_MILLIS = DAY_IN_MILLIS * 7;
        

        你可以投射 int 但我建议使用 long

        【讨论】:

          【解决方案7】:

          你不能。对不起。或者更准确地说:如果您知道时区和开始时间(或结束时间),则可以。一天可能有 23、24 或 25 小时或其他一些长度。因此,没有任何可靠的公式可以将毫秒转换为天。因此,虽然您可以安全地依赖一秒 1000 毫秒、一分钟 60 秒(以下预留)和一小时 60 分钟,但转换为天需要更多上下文才能确定和准确。

          保留:在现实生活中,由于闰秒,一分钟有时是 61 秒。不是在 Java 中。 Java 总是将一分钟计为 60 秒,因为普通的计算机时钟不知道闰秒。常见的操作系统和 Java 本身不仅知道夏令时 (DST),而且还知道许多其他导致一天短于或长于 24 小时的时间线异常。

          演示。我写这篇文章的时间是 2021 年 3 月 29 日,也就是我的时区欧洲/哥本哈根和欧盟其他地区切换到夏令时的第二天。

              ZoneId myTimeZone = ZoneId.of("Europe/Copenhagen");
              ZonedDateTime now = ZonedDateTime.now(myTimeZone);
              ZonedDateTime twoDaysAgo = now.minusDays(2);
              ZonedDateTime inTwoDays = now.plusDays(2);
              
              System.out.println(ChronoUnit.MILLIS.between(twoDaysAgo, now));
              System.out.println(ChronoUnit.MILLIS.between(now, inTwoDays));
          

          输出:

          169200000
          172800000
          

          所以两天是多少毫秒取决于你指的是哪两天。以及在哪个时区。

          那该怎么办?

          1. 如果出于您的目的,您可以始终安全地将一天定义为 24 小时,例如因为您的天数以 UTC 计算,或者您的用户可以接受这种不准确,请使用 DurationTimeUnit。从 Java 9 开始,Duration 类还会告诉您除了一整天之外还有多少小时、分钟和秒。请参阅 Arvind Kumar Avinash 的答案。对于TimeUnit 枚举,请参阅whaley 和Dev Parzival 的答案。不管怎样,好消息是你数学很烂也没关系,因为数学会帮你搞定。

          2. 如果您知道时区和起点,请使用ZonedDateTimeChronoUnit.DAYS。在这种情况下,数学也会为您处理。

            ZonedDateTime start = LocalDate.of(2021, Month.MARCH, 28).atStartOfDay(myTimeZone);
            long millisToConvert = 170_000_000;
            
            ZonedDateTime end = start.plus(millisToConvert, ChronoUnit.MILLIS);
            long days = ChronoUnit.DAYS.between(start, end);
            System.out.format("%d days%n", days);
            
          2 days
          

          如果您还需要小时、分钟和秒:

              Duration remainingTime = Duration.between(start.plusDays(days), end);
              System.out.format(" - and an additional %s hours %d minutes %d seconds%n",
                      remainingTime.toHours(),
                      remainingTime.toMinutesPart(),
                      remainingTime.toSecondsPart());
          
           - and an additional 0 hours 13 minutes 20 seconds
          

          如果您有一个端点,请使用minus 方法(而不是上面代码中使用的plus 方法)从端点减去毫秒以获得起点。

          在任何情况下都不要像在问题和当前接受的答案中那样自己进行数学运算。它容易出错,并导致代码难以阅读。如果您的读者数学很烂,他或她可能会花费大量宝贵的开发人员时间来尝试验证您是否正确完成了它。将数学留给经过验证的库方法,您的读者会更容易相信您的代码是正确的。

          【讨论】:

            【解决方案8】:

            如果您在代码中解决更复杂的记录执行统计信息的任务:

            public void logExecutionMillis(LocalDateTime start, String callerMethodName) {
            
              LocalDateTime end = getNow();
              long difference = Duration.between(start, end).toMillis();
            
              Logger logger = LoggerFactory.getLogger(ProfilerInterceptor.class);
            
              long millisInDay = 1000 * 60 * 60 * 24;
              long millisInHour = 1000 * 60 * 60;
              long millisInMinute = 1000 * 60;
              long millisInSecond = 1000;
            
              long days = difference / millisInDay;
              long daysDivisionResidueMillis = difference - days * millisInDay;
            
              long hours = daysDivisionResidueMillis / millisInHour;
              long hoursDivisionResidueMillis = daysDivisionResidueMillis - hours * millisInHour;
            
              long minutes = hoursDivisionResidueMillis / millisInMinute;
              long minutesDivisionResidueMillis = hoursDivisionResidueMillis - minutes * millisInMinute;
            
              long seconds = minutesDivisionResidueMillis / millisInSecond;
              long secondsDivisionResidueMillis = minutesDivisionResidueMillis - seconds * millisInSecond;
            
              logger.info(
                  "\n************************************************************************\n"
                      + callerMethodName
                      + "() - "
                      + difference
                      + " millis ("
                      + days
                      + " d. "
                      + hours
                      + " h. "
                      + minutes
                      + " min. "
                      + seconds
                      + " sec."
                      + secondsDivisionResidueMillis
                      + " millis).");
            }
            

            附:如果您愿意,可以用简单的 System.out.println() 替换 Logger。

            【讨论】:

              猜你喜欢
              • 2023-02-08
              • 1970-01-01
              • 2014-10-12
              • 2012-06-08
              • 2018-11-05
              • 2012-09-27
              • 2017-12-11
              • 2016-03-14
              • 1970-01-01
              相关资源
              最近更新 更多