Quiz duration is specified as days, hours and minutes each in integers.
I am trying to convert combination of these to seconds. Below code I tried. but it always returns 0 seconds. I am using jdk 6
Integer hours = 3, days=4, minutes=20;
javax.xml.datatype.Duration duration = DatatypeFactory.newInstance().newDuration(true, 0, 0,
days,
hours,
minutes,
0);
Integer seconds = duration.getSeconds(); // It always returns zero
Please guide.
As far as I can see your code you are trying to use
javax.xml.datatype.Duration
which will I believe only return the specified duration in the seconds. If you want to get the number of seconds in a time provided duration, you need to use
java.time.Duration
There is a parse method available that allows you to parse a CharSequence and get a proper instance of java.time.Duration which can be done as shown below
String toParse = "P"+days+"DT"+hours+"H"+minutes+"M";
Duration secondsDuration = Duration.parse(toParse);
System.out.println(secondsDuration.getSeconds());
This is a sample code you can read further documentation for the given method an different methods available for java.time.Duration.
The JavaDocs for javax.xml.datatype.Duration.getSeconds() say
Obtains the value of the SECONDS field as an integer value, or 0 if not present. This method works just like getYears() except that this method works on the SECONDS field.
If you want to calculate the total amount of seconds this duration is representing, you will have to calculate them yourself, maybe like this (there may be better solutions):
private static int getInSeconds(javax.xml.datatype.Duration duration) {
int totalSeconds = 0;
totalSeconds += duration.getSeconds();
totalSeconds += (duration.getMinutes() * 60);
totalSeconds += (duration.getHours() * 60 * 60);
totalSeconds += (duration.getDays() * 24 * 60 * 60);
// ... calculate values for other fields here, too
return totalSeconds;
}
For certain durations, an int will not be sufficient, keep that in mind, please.
Consider using java.time.Duration instead, if possible.
There is a backport of java.time for Java 6 and 7, but unfortunately, not for below.
java.time and ThreeTen Backport
I think you will be happier with org.threeten.bp.Duration from the backport of java.time to Java 6 and 7. java.time is the modern Java date and time API originally introduced in Java 8.
int days = 4;
int hours = 3;
int minutes = 20;
Duration duration = Duration.ofDays(days).plusHours(hours).plusMinutes(minutes);
long totalSeconds = duration.getSeconds();
Link: ThreeTen Backport
Basically, your duration is hours = 3, days=4, minutes=20 and Seconds=0. that's why when you are trying to retrieve seconds you are getting 0.
If you want convert your whole duration to seconds then add days*24*60*60 + hours*60*60 + minutes*60 + seconds.
Java 8 has much better support to Duration. Please go through https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html
The answers by deHaar, DevX and Ole V.V. are correct and guide you in the right direction.
If you want to stick to javax.xml.datatype.Duration, there is an easy way, purely using the OOTB (Out-Of-The-Box) API, to achieve what you want to. It is as simple as passing a java.util.Calendar instance to javax.xml.datatype.Duration#getTimeInMillis and converting the returned value to seconds by using TimeUnit.MILLISECONDS.toSeconds.
Demo:
import java.util.Calendar;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
public class Main {
public static void main(String[] args) throws DatatypeConfigurationException {
Integer hours = 3, days = 4, minutes = 20;
javax.xml.datatype.Duration duration = DatatypeFactory.newInstance().newDuration(true, 0, 0,
days,
hours,
minutes,
0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
long seconds = TimeUnit.MILLISECONDS.toSeconds(duration.getTimeInMillis(calendar));
System.out.println(seconds);
}
}
Output:
357600
This question already has answers here:
How do I time a method's execution in Java?
(42 answers)
How do I calculate the elapsed time of an event in Java? [duplicate]
(6 answers)
Closed 4 years ago.
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?
Unfortunately, none of the ten answers posted so far are quite right.
If you are measuring elapsed time, and you want it to be correct, you must use System.nanoTime(). You cannot use System.currentTimeMillis(), unless you don't mind your result being wrong.
The purpose of nanoTime is to measure elapsed time, and the purpose of currentTimeMillis is to measure wall-clock time. You can't use the one for the other purpose. The reason is that no computer's clock is perfect; it always drifts and occasionally needs to be corrected. This correction might either happen manually, or in the case of most machines, there's a process that runs and continually issues small corrections to the system clock ("wall clock"). These tend to happen often. Another such correction happens whenever there is a leap second.
Since nanoTime's purpose is to measure elapsed time, it is unaffected by any of these small corrections. It is what you want to use. Any timings currently underway with currentTimeMillis will be off -- possibly even negative.
You may say, "this doesn't sound like it would ever really matter that much," to which I say, maybe not, but overall, isn't correct code just better than incorrect code? Besides, nanoTime is shorter to type anyway.
Previously posted disclaimers about nanoTime usually having only microsecond precision are valid. Also it can take more than a whole microsecond to invoke, depending on circumstances (as can the other one), so don't expect to time very very small intervals correctly.
Which types to use in order to accomplish this in Java?
The short answer is a long. Now, more on how to measure...
System.currentTimeMillis()
The "traditional" way to do this is indeed to use System.currentTimeMillis():
long startTime = System.currentTimeMillis();
// ... do something ...
long estimatedTime = System.currentTimeMillis() - startTime;
o.a.c.l.t.StopWatch
Note that Commons Lang has a StopWatch class that can be used to measure execution time in milliseconds. It has methods methods like split(), suspend(), resume(), etc that allow to take measure at different points of the execution and that you may find convenient. Have a look at it.
System.nanoTime()
You may prefer to use System.nanoTime() if you are looking for extremely precise measurements of elapsed time. From its javadoc:
long startTime = System.nanoTime();
// ... the code being measured ...
long estimatedTime = System.nanoTime() - startTime;
Jamon
Another option would be to use JAMon, a tool that gathers statistics (execution time, number of hit, average execution time, min, max, etc) for any code that comes between start() and stop() methods. Below, a very simple example:
import com.jamonapi.*;
...
Monitor mon=MonitorFactory.start("myFirstMonitor");
...Code Being Timed...
mon.stop();
Check out this article on www.javaperformancetunning.com for a nice introduction.
Using AOP
Finally, if you don't want to clutter your code with these measurement (or if you can't change existing code), then AOP would be a perfect weapon. I'm not going to discuss this very deeply but I wanted at least to mention it.
Below, a very simple aspect using AspectJ and JAMon (here, the short name of the pointcut will be used for the JAMon monitor, hence the call to 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;
}
}
The pointcut definition could be easily adapted to monitor any method based on the class name, the package name, the method name, or any combination of these. Measurement is really a perfect use case for AOP.
Your new class:
public class TimeWatch {
long starts;
public static TimeWatch start() {
return new TimeWatch();
}
private TimeWatch() {
reset();
}
public TimeWatch reset() {
starts = System.currentTimeMillis();
return this;
}
public long time() {
long ends = System.currentTimeMillis();
return ends - starts;
}
public long time(TimeUnit unit) {
return unit.convert(time(), TimeUnit.MILLISECONDS);
}
}
Usage:
TimeWatch watch = TimeWatch.start();
// do something
long passedTimeInMs = watch.time();
long passedTimeInSeconds = watch.time(TimeUnit.SECONDS);
Afterwards, the time passed can be converted to whatever format you like, with a calender for example
Greetz,
GHad
If the purpose is to simply print coarse timing information to your program logs, then the easy solution for Java projects is not to write your own stopwatch or timer classes, but just use the org.apache.commons.lang.time.StopWatch class that is part of Apache Commons Lang.
final StopWatch stopwatch = new StopWatch();
stopwatch.start();
LOGGER.debug("Starting long calculations: {}", stopwatch);
...
LOGGER.debug("Time after key part of calcuation: {}", stopwatch);
...
LOGGER.debug("Finished calculating {}", stopwatch);
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?
Capture the current moment in UTC, with Instant.now().
Capture another such moment later.
Pass both to Duration.between.
(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?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
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.
Which types to use in order to accomplish this in Java?
Answer: long
public class Stream {
public long startTime;
public long endTime;
public long getDuration() {
return endTime - startTime;
}
// I would add
public void start() {
startTime = System.currentTimeMillis();
}
public void stop() {
endTime = System.currentTimeMillis();
}
}
Usage:
Stream s = ....
s.start();
// do something for a while
s.stop();
s.getDuration(); // gives the elapsed time in milliseconds.
That's my direct answer for your first question.
For the last "note" I would suggest you to use Joda Time. It contains an interval class suitable for what you need.
Java provides the static method System.currentTimeMillis(). And that's returning a long value, so it's a good reference. A lot of other classes accept a 'timeInMillis' parameter which is long as well.
And a lot of people find it easier to use the Joda Time library to do calculations on dates and times.
If you prefer using Java's Calendar API you can try this,
Date startingTime = Calendar.getInstance().getTime();
//later on
Date now = Calendar.getInstance().getTime();
long timeElapsed = now.getTime() - startingTime.getTime();
If you are writing an application that must deal with durations of time, then please take a look at Joda-Time which has class specifically for handling Durations, Intervals, and Periods. Your getDuration() method looks like it could return a 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);
}
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
If you're getting your timestamps from System.currentTimeMillis(), then your time variables should be longs.
i found this code to be useful when timing things:
public class Et {
public Et() {
reset();
}
public void reset() {
t0=System.nanoTime();
}
public long t0() {
return t0;
}
public long dt() {
return System.nanoTime()-t0();
}
public double etms() {
return etms(dt());
}
#Override public String toString() {
return etms()+" ms.";
}
public static double etms(long dt) {
return dt/1000000.; // 1_000_000. breaks cobertura
}
private Long t0;
}
Use this:
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
Date d1 = format.parse(strStartTime);
Date d2 = format.parse(strEndTime);
long diff = d2.getTime() - d1.getTime();
long diffSeconds,diffMinutes,diffHours;
if (diff > 0) {
diffSeconds = diff / 1000 % 60;
diffMinutes = diff / (60 * 1000) % 60;
diffHours = diff / (60 * 60 * 1000);
}
else{
long diffpos = (24*((60 * 60 * 1000))) + diff;
diffSeconds = diffpos / 1000 % 60;
diffMinutes = diffpos / (60 * 1000) % 60;
diffHours = (diffpos / (60 * 60 * 1000));
}
(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.)
the "else" part can get it correct
I built a formatting function based on stuff I stole off SO. I needed a way of "profiling" stuff in log messages, so I needed a fixed length duration message.
public static String GetElapsed(long aInitialTime, long aEndTime, boolean aIncludeMillis)
{
StringBuffer elapsed = new StringBuffer();
Map<String, Long> units = new HashMap<String, Long>();
long milliseconds = aEndTime - aInitialTime;
long seconds = milliseconds / 1000;
long minutes = milliseconds / (60 * 1000);
long hours = milliseconds / (60 * 60 * 1000);
long days = milliseconds / (24 * 60 * 60 * 1000);
units.put("milliseconds", milliseconds);
units.put("seconds", seconds);
units.put("minutes", minutes);
units.put("hours", hours);
units.put("days", days);
if (days > 0)
{
long leftoverHours = hours % 24;
units.put("hours", leftoverHours);
}
if (hours > 0)
{
long leftoeverMinutes = minutes % 60;
units.put("minutes", leftoeverMinutes);
}
if (minutes > 0)
{
long leftoverSeconds = seconds % 60;
units.put("seconds", leftoverSeconds);
}
if (seconds > 0)
{
long leftoverMilliseconds = milliseconds % 1000;
units.put("milliseconds", leftoverMilliseconds);
}
elapsed.append(PrependZeroIfNeeded(units.get("days")) + " days ")
.append(PrependZeroIfNeeded(units.get("hours")) + " hours ")
.append(PrependZeroIfNeeded(units.get("minutes")) + " minutes ")
.append(PrependZeroIfNeeded(units.get("seconds")) + " seconds ")
.append(PrependZeroIfNeeded(units.get("milliseconds")) + " ms");
return elapsed.toString();
}
private static String PrependZeroIfNeeded(long aValue)
{
return aValue < 10 ? "0" + aValue : Long.toString(aValue);
}
And a test class:
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import junit.framework.TestCase;
public class TimeUtilsTest extends TestCase
{
public void testGetElapsed()
{
long start = System.currentTimeMillis();
GregorianCalendar calendar = (GregorianCalendar) Calendar.getInstance();
calendar.setTime(new Date(start));
calendar.add(Calendar.MILLISECOND, 610);
calendar.add(Calendar.SECOND, 35);
calendar.add(Calendar.MINUTE, 5);
calendar.add(Calendar.DAY_OF_YEAR, 5);
long end = calendar.getTimeInMillis();
assertEquals("05 days 00 hours 05 minutes 35 seconds 610 ms", TimeUtils.GetElapsed(start, end, true));
}
}
I want to pass around a time number and the TimeUnit it is in.
long number = some number;
TimeUnit timeUnit = some arbitrary time unit
What can hold both the time and timeUnit in one Object from the Java libraries?
There is no Java library object that encapsulates a number and an arbitrary TimeUnit. However, there is one in Java 8 that converts itself into whatever time unit is required:
java.time.Duration
Duration stores the provided quantity and then provides comparison and conversion to all other time units. For example:
// Create duration from nano time
Duration systemTime = Duration.ofNanos(System.nanoTime());
// Create duration from millis time
Duration systemTime = Duration.ofMillis(System.currentTimeMillis());
Of course, if doing addition and subtraction or other math operations, the precision is only as good as the precision of the current operation and the supplied Duration.
/**
* Example that tells if something has reached the required age
* TRUE IF THE current system time is older or equal to the required system time
*/
// TRUE IF THE FILE HAS NOT WAITED ENOUGH TIME AFTER LAST CREATE/MODIFY
private boolean isMature() {
// it is not known whether required age is nanos or millis
Duration requiredAge = systemTimeWhenMature();
// so create a duration in whatever time unit you have
// more precise = possibly better here
Duration actualAge = Duration.ofNanos(System.nanoTime());
// if ON or OLDER THAN REQUIRED AGE
// actualAge - requiredAge = balance
// 20 - 21 = -1 (NOT MATURE)
// 21 - 21 = 0 (OK)
// 22 - 21 = 1 (OK)
Duration balance = actualAge.minus(requiredAge);
if (balance.isNegative()) {
logger.info("Something not yet expired. Expires in {} millis.", balance.negated());
return false;
} else {
return true;
}
}
And there are many more methods in Duration that are useful for converting and processing the stored quantity in various unit.
It is important to understand how the precision will affect calculations. This shows the
general precision contract by example:
// PICK A NUMBER THAT IS NOT THE SAME WHEN CONVERTED TO A LESSER PRECISION
long timeNanos = 1234567891011121314L;
long timeMillis = TimeUnit.MILLISECONDS.convert(timeNanos, TimeUnit.NANOSECONDS);
// create from milliseconds
Duration millisAccurate = Duration.ofMillis(timeMillis);
Duration nanosAccurate = Duration.ofNanos(timeNanos);
// false because of precision difference
assertFalse(timeMillis == timeNanos);
assertFalse(millisAccurate.equals(nanosAccurate));
// true because same logical precision conversion takes place
assertTrue(timeMillis - timeNanos <= 0);
assertTrue(millisAccurate.minus(nanosAccurate).isNegative());
// timeNanos has greater precision and therefore is > timeMillie
assertTrue(timeNanos - timeMillis > 0);
assertTrue(nanosAccurate.minus(millisAccurate).negated().isNegative());
In a nutshell .. I cannot believe it took me this long to find Duration!
:)
TimeUnit is just enum holding some time unit types like Second, Milliseconds, ...
TimeUnit is NOT for holding time BUT you can convert a time in a unit to another unit using TimeUnit API.
I think you have to create your object to hold time and its unit.
If you use Java 8. You can work with some new Date API
http://download.java.net/jdk8/docs/api/java/time/package-summary.html
In Joda-Time there is an Interval, but you'll need to create a Java Bean (perhaps calling it Interval) if you want to use only JRE inclusive Object types.
I have a ListView that users will put comment in. When they hit "submit" attached to an EditText box, the new comment goes into a MySQL database along with the current time.
I'd like the comments to appear in the listview with dates similar to Youtube formatting. For example: "10 seconds ago", "1 day ago", "52 days ago".
Would I use the Calendar object, SimpleDateFormat, something else?
Also, how would I store the date in the datebase? I am assuming something easily convertible like the UNIX date stamp maybe. And then would it be in the ArrayAdapter where I dynamically change the date based on the current time?
You can use PrettyTime to achieve that.
For saving time, I usually save time in millis.
To get this you need to calculate the difference between your timestamp and current timestamp (keep them in milliseconds for simplicity). The result will be number of milliseconds "ago". Then use simple math like subtraction and division and you can get number of minutes, days, weeks and whatever-you-want.
EDIT: I use this:
public static final long MILLIS_PER_SECOND = 1000;
public static final long MILLIS_PER_MINUTE = (MILLIS_PER_SECOND * 60);
public static final long MILLIS_PER_HOUR = (MILLIS_PER_MINUTE * 60);
public static final long MILLIS_PER_DAY = (MILLIS_PER_HOUR * 24);
public static final long MILLIS_PER_WEEK = (MILLIS_PER_DAY * 7);
public static final long MILLIS_PER_MONTH = (MILLIS_PER_DAY * 30);
public static final long MILLIS_PER_YEAR = (MILLIS_PER_MONTH * 12);
Note that is is not 100% correct as I (intentionally, for simplicy) made false assumption month is always 30 days long, which also influences MILLIS_PER_YEAR. But I do not really care - it's not rocket science I use these for. But you may reduce the impact by setting MILLIS_PER_YEAR this way:
public static final long MILLIS_PER_YEAR = (MILLIS_PER_DAY * (7*31 + 4*30 + 28));
28 is for February, in this case you only be 1 day off on leaps years, instead of 5 days as in former version.
Try DateUtils.getRelativeTimeSpanString to format the date for display.
This question already has answers here:
How do I time a method's execution in Java?
(42 answers)
Closed 4 years ago.
What's a simple/easy way to access the system clock using Java, so that I can calculate the elapsed time of an event?
I would avoid using System.currentTimeMillis() for measuring elapsed time. currentTimeMillis() returns the 'wall-clock' time, which may change (eg: daylight savings, admin user changing the clock) and skew your interval measurements.
System.nanoTime(), on the other hand, returns the number of nanoseconds since 'some reference point' (eg, JVM start up), and would therefore not be susceptible to system clock changes.
This is some sample code.
long startTime = System.currentTimeMillis();
// Run some code;
long stopTime = System.currentTimeMillis();
System.out.println("Elapsed time was " + (stopTime - startTime) + " miliseconds.");
Apache Commons-Lang also has the StopWatch class suited just for your purpose. It uses System.currentTimeMillis(), so you'll still have resolution problems, but you can pause and do lap times and such. I use it as standard now for event stats.
http://commons.apache.org/lang/api-release/org/apache/commons/lang/time/StopWatch.html
The Answer by Leigh is correct.
java.time
Java 8 and later has the java.time framework built in.
An Instant is a moment on the timeline in UTC with nanosecond resolution (up to 9 digits of a decimal fraction of a second). The now method grabs the current date-time moment.
Instant now = Instant.now();
2016-03-12T04:29:39.123Z
You can calculate the elapsed time between a pair of Instant objects as a Duration. The duration uses nanosecond resolution with a maximum value of the seconds that can be held in a long. This is greater than the current estimated age of the universe.
Duration duration = Duration.between( startInstant , stopInstant );
The default output of Duration::toString is in standard ISO 8601 format. You can also ask for a total count of nanoseconds (toNanos) or milliseconds (toMillis), as well as other amounts.
Java 8
In Java 8, fetching the current moment resolves only to millisecond resolution (up to 3 digits of a decimal fraction of a second). So while the java.time classes can store nanoseconds they can only determine the current moment with milliseconds. This limitation is due to a legacy issue (the default Clock implementation uses System.currentTimeMillis()).
Java 9
In Java 9 and later, the default Clock implementation can determine the current moment in up to nanosecond resolution. Actually doing so depends on the fineness of your computer’s clock hardware.
See this OpenJDK issue page for more info: Increase the precision of the implementation of java.time.Clock.systemUTC()
Micro Benchmark
If your purpose is benchmarking, be sure to look at other Questions such as:
How do I write a correct micro-benchmark in Java?
Create quick/reliable benchmark with java?
Frameworks are available to assist with short-duration benchmarking.
java.lang.System.currentTimeMillis() or java.lang.System.nanoTime() ought to work to measure elapsed time.
Here is a small StopWatch class I wrote using the System.nanoTime() as suggested in the answer from Leigh:
public class StopWatch {
// Constructor
public StopWatch() {
}
// Public API
public void start() {
if (!_isRunning) {
_startTime = System.nanoTime();
_isRunning = true;
}
}
public void stop() {
if (_isRunning) {
_elapsedTime += System.nanoTime() - _startTime;
_isRunning = false;
}
}
public void reset() {
_elapsedTime = 0;
if (_isRunning) {
_startTime = System.nanoTime();
}
}
public boolean isRunning() {
return _isRunning;
}
public long getElapsedTimeNanos() {
if (_isRunning) {
return System.nanoTime() - _startTime;
}
return _elapsedTime;
}
public long getElapsedTimeMillis() {
return getElapsedTimeNanos() / 1000000L;
}
// Private Members
private boolean _isRunning = false;
private long _startTime = 0;
private long _elapsedTime = 0;
}