Most efficient way to round a timestamp to the nearest 10 seconds - java

What is the most efficient way in Java (11) to round a given timestamp (e.g. System.currentTimeMillis()) to the nearest 10 seconds?
e.g. 12:55:11 would be 12:55:10 and 12:55:16 would be 12:55:20
This code is executed ~10-20 times per second, so it must be efficient.
Any ideas?
Thanks

Probably this:
long time = System.currentTimeMillis();
long roundedTime = (time + 5_000) / 10_000 * 10_000;
Basically 3 x 64 bit primitive arithmetic operations.
(If you want to truncate to 10 seconds granularity, just remove the + 5_000.)
Theoretically we should consider integer overflow. In practice the above code should be OK for roughly the next 292 million years. (Source: Wikipedia.)

Related

Get the seconds number from timestamp

I can get the seconds from a time stamp with this command :
long timestamp = System.currentTimeMillis() / 1000;
From this time stamp 1465731398013 I will get this result 1465731398,
What I need is only the last number, 8 in this case.
You've tagged your question modulo, which is actually the answer: You use the % operator:
long x = (System.currentTimeMillis() / 1000) % 10;
// modulus/remainder operator ---------------^
That will give you only the values 0-9, the last "digit" in the decimal number.
("modulus" and "remainder" aren't really synonymous although they're frequently used that way in programming. There are various types of "modulo" operations which vary based on their handling of the two operands' sign; more on Wikipedia.)

Use of bit wise shift operator in ConcurrentHashMap

As I was going through the ConcurrentHashMap source code, I have encountered so many bit wise shift operator. Some are applied on to create constants and some are on variables.
static final int MAXIMUM_CAPACITY = 1 << 30;
static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;
I am not able to understand, if constant like MAXIMUM_CAPACITY could be declared directly then what is the use of using bitwise shift operator.
They are not using the number in decimal form (base 10). Instead, they are saying "this is a number with 30 trailing 0 bits", implying the number is used for base 2 systems.
The bitshifting makes it easier to inform the reader of the value. In base 10, it would represent 1073741824, which seems like a random number.
This is common in programming. For example:
int secondsInDay = 60 * 60 * 24;
We are representing the amount of seconds in a minute, multiplied by the amount of minutes in an hour, multiplied by the amount of hours in a day.
We could have just put 86400, but what if we wanted to change how many minutes are in an hour (to represent time on some other planet)? You would have to manually calculate it to change the value.
On the other hand, by breaking it down into units as shown above, we can simply change the middle 60 to change how many minutes are in a day.

Ruby equivalent of Calendar.getInstance().getTimeInMillis() in 64 bits

I am using Ruby to generate a 64 bit timestamp similar to Java. I went through Class:Time and it says time could use 63 bit integer. I thought I could use:
Time.now.to_f * 1000
but I am worried about losing precision due to the floating point conversion. Can I simply get the 64 bit timestamp (millis since epoch) as in Java in ruby, as precise as possible?
Calendar.getInstance().getTimeInMillis();
I need to use the timestamp as unique ID in a database, so I would like to keep time-related collisions from minimum to non-existent.
I've added comments suggesting this really isn't what you should be doing anyway, but I really don't think you need to worry about losing precision in any meaningful way. The Ruby documentation states that the value is stored down to the nanosecond. Converting it to a floating point number may lose the last few digits, but it's not going to be significant at the millisecond level - you really don't care if the value round up or down a bit, after all... you're already relying on only creating a single entry per millisecond.
An alternative approach would be to use to_i and nsec: multiply the result of to_i by 1000, divide the result of nsec by 1000000, and add the two together. That will get you the number of milliseconds using only integer arithmetic.
The time is signed long in Java so it is 63-bit also.
So you are worried that in this year you will get an overflow? Personally, I don't think anyone will be using Java by then. In fact it's likely we will be extinct/evolved by then as well.
System.out.println("Overflow at " + new Date(Long.MAX_VALUE));
prints
Overflow at Sun Aug 17 08:12:55 CET 292278994
Note: 292 million years ago was before the dinosaurs ruled the earth.
If you are concerned about the loss of accuracy of converting a nano-second time stamp to double you can calculate what that error is
long now = System.currentTimeMillis() * 1000000L;
double error_f = Math.ulp((float) now);
double error = Math.ulp((double) now);
System.out.println("The error for a nano-second timestamp using a double "
+ now + " is " + error + " and float is " + error_f);
prints
The error for a nano-second timestamp using a double 1378970569656000000 is 256.0 and float is 1.37438953472E11
This means the error for converting to double is up to half of this which is 128 ns, for converting to float, the error is also half the ulp, which is 68 seconds, which is quite high.

how to manage the time left with System.currentTimeMillis()

I use for example this code to check if the user can do some action. So the user can only do one action each 5 seconds.
if((System.currentTimeMillis() - lastTime) > 5000)
{
// Message: Ok, you can do action now.
}else{
// Message: Have to wait 5 seconds to do action.
return;
}
lastTime = System.currentTimeMillis();
But as we all know, System.currentTimeMillis() returns a long, and that long can keep increasing until it turns negativ..
My code should run on a server that need to have more than 1 month of uptime. So I'm afraid at some point System.currentTimeMillis() will return a negativ value and my code will always tell the user that he need to wait 5 seconds or the opposite.
I'm having real hard time to concentrate on this piece of code and fix it, so I'm asking you guys if you have a tip on how to fix this problem and make my code 100% safe.
Don't worry about it.
You know whos problem it is?
The guy who will need to update it on Sun Aug 17 03:12:55 GMT-04:00 292278994.
A long in milliseconds can represent 292 277 266 years. I'm not sure this is the kind of thing you need to be worried about.
According to this thread, it will overflow in year 292278994. I will say it is plenty of time:)
As everyone has said don't worry about it but for future reference maybe you'd prefer to use Joda-Time to ask this kind of question.
import org.joda.time.DateTime;
if(lastTime.plusSeconds(5).isAfterNow()) {
// Message: Ok, you can do action now.
}
else {
// Message: Have to wait 5 seconds to do action.
return;
}
lastTime = new DateTime();
System.currentTimeMillis() returns the time in milliseconds, between the current time and midnight, January 1, 1970 UTC. With the largest maximum value that can be represented as a long is 9,223,372,036,854,775,807, if my calculation is right (long max / (1000 * 3600 * 24 * 365)), that could go up to more than 292471208 years. If your program can survive that long, let someone who will be born that many years later worry about it like we did for Y2K.
Even though the time it will overflow is far, far into the future as others have stated. It won't even be a problem then because you are taking the difference of two times. e.g. say you take the year 292,278,994 and the year 292,278,995 (which would appear to be negative), the difference is only 1 year (a positive number) e.g. if you take
long overflowYear = Long.MIN_VALUE; // overvflow of Long.MAX_VALUE + 1
long okayYear = Long.MAX_VALUE;
// time = 1 (positive due to an underflow!)
long time = overflowYear - okayYear;
This sort of this could happen with System.nanoTime() as it doesn't have a defined starting time and ticks one million time faster. However as long as you take the time difference, it doesn't matter if one is negative or positive provided they are less than 292 years apart.
So in answer to your question, even after the year 292,278,994 you won't have a problem until the application have been running for more than 292,278,994 years between calls to System.currentTimeMillis() !

