I know it may seems easy but i'm really new on Java , So i need your help.
I want to use local time (Mill Seconds) to trigger an action, for example printing "Hello world".
More specific, Print "Hello world" at "13:10:30:300" . but i don't know what specific class should i use (Data,Local Time , etc) so i can compare it to Desired Time in a while loop.
I tried this, but it's not working on milliseconds.
import java.time.format.DateTimeFormatter;
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm:ss:ms");
LocalDateTime now = LocalDateTime.now();
LocalDateTime desire = 13:10:30.300;
while (now != desire ) {
LocalDateTime now = LocalDateTime.now();
}
System.out.println("Hello World!");
Do you have any suggestion please?
Your main problem is this: now != desire. This compares whether these objects are the same, not whether their contents are the same. To compare if the times are the same, you should use now.equals(desire).
Your second problem is that this this loop might become infinite if between 2 checks now becomes greater than desire.
Your third problem is that you are wasting CPU cycles constantly checking the time. You should calculate how many milliseconds your desired time is away and sleep until then. So something like: Thread.sleep(desireMillis - nowMillis)
Related
Have such a simple Java class:
public static void main(String[] args) {
LocalDateTime dateTime = LocalDateTime.of(2017, 11, 26, 15, 38);
Period period = Period.ofYears(1).ofMonths(2).ofDays(3);
dateTime = dateTime.minus(period);
System.out.println(dateTime);
}
}
Which results in 2017-11-23T15:38
Can someone explain me, why a date is subtracted while year and months - doesn't?
Because each three method
(ofYears(1) & ofMonths(2) & ofDays(3))
returns an instance of Period class
Each time you call another method value in Period period gets overriden.
If say ofYears(1) return instance of Period class named a then ofMonths(2) also return a new instance and override he initial one. So, the last one remains and stored to the period variable.
That's why only the ofDays(3) is showing effect.
If you want to do the same you should try calling below method
`public static Period of(int years,
int months,
int days)
It is simple.
Each of the methods, ofYears, ofMonths and ofDays return a new instance of period.
So effectively your period is equal to Period.ofDays(3)
This is not a builder pattern, where you keep modifying the same instance.
In order to achieve what you need, this code will do the work:
LocalDateTime dateTime = LocalDateTime.of(2017, 11, 26, 15, 38);
Period period = Period.of(1, 2, 3);
dateTime = dateTime.minus(period);
System.out.println(dateTime);
prints out
2016-09-23T15:38
Because it works like Period.ofDays(3) overridden every time since they are static method.
Use Period of(int years,int months,int days)
dateTime = dateTime.minus(Period.of(1, 2, 3));
Or you can use withDays, withMonths, withYears like for chaining
Give a Man a Fish, and You Feed Him for a Day. Teach a Man To Fish,
and You Feed Him for a Lifetime.
(It certainly goes for a woman too.)
I am trying to teach you to fish. I am explaining how to catch such an error without having to ask on Stack Overflow first.
Set up your IDE to warn you when you use an object (an instance) for calling a static method. That is whenever you do something like
yourObject.someStaticMethod();
In my Eclipse your code gives this warning:
The static method ofDays(int) from the type Period should be accessed
in a static way
This tells us that ofDays() is a static method, and therefore the result of the call is the same as calling Period.ofDays(3). Eclipse even offers to fix the problem for me:
After I click “Change access to static using Period (declaring type)”, that code line becomes:
Period.ofYears(1).ofMonths(2);
Period period = Period.ofDays(3);
Now I think you can see why you got the result you got.
So:
Make sure your IDE is configured to issue such warnings. It doesn’t have to be Eclipse, other IDEs can do the same.
Read those warnings when you get them and make sure you understand them. If you've skipped a warning once, if you get an unexpected result, go back and read the warning again. If you still need to ask on Stack Overflow, you're welcome of course, and consider including the text of that warning you didn't understand.
Others have nicely explained how to fix your code to give you your desired result. If Period.of(1, 2, 3) is a bit confusing because you can't tell what's years, months weeks and days, use Period.ofYears(1).plusMonths(2).plusDays(3), and everything is clear. It also resembles what you tried in the question.
Link: How to debug small programs with many tips similar to the one I am giving here (and not because yours was a poor question, it’s a good one, I upvoted it).
Remember that all classes in the java.time package are immutable (see Java Docs). Instances of Period cannot be changed after creation, you will have to create a new instance and reassign it.
This is the reason why only the last Period.ofDays(3) has an effect on the result (as previous answers suggest). And it is also the reason why withDays returns a copy of the respective Period.
Initial time=22:00:00,final time=23:59:59.
If the current time is, let's say 23:00:00 then I will get the success message otherwise error message will be shown. And I am comparing this time with the system time.
My code:
//retrieving the system time in string format
SimpleDateFormat sdfDate = new SimpleDateFormat("HH:mm:ss");
Date date = new Date();
String s=sdfDate.format(date);
//Initial and final predefined time
String ten ="22:00:00";
String twelve ="23:59:59";
//comparing with the system time
try{
if(s.compareTo("twelve")<0 && s.compareTo("ten")>0 ){
out.print("success");
}else{
out.print("failed");
}
}catch(Exception l){
System.out.println(l.toString());
}
I tried to check it when the system time was 23:45:00. I also confirmed the time by printing out.print(""+s);. But I got the failed message. I don't know my loop is working or not.
What can I do to fix this?
If you're comparing hours, don't use strings, use a proper type.
In Java you have:
Java >= 8: java.time.LocalTime
Java <= 7: org.threeten.bp.LocalTime (from external lib: http://www.threeten.org/threetenbp/)
In both you can do:
LocalTime ten = LocalTime.parse("22:00:00");
LocalTime twelve = LocalTime.parse("23:59:59");
// current time
LocalTime now = LocalTime.now();
// compare
if (now.isBefore(twelve) && now.isAfter(ten)) {
// succcess
}
To get the current time, you could also use the now method with a timezone (example: LocalTime.now(ZoneId.of("America/New_York"))), if you need the time at some specific place (now() without arguments will use the JVM default timezone).
Transforming the strings to a type that represents the data you're working with is much more reliable. Also note that this API makes the code much easier and more readable, with meaningful methods names such as isAfter and isBefore.
Comparing strings might work, but using the proper types works even better.
Try this:
if(s.compareTo(twelve) < 0 && s.compareTo(ten) > 0)
By putting quotes around twelve and ten, you're comparing to the strings "twelve" and "ten", and not referencing the variables twelve and ten that you defined ealier in the program.
I have written the following Java code:
Calendar now = Calendar.getInstance();
now.setTime(new Date());
Date currentDate = null;
while (now.compareTo(stop) < 0 ) {
currentDate = new Date();
now.setTime(currentDate);
}
that is meant to track down the time passing while other components (in particular: a Twitter Streaming listener) perform other actions. So, this is not meant to be a simple sleep, since other components are running in the meanwhile: this loop is just meant to keep the machine occupied for a while, until the date indicated by stop arrives.
However, by doing this the memory size keeps increasing a lot. I profiled the thing and I saw that this generates a huge amount of Date objects in memory.
Is there a smarter way of doing this?
Thank you in advance.
The minimum change is to use setTimeInMillis using System.currentTimeMillis rather than setTime:
while (now.compareTo(stop) < 0 ) { // Ugh, busy wait, see below
now.setTimeInMillis(System.currentTimeMillis());
}
...or actually, just use milliseconds in the first place:
long stopAt = stop.getTimeMillis();
while (System.currentTimeMillis() < stopAt) { // Ugh, busy wait, see below
}
However, surely with broader context there's a way to avoid busy-waiting at all. Busy-waits are almost never appropriate.
So, this is not meant to be a simple sleep, since other components are running in the meanwhile: this loop is just meant to keep the machine occupied for a while, until the date indicated by stop arrives.
Presumably those components are running on other threads, as your while loop is a busy-wait.
That being the case, this thread should sleep — either for a period of time, or until it's woken up by something else.
For instance, you haven't said what stop is, but as you're using it with compareTo presumably it's a Calendar. So it should be possible to get the difference (in milliseconds, via getTimeInMillis) between stop and now, and sleep rather than busy-waiting:
Calendar now = Calendar.getInstance(); // Initializes to "now", no need to do that yourself
long delay = stop.getTimeInMillis() - now.getTimeInMillis();
if (delay > 0) {
Thread.sleep(delay);
}
I want to have my application execute code at a point in the future.
I want to do:
Date now = new Date();
for (Date beep : scheduledBeeps) {
if (beep.after(now))
{
Logger.i("adding beep");
m_beepTimer.postAtTime(beepNow, beep.getTime());
}
}
In the log I can see 4 beeps added, however they never fire. I'm assuming it has something to do with uptimeMillis, but I'm not sure what to do.
You will have to get the difference between now and beep.gettime() and pass it to postattime function. Since uptime is used as base, it may not be accurate if the phone goes to deep sleep.
beep.gettime - now + SystemCLock.uptimeMillis()
should be passed to postattime function
You are currently passing a very large number equivalent to current milliseconds from jan 1 1970.
You could use the Calendar class to set a certain point in time.
Calendar beepTime = Calendar.getInstance();
beepTime.set(Calendar.DAY_OF_MONTH, 2);
beepTIme.set(Calendar.HOUR_OF_DAY, 01);
beepTime.set(Calendar.MINUTE, 55);
beepTime.set(Calendar.SECOND, 00);
getInstance will set it to the current time, and you can change any variable you like, such as the ones above. For example this would create a time at 1:55 on the 2nd of the current month. You would then set this to be the time to go off with
beepTime.getTimeInMillis()
just pop that into your postAtTime method
Edit: Also I don't know enough about your problem to say for sure, but it may be better to use AlarmManager. I know that that still works even if the program is not running, whereas I don't think PostDelayed does. Feel free to correct me if I'm wrong!
Is there a better way of doing this?
boolean oneCalendarWeek = interval.getStart().plusWeeks(1).equals( interval.getEnd() );
I guess the following won't work because of the way equals is implemented...
boolean oneCalendarWeek = interval.toPeriod().equals( Weeks.ONE );
From the comments:
i really want to know if the api supports something like my second example which i think is clearer than the first
While the example using Weeks.ONE does not work (since Period.equals() first checks if the two Period instances support the same number of fields, and Weeks.ONE only supports one field), this should work instead:
boolean oneCalendarWeek = interval.toPeriod().equals( Period.weeks(1) );
Here is a code sample that tests this for an interval that starts before the start of DST and ends while in DST. However, I'm not 100% sure how this would behave if the start or end time of the Interval fell exactly on the DST boundary.