How do I measure time elapsed in Java? [duplicate]

2018-12-31 04:25发布

I want to have something like this:

public class Stream
{
    public startTime;
    public endTime;

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

Also it is important that for example if the startTime it's 23:00 and endTime 1:00 to get a duration of 2:00.

Which types to use in order to accomplish this in Java?

标签: java time
15条回答
琉璃瓶的回忆
2楼-- · 2018-12-31 04:56

tl;dr

for example if the startTime it's 23:00 and endTime 1:00 to get a duration of 2:00.

Not possible. If you have only time-of-day, the clock stops at midnight. Without the context of dates, how do we know if you mean 1 AM on the next day, next week, or next decade?

So going from 11 PM to 1 AM means moving backwards in time 22 hours, running the hands of the clock counterclockwise. See the result below, a negative twenty-two hours.

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

Crossing midnight requires the larger context of date in addition to time-of-day (see below).

How do I measure time elapsed in Java?

  1. Capture the current moment in UTC, with Instant.now().
  2. Capture another such moment later.
  3. Pass both to Duration.between.
  4. (a) From the resulting Duration object, extract a number of 24-hour days, hours, minutes, seconds, and fractional second in nanoseconds by calling the various to…Part methods.
    (b) Or, call toString to generate a String in standard ISO 8601 format of PnYnMnDTnHnMnS.

Example code, using pair of Instant objects.

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

New Technology In Java 8+

We have new technology for this now built into Java 8 and later, the java.time framework.

java.time

The java.time framework is defined by JSR 310, inspired by the highly successful Joda-Time project, extended by the ThreeTen-Extra project, and described in the Oracle Tutorial.

The old date-time classes such as java.util.Date/.Calendar bundled with the earliest versions of Java have proven to be poorly designed, confusing, and troublesome. They are supplanted by the java.time classes.

Resolution

Other answers discuss resolution.

The java.time classes have nanosecond resolution, up to nine digits of a decimal fraction of a second. For example, 2016-03-12T04:29:39.123456789Z.

Both the old java.util.Date/.Calendar classes and the Joda-Time classes have millisecond resolution (3 digits of fraction). For example, 2016-03-12T04:29:39.123Z.

In Java 8, the current moment is fetched with up to only millisecond resolution because of a legacy issue. In Java 9 and later, the current time can be determined up to nanosecond resolution provided your computer’s hardware clock runs so finely.

Time-Of-Day

If you truly want to work with only the time-of-day lacking any date or time zone, use the LocalTime class.

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

A Duration represents a span of time it terms of a count of seconds plus nanoseconds.

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

Dump to console.

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

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

ISO 8601

Notice the default output of Duration::toString is in standard ISO 8601 format. In this format, the P marks the beginning (as in 'Period'), and the T separates any years-months-days portion from the hours-minutes-seconds portion.

Crossing Midnight

Unfortunately, working with time-of-day only gets tricky when you wrap around the clock crossing midnight. The LocalTime class handles this by assuming you want to go backwards to an earlier point in the day.

Using the same code as above but going from 23:00 to 01:00 results in a negative twenty-two hours (PT-22H).

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

sooner: 23:00 | later: 01:00 | duration: PT-22H

Date-Time

If you intend to cross midnight, it probably makes sense for you to be working with date-time values rather than time-of-day-only values.

Time Zone

Time zone is crucial to dates. So we specify three items: (1) the desired date, (2) desired time-of-day, and (3) the time zone as a context by which to interpret that date and time. Here we arbitrarily choose the time zone of the Montréal area.

If you define the date by only an offset-from-UTC, use a ZoneOffset with a OffsetDateTime. If you have a full time zone (offset plus rules for handling anomalies such as Daylight Saving Time), use a ZoneId with a ZonedDateTime.

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

We specify the later time as next day at 1:00 AM.

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

We calculate the Duration in the same manner as seen above. Now we get the two hours expected by this Question.

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

Dump to console.

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

sooner: 2016-01-23T23:00-05:00[America/Montreal] | later: 2016-01-24T01:00-05:00[America/Montreal] | duration: PT2H

Daylight Saving Time

If the date-times at hand had involved Daylight Saving Time (DST) or other such anomaly, the java.time classes would adjust as needed. Read class doc for details.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

查看更多
时光乱了年华
3楼-- · 2018-12-31 04:57

It is worth noting that

  • System.currentTimeMillis() has only millisecond accuracy at best. At worth its can be 16 ms on some windows systems. It has a lower cost that alternatives < 200 ns.
  • System.nanoTime() is only micro-second accurate on most systems and can jump on windows systems by 100 microseconds (i.e sometimes it not as accurate as it appears)
  • Calendar is a very expensive way to calculate time. (i can think of apart from XMLGregorianCalendar) Sometimes its the most appropriate solution but be aware you should only time long intervals.
查看更多
梦该遗忘
4楼-- · 2018-12-31 04:57
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
查看更多
登录 后发表回答