How to get decimal result when converting nanosecond to millisecond? - java

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.

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

Fastest way to get nanos unix epoch time in Java

I currently do this to successfully get the current epoch time in nanos:
Instant inst = Instant.now();
long time = inst.getEpochSecond();
time *= 1000000000l;
time += inst.getNano();
However, it's a bit too slow for my use case, taking around 1us each call after the JVM has warmed up.
Is there a faster way to do it?
I'm happy with a solution that gives me the microseconds since epoch, as long as it's faster than the above.
What may work is to run:
long n1 = System.nanoTime();
long m = System.currentTimeMillis();
long n2 = System.nanoTime();
a number of times until the difference between n1 and n2 is less than the resolution you want (it's about 400 ns on my PC after a couple of iterations).
You can then use the difference between n1 (or n2 or an average of the 2...) and m * 1e6 as an offset that you need to add to System.nanoTime() to get the current epoch nanos.
Disclaimer:
System.nanoTime doc explicitly states that the resolution is at least that of System.currentTimeMillis(), which may be > 1 ms. So no guarantee that you will get microsecond resolution.
Corollary: this probably doesn't work in all environments (you may never get n2-n1 small enough - or it may be 0 just because the resolution of your system is too low).
System.nanoTime() may be out of sync over long periods - so this is a trade off between precision and performance.
You also need to account for possible arithmetic overflow.
See also: Current time in microseconds in java

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

Retrieve number after point in BigDecimal number without RoundingMode

how to keep only 3 value after point in BigDecimal ?
i found a solution but it requirt a RoundingMode
BigDecimal d = BigDecimal.valueOf(0.5649);
System.out.println(d.remainder(BigDecimal.ONE));
System.out.println(d.remainder(BigDecimal.ONE).divide(BigDecimal.valueOf(1), 3, RoundingMode.CEILING));
i want to keep a number exact without rounding.
Just use setScale and RoundingMode.DOWN
Rounding mode to round towards zero. Never increments the digit prior
to a discarded fraction (i.e., truncates).
for example
BigDecimal.valueOf(0.5649).setScale(3, RoundingMode.DOWN)
BigDecimal isn't intended to be used with such limitations. Only ever wanting 3 decimals is a strange requirement. Maybe you only want to present 3 decimals to the users?
If so I suggest using: java.text.DecimalFormat
If you really want to make sure that you never do calculations with higher precission than 3 decimals I suggest making your own reprensentation/class. Internally you hold the value as a long (or appropriate class/primitive) but at a value 1000 times the actual value. All calculations are done with the internal reprensentation and when asked for a value, divide the internal value with 1000.0d and convert to double (or appropriate) and return.
I would use double for this.
double d = 0.5649;
d = (long) (d * 1000) / 1000.0; // round down.
System.out.println(d);
prints
0.564
or
d = (long) (d * 1000 + 0.5) / 1000.0; // round half up.

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