System.currentTimeMillis() only updating every 128 seconds? - java

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

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

Is there a shorter way to represent a time in milliseconds?

I am asked to store the time right before my algorithm start, and time when it ends, and also need to provide the difference between them (end time - start time).
But the System.currentTimeMillis() function generates values that are too long:
start=1497574732045
end=1497574732168
Is there a way to make this value just 3 digits like "123" but also be as precise as using the System.currentTimeMillis() function?
as the currentTimeMillis() description says:-
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.
Returns:
the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC.
in your case use this simple trick and you will get the desired result.
Long startTime= Long.parseLong("1497674732168");
Long endTime= Long.parseLong("1497574732168");
System.out.println("start time is"+new Date(startTime)+"end time is"+new Date(endTime));
If you need to store the start and end times separately, there are only two ways (I can think of) to make the values smaller.
Firstly, System.currentTimeMillis() counts from January 1, 1970 UTC. But if your clock is never going to run previous to "now", you can subtract a fixed amount of time. I chose 1497580000000 as it's definitely in the past at the time I wrote this and its a nice even number.
Second, divide the value by any amount of precision you are willing to lose. In your case you might not want to even do that, but here I chose 100.
The numbers returned look small now, but they will continue to get bigger as the difference between the current time and 1497580000000 become more pronounced.
The preferred solution is to not do any of this at all, but just store the long value if you can.
You'll never magic a large precise number into only 3 decimal digits. Not without quantum mechanics.
{
long start = 1497584001010L;
long end = 1497584008000L;
System.out.println("Diff: " + (end - start));
int compactStart = compact(start);
int compactEnd = compact(end);
System.out.println("Compact Start: " + compactStart);
System.out.println("Compact End: " + compactEnd);
System.out.println("Diff: " + (expand(compactEnd) - expand(compactStart)));
}
private int compact(long millis) {
return (int)((millis - 1497580000000L)/100);
}
private long expand(int millis) {
return (millis + 1497584000000L)*100;
}
Result...
Diff: 6990
Compact Start: 40010
Compact End: 40080
Diff: 7000
Note 7000 doesn't equal 6990 because of the intentional precision loss.

How can I set the program time in seconds?

I want to give the program time in java. How can I get the time in seconds?
This is my program:
public static void main(String[] args) {
long start = System.nanoTime();
System.out.print(start);
}
For example when i run the program show 7955739220574 nano time. that mean's 7955 second.
Is this time is really for this program!!!!!?
Thank you.
Please note that System.nanoTime() returns the time in nanoseconds which passed since an arbitrary point in time, not necessarily the beginning of your program. System.currentTimeMillis() will give you the absolute time in milliseconds since the Unix epoch (Jan 1, 1970).
If you want to measure the duration of something you can do:
long startTime = System.nanoTime();
// ... the code being measured ...
long estimatedTime = System.nanoTime() - startTime;
... as showed in the docs i linked. If you want it in seconds you should divide estimatedTime it by 1 billion.
You could use TimeUnit:
TimeUnit.SECONDS.convert(time, TimeUnit.NANOSECONDS);
Divide the result you get in nanoseconds by 1 000 000 000.
1 nanosecond is 10^-9 * 1 seconds.
so to get seconds using nano seconds, you need to divide the value of Start by 10^-9

Datatype for milliseconds

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.

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