String to int java.lang.NumberFormatException - java

I have java program which convert String to int, but the rang of String is 190520141618013381(above the rang of int) when i convert this int the java.lang.NumberFormatException: is thrown
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(format.format(date));
stringBuffer.append(demandCount);
int test_int = Integer.parseInt(stringBuffer.toString()); // exception has been fixed by putting
//long abc_i = Long.parseLong(abc);
log.info("test_int: "+test_int);
my question is that compiler should throw NumberOutOfRangException(if this Exception is available in API) instead java.lang.NumberFormatException:, the format of number(190520141618013381) is right.

The String 190520141618013381 is outside the range of an int but it also doesn't match the accepted format of an int because it is too long.
The compiler doesn't throw this error, it is thrown at runtime.
I believe it is correct to comply with the documentation for this method.
BTW Don't use StringBuffer, it was replaced by StringBuilder ten years ago.
IMHO storing a date as an integer isn't a good idea in general.
A more efficient to get a unique id which contains the time in millis is to do something like this.
private static final AtomicLong TS_COUNTER = new AtomicLong();
public static long nextTimeStamp() {
long time = System.currentTimeMillis() * 1000;
long curr = TS_COUNTER.get();
if (curr < time && TS_COUNTER.compareAndSet(curr, time))
return time;
return TS_COUNTER.incrementAndGet();
}
This will have the time-in-millis * 1000 plus a unique id. This works fine if you average less than one million ids per second.

Related

New Date() object gives the same value

I have some code that utilizes the Date object as the name of a file in order to have distinct file names every time but the strange thing is that a new Date object gives off the same toString() for each loop iteration. I mean, the following:
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
String fileName = sdf.format((d = new Date())) + ".jpg";
Log.d("Date", d.toString());
is executed in loops.
Side note: Since this is related to Java API, I haven't tagged the question as that of Android but the OS that executes this code is Android.
AFAIK, new Date() uses System.currentTimeMilis() as the init value, what might be reason for this unusual behavior?
You format your time as yyyyMMdd_HHmmss, but the run of a loop needs just milliseconds, so use yyyyMMdd_HHmmssSSS to get a more acurate time.
As Jon Skeet mentions in his comment, the run of a loop could even take less than a millisecond (depending on the tasks you perform), so you could run into issues with this solution as well!
java.time
The modern approach uses java.time classes.
The Instant class represents a point on the timeline with a resolution of nanoseconds. The Instant.now command captures the current moment in milliseconds in Java 8, and in microseconds in Java 9 (or perhaps finer).
Replace colon characters for macOS compatibility.
String filename = Instant.now().toString().replace( ":" , "-" ) + ".jpeg" ;
Note that even with milliseconds or microseconds resolution, you may still run into collisions if running brief code on fast cores. I suggest using UUID to eliminate such risk.
UUID
If you simply want unique file names without really needing to represent the current moment in the name, then use a UUID value rather a date-time.
The UUID class can generate some versions such as Version 4 (mostly random):
String filename = UUID.randomUUID() + ".jpeg" ;
Java in loop is faster than one second it will stay same
to make sure its always unique especially in multi threaded function.
Use somthing like this
SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss:SSSSSSS");
Some hints so you wont go into much debug trouble
printDate("dd.MM.yyyy HH:mm:ss.SSS");//02.05.2010 21:45:58.073
printDate("dd.MM.yyyy HH:mm:ss.SSSSSS");//02.05.2010 21:45:58.000073
printDate("dd.MM.yyyy HH:mm:ss.SSS'000'");//02.05.2010 21:45:58.073000
printDate("dd.MM.yyyy HH:mm:ss.'000000'");//02.05.2010 21:45:58.000000
tryToParseDate("dd.MM.yyyy HH:mm:ss.SSS");//good
tryToParseDate("dd.MM.yyyy HH:mm:ss.SSSSSS");//good
tryToParseDate("dd.MM.yyyy HH:mm:ss.SSS'000'");//bad
tryToParseDate("dd.MM.yyyy HH:mm:ss.'000000'");//good
Reference:
#slartidan Answer
String-Date conversion with nanoseconds
As Recommendation when i faced this situation :
1) If am calling from S3 AWS
files it should be named as unique at start of the file name it will make hashing and searching pretty fast. as from AWS S3 best practices to optimize.
public static String genarateFileName(String name) {
StringBuilder sb = new StringBuilder(name);
sb.insert(0, IdUtil.getUniqueUuid());in short to increase performance of S3 put and get etc..)
if (sb.lastIndexOf(".") != -1) {
sb.insert(sb.lastIndexOf("."), "_" + System.nanoTime());
} else {
sb.append("_").append(System.nanoTime());
}
return sb.toString();
}
2) To generate random nano
public static String getUniqueUuid() {
int rand = (int) (Math.random() * 100);
return Integer.toHexString(rand) + Long.toHexString(java.lang.System.nanoTime());
}
3) I do use both random nano with random string check below generates
random string of some length
/**
* Generate a random uuid of the specified length. Example: uuid(15) returns
* "VcydxgltxrVZSTV"
*
* #param len the desired number of characters
* #return
*/
public static String uuid(int len) {
return uuid(len, CHARS.length);
}
/**
* Generate a random uuid of the specified length, and radix. Examples: <ul>
* <li>uuid(8, 2) returns "01001010" (8 character ID, base=2) <li>uuid(8,
* 10) returns "47473046" (8 character ID, base=10) <li>uuid(8, 16) returns
* "098F4D35" (8 character ID, base=16) </ul>
*
* #param len the desired number of characters
* #param radix the number of allowable values for each character (must be
* <= 62)
* #return
*/
public static String uuid(int len, int radix) {
if (radix > CHARS.length) {
throw new IllegalArgumentException();
}
char[] uuid = new char[len];
// Compact form
for (int i = 0; i < len; i++) {
uuid[i] = CHARS[(int) (Math.random() * radix)];
}
return new String(uuid);
}
I see many answers pointing to use the classes from java.time package instead of java.util.Date. But, to precisely answer the question, I would say that moving to a different package will not automatically solve the problem.
In fact, the loop is running faster than the rate at which the value of new Date() can change. In order to see different values for invocation of new Date(), put a Thread.sleep(1*60*1000) between each iteration (The sleep value can be as per your requirement).

