我想要这样的东西:

public class Stream
{
    public startTime;
    public endTime;

    public getDuration()
    {
        return startTime - endTime;
    }
}

同样重要的是,例如,如果startTime是23:00,endTime是1:00,则持续时间为2:00。

为了在Java中实现这一点,应该使用哪些类型?


当前回答

博士tl;

例如,如果startTime是23:00,endTime是1:00,则持续时间为2:00。

不可能的。如果你只有一天中的时间,时钟在午夜停止。如果没有日期的背景,我们怎么知道你说的是第二天凌晨1点,下一周,还是下一个十年?

所以从晚上11点到凌晨1点意味着时间倒退了22个小时,逆时针走时针。请看下面的结果,是负22小时。

Duration.between(              // Represent a span of time a total number of seconds plus a fractional second in nanoseconds.
    LocalTime.of( 23 , 0 ) ,   // A time-of-day without a date and without a time zone. 
    LocalTime.of( 1 , 0 )      // A time-of-day clock stops at midnight. So getting to 1 AM from 11 PM means going backwards 22 hours.
)                              // Return a `Duration` object.
.toString()                    // Generate a `String` representing this span of time using standard ISO 8601 format: PnYnMnDTnHnMnS

PT-22H

跨越午夜除了需要时间之外,还需要更大的日期上下文(见下文)。

如何在Java中测量时间流逝?

使用Instant.now()捕获UTC的当前时刻。 以后再捕捉这样的时刻。 将两者传递给Duration.between。 (a)从生成的Duration对象中,通过调用各种to…Part方法,提取24小时的天、小时、分、秒和以纳秒为单位的分数秒。

示例代码,使用一对即时对象。

Duration.between(    // Represent a span of time a total number of seconds plus a fractional second in nanoseconds.
    then ,           // Some other `Instant` object, captured earlier with `Instant.now()`.
    Instant.now()    // Capture the current moment in UTC with a resolution as fine as nanoseconds, depending on the limits of your host computer hardware clock and operating system. Generally you will get current moment in microseconds (six decimal digits of fractional second) in Java 9, 10, and 11, but only milliseconds in Java 8. 
)                    // Return a `Duration` object.
.toString()          // Generate a `String` representing this span of time using standard ISO 8601 format: PnYnMnDTnHnMnS

PT3M27.602197S

Java 8+中的新技术

我们在Java 8和以后的版本中都有新的技术。时间框架。

java.time

java。时间框架由JSR 310定义,其灵感来自于非常成功的Joda-Time项目,由ThreeTen-Extra项目扩展,并在Oracle教程中进行了描述。

旧的日期时间类,如java.util.Date/。与早期版本的Java捆绑在一起的日历被证明设计得很糟糕,令人困惑,而且很麻烦。它们被爪哇取代了。时间类。

决议

其他答案讨论解决方案。

java。时间类具有纳秒分辨率,最高可达秒的小数部分的9位。例如:2016-03-12T04:29:39.123456789Z。

旧的java.util.Date/。Calendar类和Joda-Time类具有毫秒级分辨率(3位分数)。例如:2016-03-12T04:29:39.123Z。

在Java 8中,由于遗留问题,当前时刻只能以毫秒的分辨率获取。在Java 9及以后版本中,如果您的计算机硬件时钟运行得非常好,则可以以纳秒的分辨率确定当前时间。

1)

如果您确实希望只使用一天中的时间,而不使用任何日期或时区,请使用LocalTime类。

LocalTime sooner = LocalTime.of ( 17, 00 );
LocalTime later = LocalTime.of ( 19, 00 );

Duration表示一段时间,它以秒加纳秒的形式表示。

Duration duration = Duration.between ( sooner, later );

转储到控制台。

System.out.println ( "sooner: " + sooner + " | later: " + later + " | duration: " + duration );

sooner: 17:00 | later: 19:00 | duration: PT2H

ISO 8601

注意Duration::toString的默认输出是标准的ISO 8601格式。在这种格式中,P标记开始(如在“Period”中),T将任何年-月-日部分与小时-分钟-秒部分分开。

过午夜

不幸的是,只有当你绕过午夜时,处理一天中的时间才会变得棘手。LocalTime类通过假设您想要返回到当天的早些时候来处理这个问题。

使用与上面相同的代码,但从23:00到01:00,结果是负22小时(PT-22H)。

LocalTime sooner = LocalTime.of ( 23, 0 );
LocalTime later = LocalTime.of ( 1, 0 );

早:23:00 |晚:01:00 |持续时间:PT-22H

日期-时间

如果您打算越过午夜,那么使用日期时间值而不是仅使用日期时间值可能更有意义。

