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();
}
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.
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.
This question already has answers here:
See if the current time falls within a specific range of time in the current day in Java
(6 answers)
Closed 6 years ago.
I am working on something where I need the user to input values in to the Terminal Window such as:
Start Time: 0800
End Time: 1200
Then I need to check if this person's start and end time fall within a range. So if the working hours are 0900 - 1700 and it is now 11:45 the above user would be shown as available, whereas if it was 1201 the above user would be unavailable.
Currently I just pull the times in as a string:
void setWorkHours(String hrs)
{
this.hours=hrs;
}
public String getWorkHours()
{
return hours;
}
Any help much appreciated.
Cheers
It would be better if the user could input a start date and time and an end date and time. This would allow a user to enter their entire week at one time.
Nevertheless, the solution is pretty much the same.
Convert the start time (date / time) to a Calendar instance.
Convert the end time (date / time) to a Calendar instance.
Use the Calendar after and before methods to determine if the time (date / time) entered is in between the start time and end time.
I am not going to do your homework for you, but I'll offer you the following suggestions:
You are going to need to get your input from the terminal (look at System.in)
You are going to need to parse the input. To do this, you need to decide what is valid input. "0800", "08:00", "08.00", "8:00", "8:00 AM", "07:60", "eight o'clock"... which of these are valid, and which will you reject? What is your error handling strategy? Just blow up the application, or provide a nice message to the user?
What datatype are you doing to parse the input into? You might have four ints: startHours, startMins, endHours, endMins. Or maybe you will use Java's Date or Calendar object. There are other options, you need to pick the one that works best for you.
Do you care about seconds? Milliseconds?
Once you have parsed the office hours, you will need some method that given a time determines whether you are inside or outside hours. Presumably this is a separate input. You'll need to parse it (hint, use a utility method for the parsing, and reuse it here), and then pass it to a method that does some calculation. Something like bool isInOfficeHours(int hours, in mins). The parameters to this method should probably match the datatype you're using to store the office hours.
I hope this helps you.
Below is the code that will take two strings in startTime and endTime and will compare to range objects you will have to define your range whatever you like. I have placed comments to explain the code.
/*
* this method will split hhmm time into two parts.
*/
public String[] getTimeHHMM(String time){
String hhmm[] = new String[2];
if(time !=null && time.length() > 1){
hhmm[0] = time.substring(0, time.length() - 2);
hhmm[1] = time.substring(time.length() - 2, time.length());
}
else{
// time not formatted correctly so deal with here
hhmm[0] = "";
hhmm[1] = time;
}
return hhmm;
}
//assuming hrs is a string containing only one time in the format hhmm
String startTime[] = getTimeHHMM(startTimeStr);
String endTime[] = getTimeHHMM(endTimeStr);
int startTimeHrs = Integer.parseInt(startTime[0]);
int startTimeMins = Integer.parseInt(startTime[1]);
int endTimeHrs = Integer.parseInt(endTime[0]);
int endTimeMins = Integer.parseInt(endTime[1]);
Date start = new Date();
Date end = new Date();
Calendar start = Calendar.getInstance();
start.set(Calendar.HOUR_OF_DAY, startHrs);
start.set(Calendar.MINUTE, startMins );
Calendar end = Calendar.getInstance();
end.set(Calendar.HOUR_OF_DAY, endHrs);
end.set(Calendar.MINUTE, endMins );
///lets say the range is startRange and endRange it should be Calendar instances, you will need to construct these as I did above with setting your range whatever you like
Calendar endRange;
Calendar startRange;
if(start.compareTo(startRange) >= 0 && end.compareTo(endRange) <=0 ){
// Here it means it is within working hours
}
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!
In my android program I am using two Calendar instances to get the elapsed time in my program, first I set a level starting time as follows:
level_Start_TimeCal = Calendar.getInstance();
and in my thread I am calculating elapsed time as follows:
level_current_TimeCal = Calendar.getInstance();
gameTime = level_current_TimeCal.getTimeInMillis()- level_Start_TimeCal.getTimeInMillis();
dsecs = (gameTime / 1000)%60;
dminutes = (gameTime / (60 * 1000))%60;
dhours = (gameTime / (60 * 60 * 1000))%60;
Recently I came to read the following:
Calendar's getInstance method returns a Calendar object whose calendar
fields have been initialized with the current date and time
I want to know if I am in right path?
Am I creating an object each time the thread running?
If yes is there any alternative to avoid creating unwanted objects and calculating elapsed time?
Final question: at some point I want to reset the time in my restart method I reset it by just calling getInstance in my reset method as follows:
public void restart() {
level_Start_TimeCal = Calendar.getInstance();
}
Is this the correct way to reset the Calendar?
The best way to calculate elapsed time is to use System.nanotime().
long start = System.nanoTime();
//do something
long end = System.nanoTime();
//to get the elapsed time, you can use the TimeUnit utility methods:
long elapsedInNanos = end - start;
long elapsedInSeconds = TimeUnit.SECONDS.convert(elapsedInNanos, TimeUnit.NANOSECONDS);
Note that it is not a useful method to access absolute time.