Java 8 Time - Equivalent of .NET DateTime.MaxValue.Ticks

I've included the whole method below, but really the challenge is simulating DateTime.MaxValue.Ticks in Java 8. I also don't know the equivalent of ".ToString("D19") in Java.
I thought I had figured out how to begin, which was by using Instant.MAX.toEpochMilli(), which I could then multiply by 10000 to get Ticks. Sadly, this simple statement throws an exception, so it's a non-starter:
Caught: java.lang.ArithmeticException: long overflow
Here is the original method. It's used to query Azure Storage Tables for historical metrics.
// Creates a TableQuery for getting metrics by timestamp
private static TableQuery GenerateMetricTimestampQuery(string partitionKey, DateTime startTime, DateTime endTime)
{
return GenerateMetricQuery(
partitionKey,
(DateTime.MaxValue.Ticks - endTime.Ticks + 1).ToString("D19") + "__",
(DateTime.MaxValue.Ticks - startTime.Ticks).ToString("D19") + "__");
}
Here is an example of a RowKey field value:
2519303419199999999__
I've spent a day on this and I'm pretty stumped. Any help would be greatly appreciated.
If possible, I would prefer to do this without JodaTime.
UPDATE1*** Based on a comment, here is an example of the exception in Java.
import java.time.Instant;
public class Tester {
public static void main(String[] args){
System.out.println(Instant.MAX.toEpochMilli());
}
}
UPDATE Original answer didn't account for offset difference between Java epoch (1970) and .NET ticks (0001). Corrected!
For reference, Long.MAX_VALUE (Java) is:
9,223,372,036,854,775,807
In .NET, DateTime.MaxValue is:
9999-12-31 23:59:59.9999999
3,155,378,975,999,999,999 ticks1 (~ 1/3 of long)
In Java 8, Instant.MAX is:
+1000000000-12-31 23:59:59.999999999
31,556,889,864,403,199,999,999,999 nanos (overflows long)
315,568,898,644,031,999,999,999 ticks2 (overflows long)
31,556,889,864,403,199,999 millis (overflows long)
31,556,889,864,403,199 seconds (~ 1/292 of long)
For reference, your value of 2519303419199999999 is:
2016-08-23 13:28:00
636,075,556,800,000,000 ticks1 (~ 1/14 of long)
14,719,588,800,000,000 ticks2 (~ 1/626 of long)
1) Since 0001-01-01 (.NET) 2) Since 1970-01-01 (Java)
As you can see, Instant.MAX in "ticks" will not fit in a long. Not even milliseconds will fit.
More importantly Instant.MAX is not the same value as DateTime.MaxValue.
I would suggest you just create a constant for the value, e.g.
public static final long DATETIME_MAXVALUE_TICKS = 3155378975999999999L; // .NET: DateTime.MaxValue.Ticks
That way you'll get same string values as you .NET code:
public static final long EPOCH_OFFSET = 62135596800L; // -Instant.parse("0001-01-01T00:00:00Z").getEpochSecond()
private static long getTicks(Instant instant) {
long seconds = Math.addExact(instant.getEpochSecond(), EPOCH_OFFSET);
long ticks = Math.multiplyExact(seconds, 10_000_000L);
return Math.addExact(ticks, instant.getNano() / 100);
}
public static void main(String[] args) {
Instant startTime = Instant.parse("2016-08-23T13:28:00Z");
String s = String.format("%19d", DATETIME_MAXVALUE_TICKS - getTicks(startTime));
System.out.println(s);
}
Output:
2519303419199999999
long maxSeconds = Instant.MAX.getEpochSecond(); //31556889864403199
int maxNanos = Instant.MAX.getNano(); //999999999
These two values can be used together to create a precise MAX value as number:
31556889864403199,999999999
If you need to print it you need to join them as String.
You can also create a BigDecimal from these two values like:
BigDecimal max = new BigDecimal(Long.toString(maxSeconds) + "." + String.format("%09d", maxNanos));
And operate on it:
BigDecimal now = new BigDecimal(String.format("%d.%09d", Instant.now().getEpochSecond(), Instant.now().getNano()));
System.out.println(max.subtract(now).toString());