时区

时区对约会至关重要。因此,我们指定三个项目:(1)所需的日期,(2)所需的时间,以及(3)时区作为解释该日期和时间的上下文。这里我们任意选择Montréal区域的时区。

如果您仅通过从utc的偏移量定义日期,则使用带OffsetDateTime的ZoneOffset。如果您有一个完整的时区(偏移量加上处理异常(如日光节约时间)的规则),则使用ZoneId和zoneeddatetime。

LocalDate localDate = LocalDate.of ( 2016, 1, 23 );
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime sooner = ZonedDateTime.of ( localDate, LocalTime.of ( 23, 0 ), zoneId );

我们指定较晚的时间为第二天凌晨1点。

ZonedDateTime later = ZonedDateTime.of ( localDate.plusDays ( 1 ), LocalTime.of ( 1, 0 ), zoneId );

我们用上面看到的同样的方式计算Duration。现在我们有两个小时的时间来回答这个问题。

Duration duration = Duration.between ( sooner, later );

转储到控制台。

System.out.println ( "sooner: " + sooner + " | later: " + later + " | duration: " + duration );

早:2016-01-23T23:00-05:00[美国/蒙特利尔]|晚:2016-01-24T01:00-05:00[美国/蒙特利尔]|时长:PT2H

日光节约时间

如果手边的日期时间涉及日光节约时间(DST)或其他类似的异常情况,java。时间类别将根据需要调整。详细信息请阅读类文档。


关于java.time

java。时间框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期-时间类,如java.util。日期,日历和简单日期格式。

Joda-Time项目现在处于维护模式,建议迁移到java。时间类。

要了解更多,请参阅Oracle教程。搜索Stack Overflow可以找到很多例子和解释。规范是JSR 310。

你可以交换java。Time对象直接使用数据库。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,不需要java。sql。*类。

从哪里获取java。时间类?

Java SE 8、Java SE 9、Java SE 10以及更高版本 内置的。 带有捆绑实现的标准Java API的一部分。 Java 9增加了一些小特性并进行了修复。 Java SE 6和Java SE 7 大部分的java。时间功能在ThreeTen-Backport中向后移植到Java 6和7。 安卓 后续版本的Android捆绑实现的java。时间类。 对于早期的Android (<26), ThreeTenABP项目适应ThreeTen-Backport(如上所述)。参见如何使用ThreeTenABP....

ThreeTen-Extra项目扩展了java。额外的课程时间。这个项目是未来可能添加到java.time的一个试验场。你可以在这里找到一些有用的类,比如Interval、YearWeek、YearQuarter等等。

其他回答

如果您正在编写一个必须处理持续时间的应用程序,那么请查看Joda-Time,它有专门处理持续时间、间隔和周期的类。你的getDuration()方法看起来可以返回一个Joda-Time Interval:

DateTime start = new DateTime(2004, 12, 25, 0, 0, 0, 0);
DateTime end = new DateTime(2005, 1, 1, 0, 0, 0, 0);

public Interval getInterval() {
    Interval interval = new Interval(start, end);
}

Java提供了静态方法System.currentTimeMillis()。这返回一个长值,所以这是一个很好的参考。很多其他类也接受'timeInMillis'形参,这个形参也很长。

许多人发现使用Joda Time库更容易计算日期和时间。

Byte Stream Reader Elapsed Time for 23.7 MB is 96 secs

import java.io.*;
import java.io.IOException;
import java.util.Scanner;

class ElaspedTimetoCopyAFileUsingByteStream
{

    private long startTime = 0;
    private long stopTime = 0;
    private boolean running = false;


    public void start() 
    {
        this.startTime = System.currentTimeMillis();
        this.running = true;
    }


    public void stop() 
    {
        this.stopTime = System.currentTimeMillis();
        this.running = false;
    }



    public long getElapsedTime() 
    {
        long elapsed;
        if (running) {
             elapsed = (System.currentTimeMillis() - startTime);
        }
        else {
            elapsed = (stopTime - startTime);
        }
        return elapsed;
    }



    public long getElapsedTimeSecs()                 
    {
        long elapsed;
        if (running) 
        {
            elapsed = ((System.currentTimeMillis() - startTime) / 1000);
        }
        else
        {
            elapsed = ((stopTime - startTime) / 1000);
        }
        return elapsed;
    }





