How to generate a random value bigger than value of System.currentTimeInMillis(). I use Random object.how can I obtain a value that have min range as System.currentTimeInMillis()?
Doesn't
long value = System.currentTimeMillis() + (long)random.nextInt(range);
work?
If you want to enforce a value that is strictly larger than System.currentTimeMillis() add an additional 1 to it. Set the range accordingly to prevent overflow (see assylias's comment).
Edited according to comments.
This is an approach if you want to be able to get numbers distributed across the entire range System.currentTimeMillis()..Long.MAX_VALUE:
long millis = System.currentTimeMillis();
long l = Math.min(Long.MAX_VALUE - millis, Math.abs(random.nextLong())) + millis;
Long.MAX_VALUE will be much more common than other results here though, in case that matters.
For a uniform distribution of times between currentTimeMillis and Long.MAX_VALUE, without overflow, you can use:
long time = System.currentTimeMillis();
long randomFutureTime = Math.abs(random.nextLong()) % (Long.MAX_VALUE - time) + time;
This may is useful to have real time of object creation, and two objects cannot have the same timestamp, so you can order them.
I use as UUID for my objects :
Const.DECAL_BIT = 20;
Const.DECAL_BIT_MASQUE = (Long.size() -1) - next 20;
private final Long timeCreate = (System.currentTimeMillis() << Const.DECAL_BIT)
+ (System.nanoTime() & Const.DECAL_BIT_MASQUE);
So you can have valid dates for 100 years : you multiply by 1M the internal datetime and had one second elapse time in nanosecond precision.
To read the date : Date d = Date((Long) timeCreate>> Const.DECAL_BIT);
Related
I have many time stamps showing at which time a user entered the room. I want to calculate an average time. The problem occurs when some action happens at night.
I tried to calculate it with milis, but it is wrong.
ArrayList<String> times = new ArrayList<String>();
times.add("00:20:01");
times.add("00:00:01");
times.add("23:40:01");
times.add("23:20:01");
times.add("23:20:01");
times.add("00:20:01");
times.add("23:40:01");
times.add("23:40:01");
times.add("00:00:01");
long commonMillis=0;
for (String date:times){
LocalTime time = new LocalTime(date);
long dayMilis = time.getMillisOfDay();
commonMillis = commonMillis + dayMilis;
}
LocalTime average = new LocalTime(commonMillis/times.size());
This code, for example, returns the value 14:08:54.333. Because the hours 00:00 and 23:00 -- calculated in millis -- are too far from each other.
Please help me to find right way to calculate the average time?
Three things:
You have to define an offset time:
If you want an average of times of different days without knowing the day, you have to define an offset time by yourself. This time is used to decide whether a time is belonging to the next day or not.
This offset time may be derived depending on the values you get.
Without an offset time, you implicitely use 0 o'clock.
Avoid overflows:
If your times list gets longer, you may run into an overflow if a long field is not sufficient to store the accumulated value. You can use a data structure which is overflow resistant like BigInteger or use the (culmulative) moving average approach.
Wrong result constructor:
The constructor LocalTime(long instant) implicitely uses your local DateTimeZone to calculate a local time from an Instant. This causes different times when using the same code between different time zones.
The method you want to use is LocalTime#fromMillisOfDay.
Here is an approach considering the above points:
long movingAverage = 0;
// 1. define offset
LocalTime offset = new LocalTime("12:00:00");
long offsetMillis = offset.getMillisOfDay();
for (String date : times) {
long sampleMillis = new LocalTime(date).getMillisOfDay();
// align to offset
if (sampleMillis < offsetMillis)
sampleMillis += DateTimeConstants.MILLIS_PER_DAY;
long diff = sampleMillis - offsetMillis;
// 2. use moving average
movingAverage = movingAverage + diff / times.size();
}
// 3. avoid LocalTime(long) constructor
LocalTime result = offset.plusMillis((int) movingAverage);
System.out.println(result); // 23:48:54.329
A naive approach would be to gather the long millisecond values in all the dates, add them up and divide them by the number of dates, transforming them back into a LocalDate. You probably need a BigInteger to hold the sum, though.
I have code which checks if the given "A" time (in milliseconds) is in the given "b" time period.
private static boolean isInTimeInterval(long time, int timePeriod) {
long curTime = Calendar.getInstance().getTimeInMillis();
// time period is in hours, 1 hour is 3600000 ms;
long startTime = curTime - timePeriod * 3600000;
if (time >= startTime && time < curTime){
return true;
}
return false;
}
I take the time from a file and parse it into a long like this:
(Long.parseLong(array[2]))
But it doesn't work correctly, what is wrong ?
To simplify things, I would suggest that you first subtract the start time from the end time, check to see if that is positive and then decide if the remaining milliseconds is smaller than the requested time period.
long difference = Calendar.getInstance().getTimeInMillis() - time;
long timeRange = timePeriod * 3600000;
return (0 <= difference && differance <= timeRange);
It makes the code slightly smaller in lines, but more importantly, it simplifies the math to where you know the code isn't the problem.
As far as the errors you are likely encountering, I'd look to your
Long.parseLong(array[2])
As that is likely grabbing the input in a manner you aren't expecting. For starters, I'd put in some logging or at least one-time println debugging statements to verify the input times are what I thought they were.
long startTime = System.nanoTime();
long startTimer = System.currentTimeMillis();
M = app.decriptare_simpla(C);
long endTime = System.nanoTime();
long stopTimer = System.currentTimeMillis();
//mesajul initial dupa decriptare
System.out.println("M : " + M.toString());
System.out.println("Decriptarea a durat: " + (endTime - startTime));
System.out.println("Decriptarea a durat: " + (stopTimer - startTimer));
This gave me:
Decriptarea a durat: 14811776
Decriptarea a durat: 15
What I want to ask is how much of a second are those 2 numbers? I mean are they, 0.15, 0.015, 0.0015...? I'd like to print them in that manner, not as an long but don't know how many decimals to add. Same question for the other number.
The conversions follow the usual rules for Standard SI Units:
long nanoSeconds = ...
double microSeconds = nanoSeconds / 1e3;
double milliSeconds = microSeconds / 1e3;
double seconds = milliSeconds / 1e3;
// Shortcuts:
double milliSeconds = nanoSeconds / 1e6;
double sconds = nanoSeconds / 1e9;
For some conversions, you can also have a look at the TimeUnit class: It allows conversions between values in different time units, for example
long microSeconds = NANOSECONDS.toMicros(nanoSeconds);
However, it unfortunately does not allow time spans given in double precision, but only as long values.
An aside, also mentioned in the comments: Measuring time spans in the order of 10-15ms usually makes no sense due to the limited resolution of the internal timer.
Have you tried like this
System.out.println(TimeUnit.SECONDS.convert((endTime - startTime), TimeUnit.NANOSECONDS));
System.out.println(TimeUnit.SECONDS.convert((stopTimer - startTimer), TimeUnit.MILLISECONDS));
I want to pass around a time number and the TimeUnit it is in.
long number = some number;
TimeUnit timeUnit = some arbitrary time unit
What can hold both the time and timeUnit in one Object from the Java libraries?
There is no Java library object that encapsulates a number and an arbitrary TimeUnit. However, there is one in Java 8 that converts itself into whatever time unit is required:
java.time.Duration
Duration stores the provided quantity and then provides comparison and conversion to all other time units. For example:
// Create duration from nano time
Duration systemTime = Duration.ofNanos(System.nanoTime());
// Create duration from millis time
Duration systemTime = Duration.ofMillis(System.currentTimeMillis());
Of course, if doing addition and subtraction or other math operations, the precision is only as good as the precision of the current operation and the supplied Duration.
/**
* Example that tells if something has reached the required age
* TRUE IF THE current system time is older or equal to the required system time
*/
// TRUE IF THE FILE HAS NOT WAITED ENOUGH TIME AFTER LAST CREATE/MODIFY
private boolean isMature() {
// it is not known whether required age is nanos or millis
Duration requiredAge = systemTimeWhenMature();
// so create a duration in whatever time unit you have
// more precise = possibly better here
Duration actualAge = Duration.ofNanos(System.nanoTime());
// if ON or OLDER THAN REQUIRED AGE
// actualAge - requiredAge = balance
// 20 - 21 = -1 (NOT MATURE)
// 21 - 21 = 0 (OK)
// 22 - 21 = 1 (OK)
Duration balance = actualAge.minus(requiredAge);
if (balance.isNegative()) {
logger.info("Something not yet expired. Expires in {} millis.", balance.negated());
return false;
} else {
return true;
}
}
And there are many more methods in Duration that are useful for converting and processing the stored quantity in various unit.
It is important to understand how the precision will affect calculations. This shows the
general precision contract by example:
// PICK A NUMBER THAT IS NOT THE SAME WHEN CONVERTED TO A LESSER PRECISION
long timeNanos = 1234567891011121314L;
long timeMillis = TimeUnit.MILLISECONDS.convert(timeNanos, TimeUnit.NANOSECONDS);
// create from milliseconds
Duration millisAccurate = Duration.ofMillis(timeMillis);
Duration nanosAccurate = Duration.ofNanos(timeNanos);
// false because of precision difference
assertFalse(timeMillis == timeNanos);
assertFalse(millisAccurate.equals(nanosAccurate));
// true because same logical precision conversion takes place
assertTrue(timeMillis - timeNanos <= 0);
assertTrue(millisAccurate.minus(nanosAccurate).isNegative());
// timeNanos has greater precision and therefore is > timeMillie
assertTrue(timeNanos - timeMillis > 0);
assertTrue(nanosAccurate.minus(millisAccurate).negated().isNegative());
In a nutshell .. I cannot believe it took me this long to find Duration!
:)
TimeUnit is just enum holding some time unit types like Second, Milliseconds, ...
TimeUnit is NOT for holding time BUT you can convert a time in a unit to another unit using TimeUnit API.
I think you have to create your object to hold time and its unit.
If you use Java 8. You can work with some new Date API
http://download.java.net/jdk8/docs/api/java/time/package-summary.html
In Joda-Time there is an Interval, but you'll need to create a Java Bean (perhaps calling it Interval) if you want to use only JRE inclusive Object types.
I'm wanting to have my JLabel display values in the format of HH:mm:ss without making use of any external libraries. (the label will update every second)
So for example, the following input in seconds and the desired output are below:
Seconds: Output:
--------------------------------------------------
long seconds = 0 00:00:00
long seconds = 5 00:00:05
long seconds = 500 00:08:20
long seconds = 5000 01:23:20
Note: the seconds value is of type long
I'm aware that typically one would just do the following conversions to get the desired numbers:
long s = 5000; //total seconds
long hrs = (s / 3600) //hours
long mins = ((s%3600)/60) //minutes
long secs = (s%60) //seconds
However, this leaves decimals on the values. Perhaps there is some sort of formatting that will allow me to toss the un-needed decimals.
Options I have come across were String.format(), SimpleDateFormat(), or concatenating a string myself.
The thing is, I will be updating this JLabel every second and sometimes it can count to the equivalent of 5-6 days if not longer.
So I'm looking for someone who has more experience in the area than I, and knows the most efficient way to tackle this issue.
I would use SimpleDateFormat if I were you.
If SDF is too slow for you, profile all your options and pick the fastest one, then refactor the rest of your code until it's fast enough.
Remember that premature optimization is the root of all evil, and that you should only really do any optimizing after you've profiled your code and missed your target execution time.
SimpleDateFormat() is really quite appropriate for your needs.
Use the TimeUnit class, as shown here in combination with the javax.swing.Timer class set to execute at 1 second intervals.
If you don't mind values wrapping then use SimpleDateFormat as follows. Remember x1000 to convert to milliseconds and to manually override the timezone.
long value = 5 * 24 * 3600 + 5000;
// wrapping solution
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
// ensure no daylight saving +1 hour
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(sdf.format(value * 1000));
Output
01:23:20
If you want the hours to go past 23.59.59 then this is the simplest I could come up with. I used DecimalFormat to force at least 2 digits for the hours.
long value = 5 * 24 * 3600 + 5000;
long hours = value / 3600; // whole hours
long mins = value / 60 - hours * 60;
long secs = value % 60;
System.out.println(String.format("%s:%2d:%2d",
new DecimalFormat("00").format(hours), mins, secs));
Output
121:23:20
I've found this to be extremely fast. Try it out. Seconds go from 0 - 59, minutes go from 0 - 59, hours go from 0 - 2,562,047,788,015. Afterwards the hours become negative and begin going towards that maximum.
performing the "+" operator on Strings is very slow. A StringBuilder performs grouping strings together the fastest from what I've seen. You should also be using "chars" not "String/Byte" Bytes are very slow as well. I'd prefer doing only multiplication however dividing by 36 and 6 give decimals that are to large for holding.
StringBuilder sb = new StringBuilder(8);
long hours = time / 3600000;
long minutes = (time - hours * 3600000) / 60000;
long seconds = (time - hours * 3600000 - minutes * 60000) / 1000;
if (hours < 10)
sb.append('0');
sb.append(hours);
sb.append(':');
if (minutes < 10)
sb.append('0');
sb.append(minutes);
sb.append(':');
if (seconds < 10)
sb.append('0');
sb.append(seconds);
String formattedTime = sb.toString();
.....
If you don't want to use a formatter class, you can get your work done by using basic operations like conversion among wrapper classes and String operations. Take a look at this code:
long h, m, s; // Initialize them after calculation.
String h1, m1, s1;
h1 = Long.toString( h );
m1 = Long.toString( m );
s1 = Long.toString( s );
if ( s1.length() < 2 )
s1 = "0" + s1;
if ( m1.length() < 2 )
m1 = "0" + m1;
if ( h1.length() < 2 )
h1 = "0" + h1;
String output = h1+":"+m1+":"+s1;
Supposing you have correctly calculated values of seconds, minutes and hours, you can gather String versions of these variables, then format them with a simple length check and finally concatenate these time unit parts.
i think you want to do the math you indicated, but take the floor of each value. then concatenate..
public class Test{
public static void main(String args[]){
double d = -100.675;
float f = -90;
System.out.println(Math.floor(d));
System.out.println(Math.floor(f));
System.out.println(Math.ceil(d));
System.out.println(Math.ceil(f));
}
}