Strange happenings when getting average milliseconds and converting to time

I am having some strange output when I am attempting to get an average from a long value and converting it to a String (in HH:mm:ss) format. I'm using the Joda time library, which mostly has been a life saver.
Here's what I have so far:
//this is in a static class
public static Duration calculateTime(Date start, Date end) {
Duration duration = new Duration(start.getTime(), end.getTime());
return duration;
}
public static String convertMillisToTime(long milliseconds) {
return String.format("%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(milliseconds),
TimeUnit.MILLISECONDS.toMinutes(milliseconds) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(milliseconds)),
TimeUnit.MILLISECONDS.toSeconds(milliseconds) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliseconds)));
}
long averageRunTime = 0;
averageRunTime += calculateTime(drs.startTime, drs.endTime).getMillis();
Since this is done in an array list, to get the average, I am taking
averageRunTime = averageRunTime / (long)arrayList.size();
when I get to the point of
convertMillisToTime(averageRunTime);
It's returning a value that is higher than any times I have. IE( I have no job times that are over 11 hours) but this is returning me a String with 11:mm:ss. Not quite sure WHY?
I used the convertMillisToTime from: How to convert milliseconds to "hh:mm:ss" format?
Can anyone point me in the right direction?
Thank you in advance,
RR
Edit: I've modified the code that converts the long to time using TimeUnit. It's strange though, I grabbed three runs (time streams) and got 09:14:17, 08:57:18, 09:10:25 for the length of each run, and the average is coming out as: 10:27:26.
You could just use a formatter from Joda Time instead, for example...
public static final PeriodFormatter PERIOD_FORMATTER = new PeriodFormatterBuilder().printZeroAlways().
appendHours().appendSeparator(":").
appendMinutes().appendSeparator(":").
appendSeconds().appendSeparator(".").
appendMillis().toFormatter();
public static String toString(Duration duration) {
return duration == null ? "[invalid duration]" : duration.toPeriod().toString(PERIOD_FORMATTER);
}

How do I convert int into char[] to display time?

I've written a simulation and would like to display the time in the JFrame along with the animation. I am calling my animation by overriding the paintComponent method and repainting every timestep. However, my time counter is in (int)seconds, and the only method I know to write text is g.drawChars, which requires an array of chars.
Any idea on how I can convert my time in seconds to char array so I can display time in a human-readable way?
Suppose yourIntValue represents your seconds.
new Integer(yourIntValue).toString().toCharArray() should do the trick.
The easier way is using String.valueOf(yourIntValue).toCharArray()
You can convert first to String and then convert to char array.
int time = 10;
char[] chars = Integer.toString(time).toCharArray();
String is a char[] 1
So you can just convert your int to String and then return the char[]
String.valueOf(i).toCharArray();
1 Elaborating a bit on that statement.
If you look at the String class you will see that it implements CharSequence
It also declares, and adds the javadoc comment
/** The value is used for character storage. */
private final char value[];
For brevity I will also just post the default constructor for String
public String() {
this.offset = 0;
this.count = 0;
this.value = new char[0];
}
You can have a look at the other constructors to see how it builds the char[] for every String.
Edit:
I wanted to comment on one of the other answers, but I have not enough rep, so I will post it as part of my answer.
String.valueOf(i).toCharArray();
and
Integer.toString(i).toCharArray();
is the (almost) same call. This is because the valueOf(int i) method of String is:
public static String valueOf(int i) {
return Integer.toString(i, 10);
}
Do you want the time formatted or just displayed as a second count?
As a second count do:
String.valueOf(yourInt).toCharArray();
To format it do:
String time = (yourInt/(60*60))+":"+((yourInt/60)%60)+":"+(yourInt%60);
time.toCharArray();
But the graphics objects have a drawString() option which will allow you to skip the toCharArray() step anyway.
I'd do it like this:
int minutes = seconds / 60;
int remainingSeconds = seconds - (minutes * 60); // or int remainingSeconds = seconds % 60
String time = minutes + ":" + remainingSeconds;
char[] timeCharArray = time.toCharArray();
Also see the documentation of toCharArray().
Convert time from int to Date (miliseconds is the int you have, just transform it from seconds to miliseconds):
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(milliSeconds);
Date date = calendar.getTime();
Parse the date to local format and you get a string (example of format is "dd.MM.yyyy"):
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
String humanReadableDate = sdf.format(date);

