I created a filter that monitors the length of a request.
long start = System.nanoTime();
...
long end = System.nanoTime();
How can I get the number of milliseconds from this now?
(end - start) / 1000000
1 microsecond = 1000 nanoseconds
1 millisecond = 1000 microseconds
Note, that the result will be rounded down, but you usually don't get true nanosecond accuracy anyway (accuracy depends on the OS). From the Javadoc on nanoTime():
This method provides nanosecond precision, but not
necessarily nanosecond accuracy.
Also note that you can use the TimeUnit class to help with conversion. With older versions of Java, the following code might be an example to transform a processing time into some other time format:
long startTime = System.nanoTime();
//Processing in-between.
long endTime = System.nanoTime();
long duration = endTime - startTime;
duration = TimeUnit.SECONDS.convert(duration, TimeUnit.NANOSECONDS);
Note that newer versions of Java have shortcuts in the TimeUnit class.
The above sample will turn nanoseconds long into seconds. Also note that this truncates it so you do lose some precision. Therefore, if you switch to minutes then you will lose the precision of seconds. If you want to get a result of "12 minutes and 32 seconds" then you would have to do further processing with this solution.
TimeUnit#toMillis(long) (since Java 5)
TimeUnit.NANOSECONDS.toMillis(end - start);
OR
Duration#toMillis() (since Java 8)
Duration.ofNanos(end - start).toMillis()
OR
Duration#between(Temporal, Temporal) (since Java 8)
Instant start = Instant.now();
...
Instant end = Instant.now();
Duration.between(start, end).toMillis()
OR
ChronoUnit.html#between(Temporal, Temporal) (since Java 8)
Instant start = Instant.now();
...
Instant end = Instant.now();
ChronoUnit.MILLIS.between(start, end)
Just subtract them and divide result by 10^6.
1 nanosecond is 10^-9 seconds and, correspondingly, 10^-6 milliseconds.
http://en.wikipedia.org/wiki/Nano-
You could just use System.currentTimeMillis().
Caveat:
Note that while the unit of time of the return value is a millisecond, the granularity of the value depends on the underlying operating system and may be larger. For example, many operating systems measure time in units of tens of milliseconds.
To get a meaningful result:
void procedure ( ... )
{
...
}
double measureProcedure ( double epsilon , ... )
{
double mean ;
double stderr = 2 * epsilon ;
while ( stderr > epsilon )
{
long start = System.nanoTime();
procedure ( ... ) ;
long end = System.nanoTime();
// recalculate mean , stderr
}
return ( mean / 1000000 ) ;
}
Related
I am using java timer, but my problem is every time exceeding 60 seconds, I like my code working like;
1 minutes 59 seconds,
2 minutes 0 seconds..
My code is below.
private long lastReceivedMessage = System.currentTimeMillis();
#Scheduled(fixedDelayString = "${listenScheduled}", initialDelay = 1000)
private void distanceBetweenLastReceivedMessageAndCurrentTime() {
long currentTime = System.currentTimeMillis() - lastReceivedMessage;
logger.info("has threw 'INFO' event due to is not running as an expected since {} {} {} {} ", TimeUnit.MILLISECONDS.toMinutes(currentTime), "minutes", TimeUnit.MILLISECONDS.toSeconds(currentTime), "seconds");
java.time classes
Capture the current moment using java.time.Instant.
Instant then = Instant.now() ;
…
Duration d = Duration.between( then , Instant.now() ) ;
String output = d.toString() ;
The toString method generates text in standard ISO 8601 format: PnYnMnDTnHnMn. I suggest you report using that format. The format uses a P to mark the beginning. A T separates any years-months-days from any hours-minutes-seconds. So, two and a half minutes is PT2M30S.
If you insist on your format, call the to…Part methods on Duration.
It is not going to automatically separate the minutes and seconds. Also, I would recommend breaking up that logger.info statement for readability.
One way to do it is to convert it to seconds first, set the modulus (remainder) of the seconds and 60 as your seconds, then divide the minutes for the minutes value. Or you could just skip the conversion and divide + modulus by 60000.
long msElapsed = 660_000; //5min 30sec
long secElapsed = msElapsed / 1000;
long minutes = secElapsed / (long) 60;
long seconds = secElapsed % 60;
System.out.printf("%d %d",(int)minutes,(int)seconds);
I'm trying to convert the number of seconds contained in a duration into hours by dividing the duration.getSeconds() value by 60 twice.
However when I do this the number is being converted into 0.0, instead of an actual value. I imagine this is because the number is too small to be represented, however I have used doubles to try and represent the number and it still doesn't work.
In the below code please assume startTime and endTime are valid LocalTimes produced by two separate calls to LocalTime.now()
Duration duration = Duration.between(startTime, endTime); //duration in sec
double durationInSec = duration.getSeconds();
double durationInHours = durationInSec / 60 / 60;
Works for me
LocalTime start = LocalTime.of ( 11 , 30 );
LocalTime stop = start.plusHours ( 2 );
Duration d = Duration.between ( start , stop );
double seconds = d.toSeconds ();
double hours = seconds / 60 / 60;
See this code run live at IdeOne.com.
start.toString() = 11:30
stop.toString() = 13:30
d.toString() = PT2H
seconds = 7200.0
hours = 2.0
Tip: When you know you want to work with fractions of double, append d to your numeric literals to avoid any confusion over the compiler's integer-to-fraction conversion and up/downscaling the types. Be explicit. So in your code, append each 60 with a d. May not be necessary here, but removes ambiguity for the reader at least.
double hours = seconds / 60d / 60d ;
<1 second = 0 hours
As others commented, if your elapsed time was less than a full second, your code results in a zero.
A Duration is internally represented by a count of whole seconds plus a fractional second as a count of nanoseconds. Your call to Duration::getSeconds() retrieves the whole seconds, without the fractional second. So for a duration of PT0.5S, getSeconds returns zero. Zero divided by sixty divided by sixty equals zero.
Duration d = Duration.parse ( "PT0.5S" ); // Half a second.
double hours = d.getSeconds () / 60d / 60d;
hours: 0.0
You should instead call Duration::toNanos to get a total number of nanoseconds elapsed. And adjust your division.
Duration d = Duration.parse ( "PT0.5S" ); // Half a second.
long nanos = d.toNanos () ;
double hours = nanos / 1_000_000_000d / 60d / 60d ;
hours: 1.388888888888889E-4
Avoid fractional hours
By the way, let me suggest that fractional hours is a poor way to handle spans-of-time. Hours, minutes, seconds, and such are not amenable to such decimal math.
Besides that, the floating-point types such as double are inherently inaccurate.
Use the Java classes intended for this purpose: Duration and Period. When reporting or exchanging textually the value of these objects, use standard ISO 8601 format. As seen above, 2 hours is represented by PT2H.
The java.time classes use ISO 8601 formats by default when parsing/generating strings. No need to specify a formatting pattern.
Duration d = Duration.parse( "PT2H" ) ;
Suppose I have a System.currentTimeMillis() value as a long number.
How do I modify it to match the instant when last minute started? I.e., zero out seconds and milliseconds.
I would prefer to not use magic constants. Using java.time is fine.
I agree with the answers recommending java.time, but it can be done yet simpler as in those answers:
long lastWholeMinute = Instant.now().truncatedTo(ChronoUnit.MINUTES).toEpochMilli();
This just gave 1517940060000. Of course, if it makes sense for you to keep the Instant object, by all means do that rather than converting to a naked primitive long.
If your long value was one you had stored rather than the time now, it’s quite similar:
long someEpochMilliValue = 1_517_941_234_567L;
long lastWholeMinute = Instant.ofEpochMilli(someEpochMilliValue)
.truncatedTo(ChronoUnit.MINUTES)
.toEpochMilli();
Using java.time is probably the easiest way. You could use withNano and withSecond, like
java.time.ZonedDateTime zdt = java.time.ZonedDateTime.now().withNano(0).withSecond(0);
long millis = zdt.toInstant().toEpochMilli();
Since the value is in milliseconds, if we assume an idealized day (no leap seconds, etc.), then given l you could do it by simply removing the value of l % 60000L from it. I realize that's a magic constant, but it's truly a constant, there are always going to be 60,000 milliseconds in a minute. I'd give it symbolic name:
private static long SIXTY_SECONDS_IN_MS = 60000L;
and not worry about it. Then it's:
long l = /*...your number...*/;
l = l - (l % SIXTY_SECONDS_IN_MS);
Why this works: The Epoch value is from midnight Jan 1st 1970, and so at 0L, 60000L, 120000L, etc., the seconds and milliseconds of an idealized day based on that value are 0. So we use the remainder operator (%) to isolate the part of the value that would remain if we divided by 60000L and remove it. Thus the resulting value, again assuming idealized days, has 0 for seconds and milliseconds. It also works across timezones if we assume all timezones are going to be at whole-minute offsets to UTC. I've only ever heard of timezones that were multiples of hours or half-hours offset from UTC ("GMT plus five hours", "GMT plus 5.5 hours"), never (say) "GMT plus five hours seven minutes and 20 seconds". (And indeed, the standard notation for timezome offsets, +0600 or similar, only includes hours and minutes, not fractional minutes.)
Live Example:
import java.time.*;
public class Example
{
private static long SIXTY_SECONDS_IN_MS = 60000L;
public static void main (String[] args) throws java.lang.Exception
{
long l = System.currentTimeMillis();
l = l - (l % SIXTY_SECONDS_IN_MS);
System.out.println("l = " + l);
// Checking the result
LocalDateTime dt = Instant.ofEpochMilli(l).atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(dt);
System.out.println(dt.getSecond()); // 0
System.out.println(dt.getNano()); // 0
}
}
Still, though, if that constant violates the terms of the question such that you think I shouldn't have answered, let me know and I'll delete the answer. :-)
I'm trying to type out a code that outputs random words from a list, the user must type back as many words as possible before 60 seconds has elapsed I am using currentTimeMillis() to keep track of time so this is difficult for me to figure out I tried the code below and it said 6000000000000 is too large of a number but when I output the current/start time, it output 1512409897444 so this doesn't make sense to me.
long currentTime = System.currentTimeMillis();
long startTime = System.currentTimeMillis();
System.out.println(currentTime);
System.out.println(startTime);
while (startTime <= 6000000000000)
{
(etc. ect.)
}
What you want to do is compare the current time against the time you started and check if their difference is below 60 seconds, aka 60000 milli seconds:
long startTime = System.currentTimeMillis();
while ((System.currentTimeMillis() - startTime) <= 60000) {
// still under 60 seconds...
}
System.currentTimeMillis() returns a value that increases from an "epoch". You must subtract two time values to determine the amount of time that has elapsed.
long startTime = System.currentTimeMillis();
long elapsedTime = 0;
while (elapsedTime <= 60000) {
// etc, etc, etc
elapsedTime = System.currentTimeMillis() - startTime;
}
As others have already answered you have to subtract the starting time to the current time to determine if the difference is greather than 60 seconds (60,000 milliseconds). Also you can use TimeUnit to get a more readeable code:
long startTime = System.currentTimeMillis();
while (TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - startTime) <= 60) {
//do stuff
}
EDIT
If you are wondering why 6000000000000 gives you an error and the result of currentTimeMillis() (1512409897444) doesn't, is because they are different datatypes: int (32 bits) vs long (64 bits). The literal value 6000000000000 is interpreted as an int value which is greather than the max supported 32-bit signed int value (2,147,483,647) and the compiler doesn't allow that. It would work if you use a long literal instead 6000000000000L (note the L at the end). Signed long's max supported value is 9,223,372,036,854,775,807. The result of System.currentTimeMillis() is a long value hence 1512409897444 is valid. Read Primitive Data Types for further information.
I'm trying to make a timing mechanism using threads, and I'm having a problem in getting the time difference between two Dates, and using that difference to get a current percentage of the time left. Here is the concept I'm trying to prototype:
And here is my implementation:
long startMilisecs = System.currentTimeMillis();
long currentMilisecs;
long endDateMilisecs = getEndDate().getTime();
int diffMillisecs = ((int)(endDateMilisecs - startMilisecs) / 1000) / 60;
int currPerc;
while (startMilisecs <= endDateMilisecs)
{
currentMilisecs = (int) System.currentTimeMillis();
currPerc = ((int)currentMilisecs * 100) / diffMillisecs;
System.out.println(" Current Percentage: " + currPerc);
}
The problem with this code is that the percentage is not starting from 0 but rather in the 20's to 40 percent.
Can you tell me what is wrong with this? and for this problem I have been restricted to using only threads.
check below:
public static int getPercentageLeft(Date start, Date end) {
long now = System.currentTimeMillis();
long s = start.getTime();
long e = end.getTime();
if (s >= e || now >= e) {
return 0;
}
if (now <= s) {
return 100;
}
return (int) ((e - now) * 100 / (e - s));
}
You need to subtract the starting time like this
currPerc = ((currentMilisecs - startMilisecs) * 100) / diffMillisecs;
to get the correct percentage.
The problem is with the System.currentTimeMillis();. Taken from the javadoc:
public static long currentTimeMillis()
Returns the current time in milliseconds. Note that while the unit of
time of the return value is a millisecond, the granularity of the
value depends on the underlying operating system and may be larger.
For example, many operating systems measure time in units of tens of
milliseconds.
See the description of the class Date for a discussion of slight
discrepancies that may arise between "computer time" and coordinated
universal time (UTC).
Returns:
the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC.
So your current time in milliseconds is based on January 1, 1970 UTC, not on your start date.
You need to calculate current time by subtracting start time from the value that is given by System.currentTimeMillis();.
I am basically formulating your linked image here. Other alternative calculations can also be carried out.