I want to calculate the total running time of my program from start to end and refresh running time in JFrame, but when I run my program I get excess 70 years, 1 day and 2 hours. Why ? What wrong ?
private void setMachineTime(){
Timer timer = new Timer();
long startTime = new Date().getTime();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
long endTime = new Date().getTime();
long diffTime = endTime - startTime ;
String time = new SimpleDateFormat("yy:mm:dd:HH:mm:ss").format(diffTime);
System.out.println(time);
}
}, 0, 1000);
}
actual result
UPD:
I rewrote code with my own format time method. Now I got what I want. Thanks to all of you.
private void setMachineTime(){
Timer timer = new Timer();
long startTime = new Date().getTime();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
long endTime = new Date().getTime();
long diffTime = endTime - startTime;
String diffSeconds = formatTime(diffTime / 1000 % 60);
String diffMinutes = formatTime(diffTime / (60 * 1000) % 60);
String diffHours = formatTime(diffTime / (60 * 60 * 1000) % 24);
System.out.println(diffHours + ":" + diffMinutes + ":" + diffSeconds);
}
}, 0, 1000);
}
private String formatTime(long diff){
long t;
t = diff;
if(t < 10){
return String.valueOf("0"+t);
} else {
return String.valueOf(t);
}
}
You are formatting the time difference as yy:mm:dd:HH:mm:ss. Just printing out diffTime would give you the milliseconds, divide by 1000 if you need seconds.
EDIT: I think i see what you are trying to do, but you are dealing with a time interval, which cannot be formatted as a date. You'll need to roll your own formatting for displaying the time as seconds, minutes, hours etc. or use an external library.
getTime return number of milliseconds from 1.1.1970...and same is for SimpleDateFormat converting number to date (and then formating it). It means when your diffTime = 0, SimpleDateFormat will try to format Date 1.1.1970 0:00:00 and with your formating string it will be 70:01:01:00:00:00. Try to use http://joda-time.sourceforge.net/api-release/org/joda/time/Interval.html instead.
And by the way, your formating string is wrong anyway...you use mm where I supouse you wanted month...but mm are minutes.
Related
I want to make a function to compare with the estimated time and actual time.
if estimated time = actual time + 15 minutes
return delay
for example:
estimated time = "09:00"
actual time = "09:15" late
How can i do it in android java ?
Quick solution to be able to use parameters easily is to use Duration.
You can get the duration between to "time". From this, you can easily check of this is in a valid delay or not comparing two Duration.
Using Duration.between with two LocalTime, you will get the duration between the two. Then you just need to compare this with a specific duration of time, something like this :
//Our times for this test.
LocalTime lt1 = LocalTime.of(9, 0);
LocalTime lt2 = LocalTime.of(9, 10);
//A duration of 15minutes, used to validate the difference between the two times
Duration delay = Duration.ofMinutes(15);
//A duration between two times
Duration d = Duration.between(lt1, lt2);
//Is less than, or equal to the duration.
boolean isValid = d.compareTo(delay) <= 0;
Using :
import java.time.Duration;
import java.time.LocalTime;
A more complete test code
LocalTime lt1 = LocalTime.of(9, 0);
LocalTime lt2 = LocalTime.of(9, 10);
LocalTime lt3 = LocalTime.of(9, 15);
LocalTime lt4 = LocalTime.of(9, 20);
Duration delay = Duration.ofMinutes(15);
System.out.format("%s and %s as more than %s delay : %s%n", lt1, lt2, delay, Duration.between(lt1, lt2).compareTo(delay));
System.out.format("%s and %s as more than %s delay : %s%n", lt1, lt3, delay, Duration.between(lt1, lt3).compareTo(delay));
System.out.format("%s and %s as more than %s delay : %s%n", lt1, lt4, delay, Duration.between(lt1, lt4).compareTo(delay));
Output :
09:00 and 09:10 as more than PT15M delay : -1
09:00 and 09:15 as more than PT15M delay : 0
09:00 and 09:20 as more than PT15M delay : 1
You can easily use different Duration values and it is not complicated to get a LocalTime from a String, a LocalDateTime or even a Date.
private void compareTime(String lastTime) {
SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss aa", Locale.US);
String currentTime = format.format(new Date(System.currentTimeMillis()));
Date date2 = null;
Date date1 = null;
try {
date1 = format.parse(lastTime);
date2 = format.parse(currentTime);
} catch (ParseException e) {
e.printStackTrace();
}
assert date2 != null;
long difference = (date2.getTime() - date1.getTime()) / 1000;
long hours = difference % (24 * 3600) / 3600; // Calculating Hours
long minute = difference % 3600 / 60; // Calculating minutes if there is any minutes difference
long min = minute + (hours * 60);
if (min > 24 || min < -24) {
}
}
Your lastTime should be in "hh:mm:ss aa" this format as same to currentTime.
I have made a Countdown to a future date (with remaining days, hours, minutes, seconds) using CountDownTimer and lots of code from this answer: https://stackoverflow.com/a/32773716/3984944
Now I want to do exactly the same but counting up from a past date. My TextView should refresh every second and show the elapsed time.
What I tried:
I tried manipulating the CountDownTimer so that it works in reverse order. Changing the interval to -1000 or adding 2000 milliseconds to the Countdown every second. Both didn't work.
Then I figured I should use the Chronometer class. The standard Chronometer only displays hours, minutes and seconds as far as I'm concerned. So no days. I then wrote the following code in the style of the CountDownTimer answer I found before that updates a TextView with the desired data:
final Chronometer ch = (Chronometer) findViewById(R.id.ch_chronometer);
final TextView tv = (TextView) findViewById(R.id.tv_show_stopwatch);
ch.setBase(endMillis); //endMillis is the date in Milliseconds
chCountdownSince.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
public void onChronometerTick(Chronometer cArg) {
long t = System.currentTimeMillis() - chCountdownSince.getBase();
long days = TimeUnit.MILLISECONDS.toDays(t);
t -= TimeUnit.DAYS.toMillis(days);
long hours = TimeUnit.MILLISECONDS.toHours(t);
t -= TimeUnit.HOURS.toMillis(hours);
long minutes = TimeUnit.MILLISECONDS.toMinutes(t);
t -= TimeUnit.MINUTES.toMillis(minutes);
long seconds = TimeUnit.MILLISECONDS.toSeconds(t);
String stopwatchDisplay = "Days: %d Hours: %d Minutes: %d Seconds: %d";
stopwatchDisplay = String.format(stopwatchDisplay, days, hours, minutes, seconds);
tv.setText(stopwatchDisplay);
}
});
I feel like this snipped makes absolute sense but upon execution it doesn't change my TextView at all. I feel like this is just not how Chronometer works but I don't know what I'm doing wrong.
Edit :
I think you forgot to start Chronometer completely.
Given that
The calls to onTick(long) are synchronized to this object so that one
call to onTick(long) won't ever occur before the previous callback is
complete.
Its unlikely that ticks are done on UI thread, but this is exactly where you need to set your text, try changing
tv.setText(stopwatchDisplay);
to
tv.post(new Runnable() {
public void run() {
tv.setText(stopwatchDisplay);
});
please use handler..
public void countDownStart() {
handler = new Handler();
runnable = new Runnable(){
#Override
public void run(){
handler.postDelayed(this,1000);
try {
FestCountdownTimer timer = new FestCountdownTimer(00, 00, 9, 3, 01, 2017);
new CountDownTimer(timer.getIntervalMillis(), 1000) {
#Override
public void onTick(long millisUntilFinished){
int days = (int) ((millisUntilFinished / 1000) / 86400);
int hours = (int) (((millisUntilFinished / 1000)
- (days * 86400)) / 3600);
int minutes = (int) (((millisUntilFinished / 1000)
- (days * 86400) - (hours * 3600)) / 60);
int seconds = (int) ((millisUntilFinished / 1000) % 60);
String countdown = String.format("%02dd %02dh %02dm %02ds", days,
hours, minutes, seconds);
txtTimerDay.setText("" + String.format("%02d", days));
txtTimerHour.setText("" + String.format("%02d", hours));
txtTimerMinute.setText(""
+ String.format("%02d", minutes));
txtTimerSecond.setText(""
+ String.format("%02d", seconds));
}
#Override
public void onFinish() {
textViewGone();
MainActivity.aSwitch.setChecked(false);
creditText.setText("Toggle On To Start");
}
}.start();
} catch (Exception e) {
e.printStackTrace(); }
}
};
handler.postDelayed(runnable, 1 * 1000);
}
Remember, 9 is Hours,3 is date,1 is Febraury Month..Month starts from 0th Index
FestCountdownTimer class
public class FestCountdownTimer {
private long intervalMillis;
public FestCountdownTimer(int second, int minute, int hour, int monthDay, int month, int year) {
Time futureTime = new Time();
// Set date to future time
futureTime.set(second, minute, hour, monthDay, month, year);
futureTime.normalize(true);
long futureMillis = futureTime.toMillis(true);
Time timeNow = new Time();
// Set date to current time
timeNow.setToNow();
timeNow.normalize(true);
long nowMillis = timeNow.toMillis(true);
// Subtract current milliseconds time from future milliseconds time to retrieve interval
intervalMillis = futureMillis - nowMillis;
}
public long getIntervalMillis() {
return intervalMillis;
}
}
Hope it helps.. :)
I want to add string time with format HH:mm:ss and special hour field. Example :
"20:15:30" (string) add "13:50:35" (string) -> result i want : "34:06:05" (string).
I have search similar code :
String time1="20:15:30";
String time2="13:50:35";
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
timeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date1 = timeFormat.parse(time1);
Date date2 = timeFormat.parse(time2);
long sum = date1.getTime() + date2.getTime();
String date3 = timeFormat.format(new Date(sum));
System.out.println("The sum is "+ date3);
And result of above code : The sum is 10:06:05 not i want. How is easy way to do this ?
You could simply take advantage of either Java 8's or Joda Time's duration capabilities.
For example, this simply creates a duration which is the sum of the number of seconds of the two times
LocalTime lt1 = LocalTime.parse("20:15:30", DateTimeFormatter.ofPattern("HH:mm:ss"));
LocalTime lt2 = LocalTime.parse("13:50:35", DateTimeFormatter.ofPattern("HH:mm:ss"));
//long t = lt1.toSecondOfDay() + lt2.toSecondOfDay();
//Duration duration = Duration.ofSeconds(t);
Duration duration = Duration.between(lt2, lt1);
System.out.println(formatDuration(duration));
Which prints out 34:06:05
formatDuration method
public static String formatDuration(Duration duration) {
long hours = duration.toHours();
duration = duration.minusHours(hours);
long minutes = duration.toMinutes();
duration = duration.minusMinutes(minutes);
long seconds = duration.getSeconds();
return String.format("%02d:%02d:%02d", hours, minutes, seconds);
}
SimpleDateFormat can't do that, but you can do it yourself, by parsing the input with a regular expression, and formatting the output with the format method.
private static String addTime(String ... times) {
if (times.length < 2)
throw new IllegalArgumentException("At least 2 times are required");
Pattern timePattern = Pattern.compile("([0-9]+):([0-5][0-9]):([0-5][0-9])");
// Parse times and sum hours, minutes, and seconds
int hour = 0, minute = 0, second = 0;
for (String time : times) {
Matcher m = timePattern.matcher(time);
if (! m.matches())
throw new IllegalArgumentException("Invalid time: " + time);
hour += Integer.parseInt(m.group(1));
minute += Integer.parseInt(m.group(2));
second += Integer.parseInt(m.group(3));
}
// Handle overflow
minute += second / 60; second %= 60;
hour += minute / 60; minute %= 60;
// Format and return result
return String.format("%02d:%02d:%02d", hour, minute, second);
}
Test
System.out.println(addTime("20:15:30", "13:50:35"));
System.out.println(addTime("20:15:30", "13:50:35", "20:15:30", "13:50:35"));
System.out.println(addTime("98765:43:21", "12:34:56"));
Output
34:06:05
68:12:10
98778:18:17
Trying to make a small countdown timer in my app but it's not working.
Idea is to count down to a specific time. First by days and when it gets closer, by hours.
The following method is inside my Fragmentclass.java (so it's a fragment)
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onViewCreated(view, savedInstanceState);
Calendar cal = Calendar.getInstance();
cal.set(2012, 8, 29, 10, 0);
long endTime = cal.getTimeInMillis();
long currentTime = System.currentTimeMillis();
long remaining = currentTime - endTime;
long seconds = remaining / 1000 % 60;
new CountDownTimer(seconds, 1000) {
TextView tv = (TextView)getActivity().findViewById(R.id.introTimeLeft);
public void onTick(long millisUntilFinished) {
Calendar cal = Calendar.getInstance();
cal.set(2012, 8, 29, 10, 0);
long endTime = cal.getTimeInMillis();
long currentTime = System.currentTimeMillis();
long remaining = currentTime - endTime;
long hours = remaining / 3600000;
long mins = remaining / 60000 % 60;
long seconds = remaining / 1000 % 60;
long days = hours / 24;
String remainingText = String.valueOf(days) + " days";
Log.i("countdown",String.valueOf(days));
tv.setText("Days left: " + days);
}
public void onFinish() {
Log.i("countdown","CD Finished");
tv.setText("CD Finished!");
}
}.start();
}
Note that the textbox value is just for testing right now, but i can't seem to get it to display the countdown.
Also is this the best approach?
Here are the values of the variables if I run your code:
endTime = 1348902045437
currentTime = 1340645325437
remaining = -8256720000
seconds = 0
as you see seconds == 0, and this is the reason.
Also note that the first argument in the CountDownTimer(long millisInFuture, long countDownInterval) constructor is
The number of millis in the future from the call to start() until the
countdown is done and onFinish() is called.
So a fixed code would be:
Calendar cal = Calendar.getInstance();
cal.set(2012, 8, 29, 10, 0);
long endTime = cal.getTimeInMillis();
long currentTime = System.currentTimeMillis();
long remaining = endTime - currentTime;
new CountDownTimer(remaining, 1000) {
...
UPDATE:
It is odd it does not update the text view. The only idea I can propose is to run update calls on the main UI thread. It should be something like this:
public void onTick(long millisUntilFinished) {
final String days = .. // some code to generate days
getActivity().runOnUiThread(new Runnable() {
public void run() {
tv.setText("Days left: " + days);
}
});
}
public void onFinish() {
Log.i("countdown","CD Finished");
getActivity().runOnUiThread(new Runnable() {
public void run() {
tv.setText("CD Finished!");
}
});
}
If this doesn't help - then I'm out of ideas.
Please include the nanos, otherwise it would be trivial:
long diff = Math.abs(t1.getTime () - t2.getTime ());
[EDIT] I want the most precise result, so no doubles; only integer/long arithmetic. Also, the result must be positive. Pseudo code:
Timestamp result = abs (t1 - t2);
Examples:
t1 = (time=1001, nanos=1000000), t2 = (time=999, nanos=999000000)
-> diff = (time=2, nanos=2000000)
Yes, milliseconds in java.sql.Timestamp are duplicated in the time and the nanos par, so 1001 milliseconds means 1 second (1000) and 1 milli which is in the time part and the nanos part because 1 millisecond = 1000000 nanoseconds). This is much more devious than it looks.
I suggest not to post an answer without actually testing the code or having a working code sample ready :)
After one hour and various unit tests, I came up with this solution:
public static Timestamp diff (java.util.Date t1, java.util.Date t2)
{
// Make sure the result is always > 0
if (t1.compareTo (t2) < 0)
{
java.util.Date tmp = t1;
t1 = t2;
t2 = tmp;
}
// Timestamps mix milli and nanoseconds in the API, so we have to separate the two
long diffSeconds = (t1.getTime () / 1000) - (t2.getTime () / 1000);
// For normals dates, we have millisecond precision
int nano1 = ((int) t1.getTime () % 1000) * 1000000;
// If the parameter is a Timestamp, we have additional precision in nanoseconds
if (t1 instanceof Timestamp)
nano1 = ((Timestamp)t1).getNanos ();
int nano2 = ((int) t2.getTime () % 1000) * 1000000;
if (t2 instanceof Timestamp)
nano2 = ((Timestamp)t2).getNanos ();
int diffNanos = nano1 - nano2;
if (diffNanos < 0)
{
// Borrow one second
diffSeconds --;
diffNanos += 1000000000;
}
// mix nanos and millis again
Timestamp result = new Timestamp ((diffSeconds * 1000) + (diffNanos / 1000000));
// setNanos() with a value of in the millisecond range doesn't affect the value of the time field
// while milliseconds in the time field will modify nanos! Damn, this API is a *mess*
result.setNanos (diffNanos);
return result;
}
Unit tests:
Timestamp t1 = new Timestamp (0);
Timestamp t3 = new Timestamp (999);
Timestamp t4 = new Timestamp (5001);
// Careful here; internally, Java has set nanos already!
t4.setNanos (t4.getNanos () + 1);
// Show what a mess this API is...
// Yes, the milliseconds show up in *both* fields! Isn't that fun?
assertEquals (999, t3.getTime ());
assertEquals (999000000, t3.getNanos ());
// This looks weird but t4 contains 5 seconds, 1 milli, 1 nano.
// The lone milli is in both results ...
assertEquals (5001, t4.getTime ());
assertEquals (1000001, t4.getNanos ());
diff = DBUtil.diff (t1, t4);
assertEquals (5001, diff.getTime ());
assertEquals (1000001, diff.getNanos ());
diff = DBUtil.diff (t4, t3);
assertEquals (4002, diff.getTime ());
assertEquals (2000001, diff.getNanos ());
I use this method to get difference between 2 java.sql.Timestmap
/**
* Get a diff between two timestamps.
*
* #param oldTs The older timestamp
* #param newTs The newer timestamp
* #param timeUnit The unit in which you want the diff
* #return The diff value, in the provided time unit.
*/
public static long getDateDiff(Timestamp oldTs, Timestamp newTs, TimeUnit timeUnit) {
long diffInMS = newTs.getTime() - oldTs.getTime();
return timeUnit.convert(diffInMS, TimeUnit.MILLISECONDS);
}
// Examples:
// long diffMinutes = getDateDiff(oldTs, newTs, TimeUnit.MINUTES);
// long diffHours = getDateDiff(oldTs, newTs, TimeUnit.HOURS);
In what units? your diff above will give milliseconds, Timestamp.nanos() returns an int, which would be in (millionths?) of a millisecond.So do you mean e.g.
(t1.getTime () + (.000001*t1.getNanos()) - (t2.getTime () + (.000001*t2.getNanos())
or am I missing something? Another question is do you need this level of precision? AFAIK the JVM isn't guaranteed to be precise at this level, I don't think it'd matter unless you're sure your datasource is that precise.
Building on mmyers code...
import java.math.BigInteger;
import java.sql.Timestamp;
public class Main
{
// 1s == 1000ms == 1,000,000us == 1,000,000,000ns (1 billion ns)
public final static BigInteger ONE_BILLION = new BigInteger ("1000000000");
public static void main(String[] args) throws InterruptedException
{
final Timestamp t1;
final Timestamp t2;
final BigInteger firstTime;
final BigInteger secondTime;
final BigInteger diffTime;
t1 = new Timestamp(System.currentTimeMillis());
Thread.sleep(20);
t2 = new Timestamp(System.currentTimeMillis());
System.out.println(t1);
System.out.println(t2);
firstTime = BigInteger.valueOf(t1.getTime() / 1000 * 1000).multiply(ONE_BILLION ).add(BigInteger.valueOf(t1.getNanos()));
secondTime = BigInteger.valueOf(t2.getTime() / 1000 * 1000).multiply(ONE_BILLION ).add(BigInteger.valueOf(t2.getNanos()));
diffTime = firstTime.subtract(secondTime);
System.out.println(firstTime);
System.out.println(secondTime);
System.out.println(diffTime);
}
}
(old code removed to shorten answer)
EDIT 2: New code:
public class ArraySizeTest {
public static void main(String[] args) throws InterruptedException {
Timestamp t1 = new Timestamp(System.currentTimeMillis());
t1.setNanos(t1.getNanos() + 60);
Thread.sleep(20);
Timestamp t2 = new Timestamp(System.currentTimeMillis());
t2.setNanos(t2.getNanos() + 30);
System.out.println(t1);
System.out.println(t2);
// The actual diff...
long firstTime = (getTimeNoMillis(t1) * 1000000) + t1.getNanos();
long secondTime = (getTimeNoMillis(t2) * 1000000) + t2.getNanos();
long diff = Math.abs(firstTime - secondTime); // diff is in nanos
System.out.println(diff);
System.out.println(Math.abs(t1.getTime() - t2.getTime()));
}
private static long getTimeNoMillis(Timestamp t) {
return t.getTime() - (t.getNanos()/1000000);
}
}
Output:
2009-02-24 10:35:15.56500006
2009-02-24 10:35:15.59600003
30999970
31
Edit 3: If you'd prefer something that returns a Timestamp, use this:
public static Timestamp diff(Timestamp t1, Timestamp t2) {
long firstTime = (getTimeNoMillis(t1) * 1000000) + t1.getNanos();
long secondTime = (getTimeNoMillis(t2) * 1000000) + t2.getNanos();
long diff = Math.abs(firstTime - secondTime); // diff is in nanoseconds
Timestamp ret = new Timestamp(diff / 1000000);
ret.setNanos((int) (diff % 1000000000));
return ret;
}
private static long getTimeNoMillis(Timestamp t) {
return t.getTime() - (t.getNanos()/1000000);
}
This code passes your unit tests.