Get the seconds number from timestamp - java

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

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

Why is System.nanoTime() returning such a large number, when that much time has not been elapsed?

So I'm pretty new at Java, but I'm making a text adventure game for CompSci, and this is my code for levels.
public static int level(int exp, Long time, int levelnum) {
//Time is the time elapsed since the program started
time = System.nanoTime();
//I divi de by 10,000,000 twice because that sqared is 100 trillion, the conversion factor between nano and second
exp = (int)(Math.round(time/10000000));
exp = Math.round(exp/10000000);
//The exp, or experience, is the percent, under 100, of the way to the next level. 1 is 10%, 2 is 20, etc.
while (exp > 10){
//This loop will check to make sure exp is under 10. If not, it will add one to the level number, and then subtract 10 from the exp and check again.
levelnum++;
exp = exp - 10;
}
int bar;
bar =1;
//Bar is here because originally, I planned on this all being one method, the next one and this, and so I placed it in meaning for it to act as the return value. It has stayed the return value.
System.out.println(levelnum + "\n" + exp + "\n" + time);
//That was for debugging purposes, so I could see the levels data as it processed.
progBar(levelnum, exp);
return bar;
}
public static void progBar(int levelnum, int exp){
char barOpen, barClose;
String bar = "";
String emptyBar;
//I realize now that I could have just "[" + bar + "]", but at the time i didnt think of that
barOpen = '[';
barClose = ']';
if (exp > 1){
//ok so if the experience is greater than 1, then we repeat the = that many times. That way, we don't repeat it when we have one
bar = "=".repeat(exp);
}else if (exp <= 1){
bar = "=";
}
//This makes sure we have the adequate space between the experience and the bar close
emptyBar = " ".repeat(10-exp);
System.out.println("You are currently level " + levelnum + "\n" + barOpen + bar + emptyBar + barClose);
}
When I ran this yesterday, it succeeded in the level barring. However, today System.nanoTime() has begun to give extremely large numbers, even in different machines, none of which accurately represent the time which has elapsed. How could I fix this?
//Time is the time elapsed since the program started
time = System.nanoTime();
No, it is not.
The actual number returned by nanoTime has no specific meaning. It can only be used to measure the duration of time that has passed between two calls to nanoTime. And those calls have to be within the same program run, on the same machine. It is not comparable between different runs, even on the same machine.
tl;dr
The only meaning you should assign to System.nanoTime is to call it twice and compare the two values as an approximate number of elapsed nanoseconds. Do not interpret the two values as being anything other than as minuend and subtrahend (the two parts of a subtraction operation) for elapsed nanos.
Duration.ofNanos( System.nanoTime() - start )
Large or small nanoTime is irrelevant
Read the documentation:
This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time. The value returned represents nanoseconds since some fixed but arbitrary origin time (perhaps in the future, so values may be negative).
The number returned by this method has no meaning other than to be compared to another such returned value to track elapsed time on a scale of nanoseconds.
So whether the number returned is large or small is irrelevant. Comparing the returned numbers between computers or JVMs is meaningless.
In my experience, the numbers may be a count of nanoseconds since the host machine was booted. But you should never count on that. Such a fact is but a mere implementation detail. That detail may differ between Java implementations, or between host OSes.
Also, keep in mind that your computer hardware is not likely able to track time precisely by single nanoseconds. So elapsed time will be approximate.
The number returned represents nanoseconds. That means a billionth of a second. So your math is invalid.
Duration
Java offers you a class to track a span of time unattached to the timeline on a scale of nanoseconds: Duration. So no need for you to do any math.
long start = System.nanoTime() ;
…
Duration duration = Duration.ofNanos( System.nanoTime() - start ) ;
String report = duration.toString() ;
You may interrogate for the amount of elapsed time by calling the various to… methods.
Tips:
If doing benchmarking, consider using the jmh library.
If doing regular business-style apps, use java.time.Instant class to capture moments.

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

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