Date calculation - progressbar showing timeleft

i want to make a simple progressbar showing me how much time some process takes. At the moment of creation of it I have only actual percentage (as int) and time that is left(as String formatted HH:mm:ss). I want it to update every second and show me the actual state of process. I've tried everything and it doesn't work. Current version looks like this - tell me please what I'm doing wrong...
int initialProgress = 35; // %
// time to finish process
Date endDate = new SimpleDateFormat("HH:mm:ss").parse("07:07:07");
Date now = new Date();
long totalDuration = (long) (((double)(endDate.getTimeInMillis()
- now.getTimeInMillis()) * 100.0 / (double)initialProgress);
and then every second I repeat:
now = new Date();
int currentProgress = (totalDuration - endDate.getTimeInMillis()
+ now.getTimeInMillis())/totalDuration;
It simply is not working. Total duration is even something strange...
The issue seems to be that you have a time remaining String and you want to parse it to percentage of work done.
The first thing you need, obviously, is the total expected time. Lets assume that this is also a String.
First write a method for parsing your HH:mm:ss String to a long representing time remaining in seconds.
public long parseToSeconds(final String duration) throws ParseException {
final MessageFormat durationFormat = new MessageFormat("{0,number,#}:{1,number,#}:{2,number,#}");
final Object[] parsedTimeRemaining = durationFormat.parse(duration);
final long totalDuration = TimeUnit.HOURS.toSeconds((Long) parsedTimeRemaining[0])
+ TimeUnit.MINUTES.toSeconds((Long) parsedTimeRemaining[1])
+ (Long) parsedTimeRemaining[2];
return totalDuration;
}
What we do here is use a MessageFormat to parse your String into an array of Object. As we have told the MessageFormat that these are numbers, it will automagically convert (or try to convert, hence the exception) to Long.
Once we have those numbers we scale them all to seconds using the (very useful) TimeUnit class.
A couple of quick tests to ensure we're on the right track:
System.out.println(parseToSeconds("00:00:01"));
System.out.println(parseToSeconds("00:01:00"));
System.out.println(parseToSeconds("01:00:00"));
System.out.println(parseToSeconds("01:01:01"));
Output:
1
60
3600
3661
Looks good.
Lets assume that right as the start of the process we get a time remaining, for simplicity, of "04:04:04", this gives 14644. Now we just need to store that and calculate the percentage against any new duration String. This should do the trick:
public int asPercentage(final long totalTime, final long remaining) {
final double percentage = remaining / ((double) totalTime);
return (int) (percentage * 100);
}
Note the fact that I cast (seemingly pointlessly) one of the items to a double. This is because in Java any operation on an integral type always returns another integral type. Casting to a double forces it to return a double.
Lets do a quick check again:
final long totalDuration = 14644;
System.out.println(asPercentage(totalDuration, parseToSeconds("03:03:03")));
System.out.println(asPercentage(totalDuration, parseToSeconds("02:02:02")));
System.out.println(asPercentage(totalDuration, parseToSeconds("01:01:01")));
Output:
75
50
25
Looks good, that is the time remaining as a percentage of the total. Maybe to quite what we want for a progress bar. Lets invert it:
public static int asPercentage(final long totalTime, final long remaining) {
final double percentage = remaining / ((double) totalTime);
return 100 - (int) (percentage * 100);
}
Output:
25
50
75
Ah-ha. Much better.

Categories

Resources