I have created a simple application to do exercises and rehearsals in general, I'm trying trying to update a variable every second but I can't find a working way.
The code is this:
long milliSec = SystemClock.elapsedRealtime();
String upTime = String.format(Locale.getDefault(),
"%02d giorni, %02d:%02d:%2d",
TimeUnit.MILLISECONDS.toDays(milliSec),
TimeUnit.MILLISECONDS.toHours(milliSec) - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(milliSec)),
TimeUnit.MILLISECONDS.toMinutes(milliSec) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(milliSec)),
TimeUnit.MILLISECONDS.toSeconds(milliSec) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(milliSec)));
The upTime variable I am putting in an array of strings. Can anyone kindly help me overcome this little obstacle?
Thanks a lot to everyone :)
I am not sure what exactly is your question.
You have the system uptime rather than the current time
You want to update a variable every second.
You store the updated variable in an array of strings.
Which of the three do you want to change?
Format the current time into a readable string using SimpleDateFormat.
Format the uptime using Instant and Duration like
Instant startTime = Instant.now(); // to this once on application start
Duration d = Duration.between(startTime, Instant.now()); // do this evey second
String s = String.format("%s days and %sh %sm %ss", duration.toDays(),
duration.toHours() - TimeUnit.DAYS.toHours(duration.toDays()),
duration.toMinutes() - TimeUnit.HOURS.toMinutes(duration.toHours()),
duration.getSeconds() - TimeUnit.MINUTES.toSeconds(duration.toMinutes()));
Remaining is to execute the code every second. I recommend placing this code inside a Runnable:
Instant startTime = Instant.now();
while (true) {
Duration duration = Duration.between(startTime, Instant.now());
String s = String.format("%s days and %sh %sm %ss", duration.toDays(),
duration.toHours() - TimeUnit.DAYS.toHours(duration.toDays()),
duration.toMinutes() - TimeUnit.HOURS.toMinutes(duration.toHours()),
duration.getSeconds() - TimeUnit.MINUTES.toSeconds(duration.toMinutes()));
// place the string wherever you need it
Thread.sleep(1000);
}
then have it running in a background thread. It will not exactly go every second but the reported uptime will be dead right.
Related
I'm trying to find the difference between current time value and a future time in HH:MM:SS format.
For example:
When date1 is "2017-05-11T20:30" and date2 is "2017-05-11T21:40", the output should be 01:10:00.
Here's the code I'm trying, wherein I'm trying to find the difference between current time and a future time value:
public void updateTimeRemaining() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm");
String currentTime = simpleDateFormat.format(new Date());
long difference = simpleDateFormat.parse(endTime).getTime() - simpleDateFormat.parse(currentTime).getTime();
if (difference>0) {
String hms = String.format("%02d:%02d:%02d", millisLeft/(3600*1000),
millisLeft/(60*1000) % 60,
millisLeft/1000 % 60);
textView.setText(hms); //setting the remaining time in a textView
}
}
I'm invoking the method updateTimeRemaining() every second so that the textview gets updated every second like a timer. The problem I'm facing is seconds value always returns 0. Instead I would like the seconds value to be updated every second like below:
01:50:45
01:50:44
01:50:43
01:50:42...
You could use
difference = simpleDateFormat.parse(endTime).getTime() - new Date().getTime();
in place of these lines of your code:
String currentTime = simpleDateFormat.format(new Date());
long difference = simpleDateFormat.parse(endTime).getTime() - simpleDateFormat.parse(currentTime).getTime();
This should work fine.
You can use CountDownTimer. Here is an example :
new CountDownTimer(30000, 1000) { // 30 seconds countdown
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
The Constructor is : CountDownTimer(long millisInFuture, long countDownInterval)
You are performing a subtraction of two values and taking action if the result is greater than 0. Since it is not, it means endTime is necessarily not in the future but is before currentTime.
Fix your endTime problem.
I got three suggestions.
To me the natural suggestion is you use the classes in java.time. They are much nicer to work with than the outdated Date and SimpleDateFormat that are built-in with your Android Java.
long endMillis = LocalDateTime.parse(endTime,
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm"))
.atZone(ZoneId.systemDefault())
.toInstant()
.toEpochMilli();
long difference = endMillis - System.currentTimeMillis();
The rest will be the same as in your code. To use LocalDateTime and DateTimeFormatter on Android you will need to get ThreeTenABP, it contains the classes.
I wish I could tell you to use Duration, another one of the newer classes. However, Duration doesn’t seem to lend itself well to formatting. This will change with Java 9 (not tested):
LocalDateTime endDateTime = LocalDateTime.parse(endTime,
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm"));
Duration diff = Duration.between(LocalDateTime.now(ZoneId.systemDefault()),
endDateTime);
if (! diff.isNegative()) {
String hms = String.format("%02d:%02d:%02d",
diff.toHoursPart(),
diff.toMinutesPart(),
diff.toSecondsPart());
textView.setText(hms); //setting the remaining time in a textView
}
Isn’t that beautiful and clear?
If you don’t want the dependency on ThreeTenABP, there is of course a fix to your code. It’s even a simplification. In your code you are formatting the new Date() that you are getting the current time from, without seconds, so they get lost, and then parsing it again, and finally getting its milliseconds since the epoch. Skip all of that and just get the current time from System.currentTimeMillis() just as in the first snippet above:
long difference = simpleDateFormat.parse(endTime).getTime()
- System.currentTimeMillis();
This will give you your seconds.
My english is not perfect, but I hope you can understand me.
I try to get the difference in seconds between two unix timestamps, but it's only return 0.
That's my code
unixOnline = Long.valueOf(online);
unixOffline = Long.valueOf(offline);
DateTimeZone BERLIN = DateTimeZone.forID("Europe/Berlin");
DateTime dateTimeOnline = new DateTime(unixOnline * 1000L, BERLIN);
DateTime dateTimeOffline = new DateTime(unixOffline * 1000L, BERLIN);
int seconds = Seconds.secondsBetween(new LocalDate(dateTimeOnline), new LocalDate(dateTimeOffline)).getSeconds();
System.out.println("Seconds: " + seconds);
Edit:
Online Timestamp: 1457536522
Offline Timestamp: 1457536642
LocalDate has no time component, so if the times are on the same day, they're effectively turned into the same time. Instead, just diff the DateTimes as they are;
int hours = Hours.hoursBetween(dateTimeOnline, dateTimeOffline).getHours();
(or in your case, since the difference is only 2 minutes, you'll only see the result with Minutes or Seconds)
EDIT: Since the question seems to have nothing to do with the time zone BERLIN which is in the code, this answer is a bit over complicated. Instead, use krzydyn's answer if it's just a time diff between UTC times.
Since you already have timestamps in seconds it can be simple calculated by formula:
int hours = (t2-t1)/3600;
Or if you need fractions:
float hours = (t2-t1)/3600f;
Update: (maybe I got suggested by the answer :)
So to get time diff in seconds is even simpler:
long seconds = t2-t1;
I am using Java Timer class for running certain task. For my program I will give starttime and endtime as parameters which will ask the java timer when to start and when to end the task.
While running my task, I want to get and check the difference between current time and endtime periodically and If current time equals endtime then cancel the task by calling timer.cancel() method.
My startTime and endTime parrameters time format are like this
String startTime = "12:00";
String endTime = "12:01";
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
Date date1 = format.parse(startTime);
Date date2 = format.parse(endTime);
long difference = date2.getTime() - date1.getTime();
I want to check the current time is equal to endtime.
But I want to check the condition that the current time is equal to end time and call the timer.cancel()
May be, you just don't know how to get the endTime.
String startTime = "12:00";
SimpleDateFormat sDateFormat = new SimpleDateFormat(
"hh:mm");
String endTime = sDateFormat.format(new java.util.Date());
if (startTime.equals(endTime)) {
timer.cancel();
}
try, and good luck
It may not be the time problem..
If comparing two Strings, you'd better use equals()
Try this :
if(currentTime.equals(endTime)) {
timer.cancel();
}
You should use the "currentTime.equals(endTime)" function to compare strings, not the == operator.The ".equals" function checks the actual contents of the string, the == operator checks whether the references of both the objects are equal which is not valid in your case.
You want to check if the current time is equal to the end time - that is understood but to what level do you wish to check if it is equal - up to the minute, second or millisecond? Since if you compare by the millisecond or lower it is possible that you may never cancel even when the time may be same to the second.
If you want to check to the millisecond - just convert your end date to millis date.getTime() and subtract System.currentTimeMillis() - if the result is 0 it is same to the millisecond. If the difference is less than 1000 (1 * 1000) it is within the second. If it is less than 60000 (1 * 60 * 1000) it is within the minute.
I need to write a method that can only execute once every 24 hours. It grabs a string, called "lastCollection", then should parse it to some sort of time object. It should then get the current time, and check if it has a 24 hour difference from "lastcollection". If so, it should execute some code, and set lastCollection to a new readable time string. Whats the best way to go about doing this?
Is this called by something or is this something that needs to be ran once every 24 hours?
If Possible you can just sleep it. I'll need a code example to show you how to fit it in but.
In case of once a day On a Schedule
Get Time at start of method.
Perform Method
Get New Time
Get Difference in Start Time and Current Time
Sleep the remainder of the time until same start time of the next day.
OR
Need to check before Performing
Get Time at start of method save to variable
Every time this method is called check a difference in a value say Minutes(see below)
If it is greater than 24 then repeat the method
Date Diffs can be done like this:
Date lasttimeran = null;
Date now = null;
long diff = now.getTime() - lasttimeran.getTime();
long diffMinutes = diff / (60 * 1000);
//If block to check if it has been long enough >= ensures a diff of exactly 24 hours will still trigger the method to be ran
if (diffMinutes >= 1440) {
//Do Something
}
else{
//Do Nothing
}
Calendar expCal = Calendar.getInstance();
while (true) {
expCal.add(Calendar.HOUR, 24);
Date expirationDate = expCal.getTime();
Date currentDate = new Date();
if (currentDate.compareTo(expirationDate) == 0)
//Do your Work here
expCal = Calendar.getInstance();
}
I have the following code that normally would take some instances of time, convert them to milliseconds to make some fairly precise computations, and produce the equivalent day(s) between those times OR hour(s) between them as the case may be. I think the code best explains what I am trying to achieve. Following are some snippets...
private int hours = 0;
/* This is intended to get the days between 'startDate' and 'endDate'
* and ensure it is between zero & the specified 'range' of days, inclusive*/
public int getPeriodBtw(Date startDate, Date endDate, int range)
{
int daysBtw = 0;
Calendar constantDate = Calendar.getInstance();
constantDate.setTime(startDate);
Calendar currentDate = Calendar.getInstance();
currentDate.setTime(endDate);
long rangePeriod = Period.ConvertDaysToMillis(range);
long duration = (constantDate.getTimeInMillis() + rangePeriod) - currentDate.getTimeInMillis();
daysBtw = (int)Period.ConvertMillisToDays(duration);
if(duration >= 0 && duration <= rangePeriod)
{
if(daysBtw == 0){
hours = (int)Period.ConvertMillisToHours(duration);
}
}
return daysBtw;
}
Now, the logic above seems all knit tight and good to me, but surprisingly, I get odd results as currentDate changes. I mean, normally I would expect something like this... See the following Illustration;
If constantDate = 10:00am
If range = 1 day starting from constantDate
and lets say currentDate = 2:00pm on the same day (i.e within range),
then daysBtw should return = 0
hours between constantDate and currentDate is 4hrs
Now this means currentDate is 4hrs Less range,
Thus duration should be 1day(24hrs) - 4hrs = 20hrs
Of course I think handling this in Millisecond offset from epoch wld be something like so;
10:00am(millis) + 1day(millis) - 2:00pm(millis) = 20hrs
long duration = (constantDate.getTimeInMillis() + rangePeriod) - currentDate.getTimeInMillis();
hours = (int)Period.ConvertMillisToHours(duration);
so hours should return = 20
Now, if currentDate changes to 3:00pm, following the same logic previously described, shouldn't hours = 19???... Problem is, my program gets hours = 21 instead.
I've been really confused as to what I might be doing wrong. Is the problem with my Logic???... Or is it somewhere in my Code???... I feel terribly bad admitting that I've spent a few hours on and off this thing that I know is rather simple, But time is not my friend as usual, and I have to move on to things less trivial. Any form of help would be highly appreciated. Thanks Y'all!
Okay... I did find a solution to this issue earlier on... Turned out it was due to;
1. some bad logic on my side, and also
2. some loss of precision when using java.util.concurrent.TimeUnit to convet Milliseconds to Days
TimeUnit.DAYS.convert(args, TimeUnit.MILLISECONDS);
It still beats me why they had to make the convert method recieve its milliseconds argument as long and return days as long too, without creating an option to set the preferred RoundingMode.... Anyways, its been added to my short list of ( STAY-AWAY-FROM-IT ) API's. Lolz!