Java System.nanoTime() huge difference in elapsed time

I'm in and android widget and checking elapsed time between two calls of System.nanoTime() and the number is huge. How do you measure elapsed time with this? it should be a fraaction of a second and instead its much more. Thanks
The System.nanoTime() returns a time value whose granularity is a nanosecond; i.e. 10-9 seconds, as described in the javadoc. The difference between two calls to System.nanoTime() that are a substantial fraction of a second apart is bound to be a large number.
If you want a time measure with a larger granularity, consider System.currentTimeMillis() ... or just divide the nanosecond values by an appropriate power of 10 to suit your application.
Note that on the Android platform there are 3 distinct system clocks that support different "measures" of time; see SystemClock. If you are programming explicitly for the Android platform, you should read the javadoc and decide which measure is most appropriate to what you are doing.
For your information, "nano-" is one of the standard prefixes defines by the International System of Units (SI) - see http://physics.nist.gov/cuu/Units/prefixes.html.
If you really think that "they" got it wrong and that "nano-" is too small, you could always write a letter to the NIST. I'm sure someone would appreciate it ... :-)
One seconds contains 1,000,000,000 nanoseconds, so as long as your number is in that range, it's reasonable.
If you want it in fractional form, just take your value / 10^9 where value is your difference in nanoTime()s.
long nanoSeconds = 500000000;
float seconds = nanoSeconds / 1000000000;
Log.i("NanoTime", nanoSeconds + " ns is the same as " + seconds + " seconds");
Your output would be:
07-27 11:35:47.196: INFO/NanoTime(14237): 500000000 ns is the same as 0.5 seconds

Categories

Resources