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);
Related
I need help with this string format: "08/13/2015 10:03:50"
I would like to compare the time within a range of 2 min. I get regex to a point but would not know how to go about this when the time is in string format and the cross over to another hour, (Ex. 10:59:30 would lap over to 11:01:30 not 10:61:30).
Code would be something like
string1 = "08/13/2015 10:03:50";
string2 = "08/13/2015 10:05:50, 08/13/2015 10:55:50, 08/13/2015 10:15:50,
08/13/2015 10:14:50, 08/13/2015 10:25:50, 08/13/2015 10:55:50";
if(string2.contains("string1(with plus or minus 2 of string1 min)"){
//Pass
}
Code I am using to grab the date
DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
Calendar cal = Calendar.getInstance();
String timeOfUpdate = dateFormat.format(cal.getTime());
System.out.println(timeOfUpdate);
Parse the Strings as Date like suggested in the comments, then retrieve the timestamps of both Date objects through the getTime() method. Subtract these two numbers from one another. This get's you the chronological distance of these times in milliseconds, which you can compare to your criteria converted to milliseconds.
Update regarding the date list addendum: To evaluate a String containing a list of dates, you have to split the string along the list separator into an array of strings by using String#split().
Then, you can parse each sub string into a Date object and retrieve the timestamp of each as per the #getTime() method mentioned in the first paragraph. Collect these timestamps into a list.
This list can be searched for entries within the expected range, for example using the Stream API's filter function (Java 8 and newer). Here's a short tutorial about that function.
Try executing the below steps:
Convert String1 into Date Object and apply getTime() method, store the result in some variable
Convert String2 into a array of Strings by using split on comma
Run a loop on results retrieved in step#2, inside loop
Convert each value fetched into Date Object
Call getTime on date object converted
Subtract this number with the one fetched in Step#1
Now you will get the difference in milliseconds(1 min = 60000 miliseconds)
if the difference is either greater than -120000 or less than 120000 miliseconds than break the loop and set the flag to true.
Let me know if you still face any issue.
You can use date.getTime() for getting date in milliseconds since 1970 and split your date string arrays :
int offsetMinutes = 2;
String string1 = "08/13/2015 10:03:50, 08/14/2015 10:05:50, 08/14/2015 10:05:50";
String string2 = "08/13/2015 10:05:49, 08/14/2015 10:05:50, 08/15/2015 10:05:50";
String[] string1Array = string1.split(",");
String[] string2Array = string2.split(",");
DateFormat format = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss", Locale.ENGLISH);
for (int j = 0 ; j< string1Array.length;j++)
{
Date date1 = format.parse(string1Array[j].trim());
for (int i = 0; i < string2Array.length; i++) {
Date date2 = format.parse(string2Array[i].trim());
if (date1.getTime() >= (date2.getTime() + offsetMinutes * 60 * 1000) || date1.getTime() <= (date2.getTime() - offsetMinutes * 60 * 1000)) {
//Here we are
}
}
}
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.
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);
}
Class level variables:
static int secondsInterval = 100000000;
static long secondsSpecial=0;
static Date dateSecondsReg;
I have the following function I pass two arguments to this function:
The number of seconds which have elapsed since a certain date.
The actual date (Beginning date) since when the calculation commences.
the method is:
public static void secondsToNotify(long seconds, String d){
Date dt = Convert(d);
System.out.println(""+dt);
Calendar cal = Calendar.getInstance();
cal.setTime(dt);
secondsSpecial = secondsInterval*(1+(seconds/secondsInterval));
cal.add(Calendar.SECOND, (int) secondsSpecial);
dateSecondsReg = cal.getTime();
System.out.println(""+dateSecondsReg);
System.out.println(""+secondsSpecial);
}
I pass the following arguments to the method:
secondsToNotify(2682810000L, "1929-01-02");
To my amazement the resulting date, instead of being in future is in past:
Results
1929-01-02
Mon Jun 17 17:08:24 IST 1878
2700000000
Cant understand where I am going wrong, any hints?
seconds / secondsInterval will be carried out in integer arithmetic which means that any remainder is lost.
Pre-multiplying by 1.0 will force the calculation to be carried out in floating point:
1.0 * seconds / secondsInterval
(P.S. Eventually, your cast (int)secondsSpecial will give you trouble if secondsSpecial gets large: you need to rethink that. One idea would be to drop all your int types. Then, as a workaround to Calendar.add having an int as the interval argument, convert secondsSpecial to years and seconds and add the intervals successively.)
you have an integer overflow here
Cal.add(Calendar.SECOND, (int) secondsSpecial);
that cast to int results in -1594967296 being passed
Check System.out.println(Integer.MAX_VALUE); will give 2147483647 ie 2^31 -1
since it seems that Calendar.add only takes in int as increment how about
cal.setTimeInMillis(dt.getTime() + secondsSpecial)
I think the problem lies in:
Cal.add(Calendar.SECOND, (int) secondsSpecial);
You're casting a long to int, and unless I've miscounted a zero or two I think your long is bigger than Integer.MAX_VALUE. So this will wrap around to some negative number, and there's your subtraction.
(For the record, starting variable names with capital letters is very bad style in Java, and made your code quite hard to read.)
For anyone who stumbles here, this is what I came up with as of now ( Not too robust though, improving it)
public class testSplSec {
static int secondsInterval = 100000000;
static long secondsSpecial=0;
static Date dateSecondsReg;
static Integer intValue;
public static void secondsToNotify(long seconds, String d){
Date dt = Convert(d);
System.out.println(""+dt);
Calendar cal = Calendar.getInstance();
cal.setTime(dt);
secondsSpecial = secondsInterval*(1+(seconds/secondsInterval));
System.out.println(""+(secondsSpecial));
long hour = (secondsSpecial /60)/60;
System.out.println(""+hour);
if(hour >= Integer.MAX_VALUE){
}else{
intValue = (int) (long)hour;
}
cal.add(Calendar.HOUR,intValue);
dateSecondsReg = cal.getTime();
System.out.println(""+dateSecondsReg);
System.out.println(""+secondsSpecial);
}
public static Date Convert(String S){
String DateStr = S;
Date d = null;
try {
d = new SimpleDateFormat("yyyy-MM-dd").parse(DateStr);
} catch (ParseException e) {
e.printStackTrace();
}
java.sql.Date d1 = new java.sql.Date(d.getTime());
return d1;
}
public static void main(String[] args){
secondsToNotify(2682810000L, "1929-01-02");
}
}
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.