Datatype for milliseconds - java

I´ve a time measure system in my app and where I have my milliseconds in a LONG datatype.
Now, I want them to convert into seconds, that´s easy by dividing through 1000.
What I need is decimal place for the milliseconds. How do I get it?

long seconds = timeInMillis/1000;
long milliseconds = timeInMillis%1000;
double timeInSeconds = ((double)seconds) + (((double)milliseconds)/1000.0);

You can also use TimeUnit. It has clean methods to handle such conversions. Like convertion from milliseconds to seconds and vice-versa.

Ok, I´m so stupid.
Just took the datatype Double.

Related

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

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.)

System.currentTimeMillis() only updating every 128 seconds?

I have a loop in which I am checking seconds elapsed by doing t-(long)(System.currentTimeMillis()/1000.0f) where t is set to t=(long)(System.currentTimeMillis()/1000.0f) right before the loop. I find that (long)(System.currentTimeMillis()/1000.0f) is equal to t for the first 128 seconds. It then updates after another 128 seconds. I am doing this on a background thread. What am I doing wrong?
System.currentTimeMillis() is a sufficiently large value that float cannot represent all integers around that range.
The fix is to simply use integer division by 1000.
You can use this to convert milis to second
long timeMillis = System.currentTimeMillis();
long timeSeconds = TimeUnit.MILLISECONDS.toSeconds(timeMillis);

How to get decimal result when converting nanosecond to millisecond?

Using TimeUnit, how can I convert 665477 nanosecond to 0.665477 millisecond?
long t = TimeUnit.MILLISECONDS.convert(665477L, TimeUnit.NANOSECONDS);
This always gives 0 but I need decimal points precision.
From Java Documentation - TimeUnit#convert
public long convert(long sourceDuration,TimeUnit sourceUnit)
Convert the given time duration in the given unit to this unit.
Conversions from finer to coarser granularities truncate, so lose
precision. For example converting 999 milliseconds to seconds results
in 0. Conversions from coarser to finer granularities with arguments
that would numerically overflow saturate to Long.MIN_VALUE if negative
or Long.MAX_VALUE if positive.
So to get your answer
double milliseconds = 665477 / 1000000.0;
shorter and less error prone:
double millis = 665477 / 1E6;
milli -> mikro -> nano
are two steps, each step has a conversion faktor of 1000 = 1E3;
So makes one million, which can easier be read as 1E6, than by counting zeros.
Just divide by 1,000,000:
double millis = 665477 / 1000000.0;
With TimeUnit you will only get an integer result.
You can calculate this manualy
double mil = 665477L/1_000_000.0
double milliSeconds = nanoSeconds / (double) TimeUnit.MILLISECONDS.toNanos(1);
so you don't have to put the magic number 1_000_000.0 in your code, or remember what is the correct ratio to make sure there is no bug: the line is pretty self-validating.
You can import static java.util.concurrent.TimeUnit.MILLISECONDS; for a code reading even more like prose.

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.sql.Timestamp way of storing NanoSeconds

java.sql.Timestamp constructor go like this:
public Timestamp(long time) {
super((time/1000)*1000);
nanos = (int)((time%1000) * 1000000);
if (nanos < 0) {
nanos = 1000000000 + nanos;
super.setTime(((time/1000)-1)*1000);
}
}
It basically accepts time in millisecond and then extracts the last 3 digits and makes it nanos. So for a millisecond value of 1304135631 421, I'm getting Timestamp.getnanos() as
421000000. This is plain calculation (adding 6 zeroes at the end)... does not seems to be optimum.
A better way could have been Timestamp constructor that accepts time in nanoseconds and then calculates the nanosecond value out of that.
If you run the below program, you'll see the difference between actual nanoseconds and the one returned by Timestamp way of calculating nanosecods.
long a = System.currentTimeMillis();
for(;;){
long b = System.currentTimeMillis();
Timestamp tm = new Timestamp(System.currentTimeMillis());
System.out.println(tm.getTime());
System.out.println(tm.getNanos());
System.out.println("This is actual nanos" + System.nanoTime()%1000000000);
System.out.println("--------------------------");
if(b-a >= 1)
break;
}
So all the discussion about Timestamp that says it stores time up to nanoseconds , does not seems to be so correct.. Isn't?
The time in millis does not represent the time in nanos. More precise it simply can't be. You're supposed to use Timestamp#setNanos() to set the real nanos.
long timeInMillis = System.currentTimeMillis();
long timeInNanos = System.nanoTime();
Timestamp timestamp = new Timestamp(timeInMillis);
timestamp.setNanos((int) (timeInNanos % 1000000000));
// ...
Since the introduction of java.time.*, there is a new factory method in java.sql.Timestamp: Timestamp.from(Instant.now()) will do the job (with nanoseconds precision). There is also Timestamp.toInstant() to convert it the other way around.
Although it's an old post, I would like to add that the docs of Timestamp does state that it "holds fractional seconds by allowing the specification of
fractional seconds to a precision of nanaoseconds". The confusing part is "hold". This seems confusing at first but if understood correctly, it actually does not state that it holds nanaoseconds
value.It says it "holds" fractional value and allows it to be a "precision" of nanoseconds. Precision should be understood in terms of representation
of total number of digits. So it essentially means that the part is actually fractional (still milliseconds) but is multiplied by 1000000 to represent it as nanoseconds.
The accepted answer (by ever helpful BaluC) sums it up nicely.
I like OpenJPA's implementation of TimestampHelper. It use static initializers to keep track of elapsed nanoseconds between calls to make a timestamp.

Categories

Resources