    public static void main(String[] args) throws IOException
    {
        ElaspedTimetoCopyAFileUsingByteStream  s = new ElaspedTimetoCopyAFileUsingByteStream();
        s.start();

        FileInputStream in = null;
        FileOutputStream out = null;

      try {
         in = new FileInputStream("vowels.txt");   // 23.7  MB File
         out = new FileOutputStream("output.txt");

         int c;
         while ((c = in.read()) != -1) {
            out.write(c);
         }
      }finally {
         if (in != null) {
            in.close();
         }
         if (out != null) {
            out.close();
         }
      }



        s.stop();
        System.out.println("elapsed time in seconds: " + s.getElapsedTimeSecs());
    }
}

[Elapsed Time for Byte Stream Reader][1]

**Character Stream Reader Elapsed Time for 23.7 MB is 3 secs**

import java.io.*;
import java.io.IOException;
import java.util.Scanner;

class ElaspedTimetoCopyAFileUsingCharacterStream
{

    private long startTime = 0;
    private long stopTime = 0;
    private boolean running = false;


    public void start() 
    {
        this.startTime = System.currentTimeMillis();
        this.running = true;
    }


    public void stop() 
    {
        this.stopTime = System.currentTimeMillis();
        this.running = false;
    }



    public long getElapsedTime() 
    {
        long elapsed;
        if (running) {
             elapsed = (System.currentTimeMillis() - startTime);
        }
        else {
            elapsed = (stopTime - startTime);
        }
        return elapsed;
    }



    public long getElapsedTimeSecs()                 
    {
        long elapsed;
        if (running) 
        {
            elapsed = ((System.currentTimeMillis() - startTime) / 1000);
        }
        else
        {
            elapsed = ((stopTime - startTime) / 1000);
        }
        return elapsed;
    }





    public static void main(String[] args) throws IOException
    {
        ElaspedTimetoCopyAFileUsingCharacterStream  s = new ElaspedTimetoCopyAFileUsingCharacterStream();
        s.start();

         FileReader in = null;                // CharacterStream Reader
      FileWriter out = null;

      try {
         in = new FileReader("vowels.txt");    // 23.7 MB
         out = new FileWriter("output.txt");

         int c;
         while ((c = in.read()) != -1) {
            out.write(c);
         }
      }finally {
         if (in != null) {
            in.close();
         }
         if (out != null) {
            out.close();
         }
      }

              s.stop();
        System.out.println("elapsed time in seconds: " + s.getElapsedTimeSecs());
    }
}


[Elapsed Time for Character Stream Reader][2]


  [1]: https://i.stack.imgur.com/hYo8y.png
  [2]: https://i.stack.imgur.com/xPjCK.png

为了在Java中实现这一点,应该使用哪些类型?

简短的回答是长。现在,更多关于如何衡量……

System.currentTimeMillis()

“传统”的方法是使用System.currentTimeMillis():

long startTime = System.currentTimeMillis();
// ... do something ...
long estimatedTime = System.currentTimeMillis() - startTime;

o.a.c.l.t.StopWatch

注意,Commons Lang有一个StopWatch类,可以用来测量以毫秒为单位的执行时间。它有split(), suspend(), resume()等方法,允许在执行的不同点采取措施,您可能会发现方便。看一看。

System.nanoTime()

如果您正在寻找运行时间的极其精确的度量,您可能更喜欢使用System.nanoTime()。从它的javadoc:

long startTime = System.nanoTime();    
// ... the code being measured ...    
long estimatedTime = System.nanoTime() - startTime;

Jamon

另一种选择是使用JAMon,这是一种收集start()和stop()方法之间任何代码的统计信息(执行时间、命中次数、平均执行时间、最小值、最大值等)的工具。下面是一个非常简单的例子:

import com.jamonapi.*;
...
Monitor mon=MonitorFactory.start("myFirstMonitor");
...Code Being Timed...
mon.stop();

查看www.javaperformancetunning.com上的这篇文章,有很好的介绍。

使用AOP

最后,如果您不想让这些度量使您的代码变得混乱(或者如果您不能更改现有的代码),那么AOP将是一个完美的武器。我不打算深入讨论这个问题但我至少想提一下。

下面是一个使用AspectJ和JAMon的非常简单的方面(这里,切入点的短名称将用于JAMon监视器,因此调用thisJoinPoint.toShortString()):

public aspect MonitorAspect {
    pointcut monitor() : execution(* *.ClassToMonitor.methodToMonitor(..));

    Object arround() : monitor() {
        Monitor monitor = MonitorFactory.start(thisJoinPoint.toShortString());
        Object returnedObject = proceed();
        monitor.stop();
        return returnedObject;
    }
}

切入点定义可以很容易地调整为基于类名、包名、方法名或它们的任何组合来监视任何方法。度量实际上是AOP的一个完美用例。

如果您从System.currentTimeMillis()获取时间戳,那么您的时间变量应该是长变量。